USB fixes for 6.15-rc4

Here are some small USB driver fixes and new device ids for 6.15-rc4.
 Nothing major in here, just the normal set of issues that have cropped
 up after -rc1:
   - new device ids for usb-serial drivers
   - new device quirks added
   - typec driver fixes
   - chipidea driver fixes
   - xhci driver fixes
   - wdm driver fixes
   - cdns3 driver fixes
   - MAINTAINERS file update
 
 All of these, except for the MAINTAINERS file update, have been in
 linux-next for a while with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaAtzuQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ynJ+gCgnnXV+nmrAvFffI5LQWlui2xOT8AAoKGt8e8v
 +FBjTEXoyXzzsbQCYBNS
 =P5vR
 -----END PGP SIGNATURE-----

Merge tag 'usb-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some small USB driver fixes and new device ids for 6.15-rc4.
  Nothing major in here, just the normal set of issues that have cropped
  up after -rc1:

   - new device ids for usb-serial drivers

   - new device quirks added

   - typec driver fixes

   - chipidea driver fixes

   - xhci driver fixes

   - wdm driver fixes

   - cdns3 driver fixes

   - MAINTAINERS file update

  All of these, except for the MAINTAINERS file update, have been in
  linux-next for a while with no reported issues"

* tag 'usb-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (27 commits)
  MAINTAINERS: Assign maintainer for the port controller drivers
  USB: serial: simple: add OWON HDS200 series oscilloscope support
  USB: serial: ftdi_sio: add support for Abacus Electrics Optical Probe
  USB: serial: option: add Sierra Wireless EM9291
  usb: typec: class: Unlocked on error in typec_register_partner()
  usb: quirks: Add delay init quirk for SanDisk 3.2Gen1 Flash Drive
  USB: wdm: add annotation
  USB: wdm: wdm_wwan_port_tx_complete mutex in atomic context
  USB: wdm: close race between wdm_open and wdm_wwan_port_stop
  USB: wdm: handle IO errors in wdm_wwan_port_start
  USB: VLI disk crashes if LPM is used
  usb: dwc3: gadget: check that event count does not exceed event buffer length
  USB: storage: quirk for ADATA Portable HDD CH94
  usb: quirks: add DELAY_INIT quirk for Silicon Motion Flash Drive
  USB: OHCI: Add quirk for LS7A OHCI controller (rev 0x02)
  usb: dwc3: xilinx: Prevent spike in reset signal
  usb: cdns3: Fix deadlock when using NCM gadget
  usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling
  usb: chipidea: ci_hdrc_imx: fix call balance of regulator routines
  usb: chipidea: ci_hdrc_imx: fix usbmisc handling
  ...
This commit is contained in:
Linus Torvalds 2025-04-25 10:48:16 -07:00
commit 2d5c7fe097
19 changed files with 167 additions and 63 deletions

View File

@ -25204,9 +25204,13 @@ S: Maintained
F: drivers/usb/typec/mux/pi3usb30532.c
USB TYPEC PORT CONTROLLER DRIVERS
M: Badhri Jagan Sridharan <badhri@google.com>
L: linux-usb@vger.kernel.org
S: Orphan
F: drivers/usb/typec/tcpm/
S: Maintained
F: drivers/usb/typec/tcpm/tcpci.c
F: drivers/usb/typec/tcpm/tcpm.c
F: include/linux/usb/tcpci.h
F: include/linux/usb/tcpm.h
USB TYPEC TUSB1046 MUX DRIVER
M: Romain Gantois <romain.gantois@bootlin.com>

View File

@ -1963,6 +1963,7 @@ static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data)
unsigned int bit;
unsigned long reg;
local_bh_disable();
spin_lock_irqsave(&priv_dev->lock, flags);
reg = readl(&priv_dev->regs->usb_ists);
@ -2004,6 +2005,7 @@ static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data)
irqend:
writel(~0, &priv_dev->regs->ep_ien);
spin_unlock_irqrestore(&priv_dev->lock, flags);
local_bh_enable();
return ret;
}

View File

@ -336,6 +336,13 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
return ret;
}
static void ci_hdrc_imx_disable_regulator(void *arg)
{
struct ci_hdrc_imx_data *data = arg;
regulator_disable(data->hsic_pad_regulator);
}
static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
struct ci_hdrc_imx_data *data;
@ -394,6 +401,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
"Failed to enable HSIC pad regulator\n");
goto err_put;
}
ret = devm_add_action_or_reset(dev,
ci_hdrc_imx_disable_regulator, data);
if (ret) {
dev_err(dev,
"Failed to add regulator devm action\n");
goto err_put;
}
}
}
@ -432,11 +446,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
ret = imx_get_clks(dev);
if (ret)
goto disable_hsic_regulator;
goto qos_remove_request;
ret = imx_prepare_enable_clks(dev);
if (ret)
goto disable_hsic_regulator;
goto qos_remove_request;
ret = clk_prepare_enable(data->clk_wakeup);
if (ret)
@ -470,7 +484,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) {
pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL;
data->override_phy_control = true;
usb_phy_init(pdata.usb_phy);
ret = usb_phy_init(pdata.usb_phy);
if (ret) {
dev_err(dev, "Failed to init phy\n");
goto err_clk;
}
}
if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM)
@ -479,7 +497,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
ret = imx_usbmisc_init(data->usbmisc_data);
if (ret) {
dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
goto err_clk;
goto phy_shutdown;
}
data->ci_pdev = ci_hdrc_add_device(dev,
@ -488,7 +506,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (IS_ERR(data->ci_pdev)) {
ret = PTR_ERR(data->ci_pdev);
dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n");
goto err_clk;
goto phy_shutdown;
}
if (data->usbmisc_data) {
@ -522,19 +540,20 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
phy_shutdown:
if (data->override_phy_control)
usb_phy_shutdown(data->phy);
err_clk:
clk_disable_unprepare(data->clk_wakeup);
err_wakeup_clk:
imx_disable_unprepare_clks(dev);
disable_hsic_regulator:
if (data->hsic_pad_regulator)
/* don't overwrite original ret (cf. EPROBE_DEFER) */
regulator_disable(data->hsic_pad_regulator);
qos_remove_request:
if (pdata.flags & CI_HDRC_PMQOS)
cpu_latency_qos_remove_request(&data->pm_qos_req);
data->ci_pdev = NULL;
err_put:
put_device(data->usbmisc_data->dev);
if (data->usbmisc_data)
put_device(data->usbmisc_data->dev);
return ret;
}
@ -556,10 +575,9 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev)
clk_disable_unprepare(data->clk_wakeup);
if (data->plat_data->flags & CI_HDRC_PMQOS)
cpu_latency_qos_remove_request(&data->pm_qos_req);
if (data->hsic_pad_regulator)
regulator_disable(data->hsic_pad_regulator);
}
put_device(data->usbmisc_data->dev);
if (data->usbmisc_data)
put_device(data->usbmisc_data->dev);
}
static void ci_hdrc_imx_shutdown(struct platform_device *pdev)

View File

@ -726,7 +726,7 @@ static int wdm_open(struct inode *inode, struct file *file)
rv = -EBUSY;
goto out;
}
smp_rmb(); /* ordered against wdm_wwan_port_stop() */
rv = usb_autopm_get_interface(desc->intf);
if (rv < 0) {
dev_err(&desc->intf->dev, "Error autopm - %d\n", rv);
@ -829,6 +829,7 @@ static struct usb_class_driver wdm_class = {
static int wdm_wwan_port_start(struct wwan_port *port)
{
struct wdm_device *desc = wwan_port_get_drvdata(port);
int rv;
/* The interface is both exposed via the WWAN framework and as a
* legacy usbmisc chardev. If chardev is already open, just fail
@ -848,7 +849,15 @@ static int wdm_wwan_port_start(struct wwan_port *port)
wwan_port_txon(port);
/* Start getting events */
return usb_submit_urb(desc->validity, GFP_KERNEL);
rv = usb_submit_urb(desc->validity, GFP_KERNEL);
if (rv < 0) {
wwan_port_txoff(port);
desc->manage_power(desc->intf, 0);
/* this must be last lest we race with chardev open */
clear_bit(WDM_WWAN_IN_USE, &desc->flags);
}
return rv;
}
static void wdm_wwan_port_stop(struct wwan_port *port)
@ -859,8 +868,10 @@ static void wdm_wwan_port_stop(struct wwan_port *port)
poison_urbs(desc);
desc->manage_power(desc->intf, 0);
clear_bit(WDM_READ, &desc->flags);
clear_bit(WDM_WWAN_IN_USE, &desc->flags);
unpoison_urbs(desc);
smp_wmb(); /* ordered against wdm_open() */
/* this must be last lest we open a poisoned device */
clear_bit(WDM_WWAN_IN_USE, &desc->flags);
}
static void wdm_wwan_port_tx_complete(struct urb *urb)
@ -868,7 +879,7 @@ static void wdm_wwan_port_tx_complete(struct urb *urb)
struct sk_buff *skb = urb->context;
struct wdm_device *desc = skb_shinfo(skb)->destructor_arg;
usb_autopm_put_interface(desc->intf);
usb_autopm_put_interface_async(desc->intf);
wwan_port_txon(desc->wwanp);
kfree_skb(skb);
}
@ -898,7 +909,7 @@ static int wdm_wwan_port_tx(struct wwan_port *port, struct sk_buff *skb)
req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
req->wValue = 0;
req->wIndex = desc->inum;
req->wIndex = desc->inum; /* already converted */
req->wLength = cpu_to_le16(skb->len);
skb_shinfo(skb)->destructor_arg = desc;

View File

@ -369,6 +369,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM },
{ USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
/* SanDisk Corp. SanDisk 3.2Gen1 */
{ USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT },
/* Realforce 87U Keyboard */
{ USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM },
@ -383,6 +386,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0904, 0x6103), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
/* Silicon Motion Flash Drive */
{ USB_DEVICE(0x090c, 0x1000), .driver_info = USB_QUIRK_DELAY_INIT },
/* Sound Devices USBPre2 */
{ USB_DEVICE(0x0926, 0x0202), .driver_info =
USB_QUIRK_ENDPOINT_IGNORE },
@ -539,6 +545,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x2040, 0x7200), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
/* VLI disk */
{ USB_DEVICE(0x2109, 0x0711), .driver_info = USB_QUIRK_NO_LPM },
/* Raydium Touchscreen */
{ USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM },

View File

@ -207,15 +207,13 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
skip_usb3_phy:
/* ulpi reset via gpio-modepin or gpio-framework driver */
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio)) {
return dev_err_probe(dev, PTR_ERR(reset_gpio),
"Failed to request reset GPIO\n");
}
if (reset_gpio) {
/* Toggle ulpi to reset the phy. */
gpiod_set_value_cansleep(reset_gpio, 1);
usleep_range(5000, 10000);
gpiod_set_value_cansleep(reset_gpio, 0);
usleep_range(5000, 10000);

View File

@ -4617,6 +4617,12 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
if (!count)
return IRQ_NONE;
if (count > evt->length) {
dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
count, evt->length);
return IRQ_NONE;
}
evt->count = count;
evt->flags |= DWC3_EVENT_PENDING;

View File

@ -165,6 +165,25 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
return 0;
}
static int ohci_quirk_loongson(struct usb_hcd *hcd)
{
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
/*
* Loongson's LS7A OHCI controller (rev 0x02) has a
* flaw. MMIO register with offset 0x60/64 is treated
* as legacy PS2-compatible keyboard/mouse interface.
* Since OHCI only use 4KB BAR resource, LS7A OHCI's
* 32KB BAR is wrapped around (the 2nd 4KB BAR space
* is the same as the 1st 4KB internally). So add 4KB
* offset (0x1000) to the OHCI registers as a quirk.
*/
if (pdev->revision == 0x2)
hcd->regs += SZ_4K; /* SZ_4K = 0x1000 */
return 0;
}
static int ohci_quirk_qemu(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@ -224,6 +243,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
.driver_data = (unsigned long)ohci_quirk_amd700,
},
{
PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a24),
.driver_data = (unsigned long)ohci_quirk_loongson,
},
{
.vendor = PCI_VENDOR_ID_APPLE,
.device = 0x003f,

View File

@ -1878,9 +1878,10 @@ int xhci_bus_resume(struct usb_hcd *hcd)
int max_ports, port_index;
int sret;
u32 next_state;
u32 temp, portsc;
u32 portsc;
struct xhci_hub *rhub;
struct xhci_port **ports;
bool disabled_irq = false;
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
@ -1896,17 +1897,20 @@ int xhci_bus_resume(struct usb_hcd *hcd)
return -ESHUTDOWN;
}
/* delay the irqs */
temp = readl(&xhci->op_regs->command);
temp &= ~CMD_EIE;
writel(temp, &xhci->op_regs->command);
/* bus specific resume for ports we suspended at bus_suspend */
if (hcd->speed >= HCD_USB3)
if (hcd->speed >= HCD_USB3) {
next_state = XDEV_U0;
else
} else {
next_state = XDEV_RESUME;
if (bus_state->bus_suspended) {
/*
* prevent port event interrupts from interfering
* with usb2 port resume process
*/
xhci_disable_interrupter(xhci->interrupters[0]);
disabled_irq = true;
}
}
port_index = max_ports;
while (port_index--) {
portsc = readl(ports[port_index]->addr);
@ -1974,11 +1978,9 @@ int xhci_bus_resume(struct usb_hcd *hcd)
(void) readl(&xhci->op_regs->command);
bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
/* re-enable irqs */
temp = readl(&xhci->op_regs->command);
temp |= CMD_EIE;
writel(temp, &xhci->op_regs->command);
temp = readl(&xhci->op_regs->command);
/* re-enable interrupter */
if (disabled_irq)
xhci_enable_interrupter(xhci->interrupters[0]);
spin_unlock_irqrestore(&xhci->lock, flags);
return 0;

View File

@ -561,8 +561,8 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
* pointer command pending because the device can choose to start any
* stream once the endpoint is on the HW schedule.
*/
if (ep_state & (EP_STOP_CMD_PENDING | SET_DEQ_PENDING | EP_HALTED |
EP_CLEARING_TT | EP_STALLED))
if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
(ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
return;
trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
@ -2573,9 +2573,6 @@ static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
xhci_handle_halted_endpoint(xhci, ep, td, EP_SOFT_RESET);
return;
case COMP_STALL_ERROR:
ep->ep_state |= EP_STALLED;
break;
default:
/* do nothing */
break;
@ -2916,7 +2913,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (xhci_spurious_success_tx_event(xhci, ep_ring)) {
xhci_dbg(xhci, "Spurious event dma %pad, comp_code %u after %u\n",
&ep_trb_dma, trb_comp_code, ep_ring->old_trb_comp_code);
ep_ring->old_trb_comp_code = trb_comp_code;
ep_ring->old_trb_comp_code = 0;
return 0;
}
@ -3780,7 +3777,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
* enqueue a No Op TRB, this can prevent the Setup and Data Stage
* TRB to be breaked by the Link TRB.
*/
if (trb_is_link(ep_ring->enqueue + 1)) {
if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->enqueue + 1)) {
field = TRB_TYPE(TRB_TR_NOOP) | ep_ring->cycle_state;
queue_trb(xhci, ep_ring, false, 0, 0,
TRB_INTR_TARGET(0), field);

View File

@ -322,7 +322,7 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
xhci_info(xhci, "Fault detected\n");
}
static int xhci_enable_interrupter(struct xhci_interrupter *ir)
int xhci_enable_interrupter(struct xhci_interrupter *ir)
{
u32 iman;
@ -335,7 +335,7 @@ static int xhci_enable_interrupter(struct xhci_interrupter *ir)
return 0;
}
static int xhci_disable_interrupter(struct xhci_interrupter *ir)
int xhci_disable_interrupter(struct xhci_interrupter *ir)
{
u32 iman;
@ -1605,11 +1605,6 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
goto free_priv;
}
/* Class driver might not be aware ep halted due to async URB giveback */
if (*ep_state & EP_STALLED)
dev_dbg(&urb->dev->dev, "URB %p queued before clearing halt\n",
urb);
switch (usb_endpoint_type(&urb->ep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
@ -1770,8 +1765,8 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
goto done;
}
/* In these cases no commands are pending but the endpoint is stopped */
if (ep->ep_state & (EP_CLEARING_TT | EP_STALLED)) {
/* In this case no commands are pending but the endpoint is stopped */
if (ep->ep_state & EP_CLEARING_TT) {
/* and cancelled TDs can be given back right away */
xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
urb->dev->slot_id, ep_index, ep->ep_state);
@ -3209,11 +3204,8 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
ep = &vdev->eps[ep_index];
spin_lock_irqsave(&xhci->lock, flags);
ep->ep_state &= ~EP_STALLED;
/* Bail out if toggle is already being cleared by a endpoint reset */
spin_lock_irqsave(&xhci->lock, flags);
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE;
spin_unlock_irqrestore(&xhci->lock, flags);

View File

@ -664,7 +664,7 @@ struct xhci_virt_ep {
unsigned int err_count;
unsigned int ep_state;
#define SET_DEQ_PENDING (1 << 0)
#define EP_HALTED (1 << 1) /* Halted host ep handling */
#define EP_HALTED (1 << 1) /* For stall handling */
#define EP_STOP_CMD_PENDING (1 << 2) /* For URB cancellation */
/* Transitioning the endpoint to using streams, don't enqueue URBs */
#define EP_GETTING_STREAMS (1 << 3)
@ -675,7 +675,6 @@ struct xhci_virt_ep {
#define EP_SOFT_CLEAR_TOGGLE (1 << 7)
/* usb_hub_clear_tt_buffer is in progress */
#define EP_CLEARING_TT (1 << 8)
#define EP_STALLED (1 << 9) /* For stall handling */
/* ---- Related to URB cancellation ---- */
struct list_head cancelled_td_list;
struct xhci_hcd *xhci;
@ -1891,6 +1890,8 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci,
struct usb_tt *tt, gfp_t mem_flags);
int xhci_set_interrupter_moderation(struct xhci_interrupter *ir,
u32 imod_interval);
int xhci_enable_interrupter(struct xhci_interrupter *ir);
int xhci_disable_interrupter(struct xhci_interrupter *ir);
/* xHCI ring, segment, TRB, and TD functions */
dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);

View File

@ -1093,6 +1093,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 1) },
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 2) },
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) },
/* Abacus Electrics */
{ USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) },
{ } /* Terminating entry */
};

View File

@ -442,6 +442,11 @@
#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */
#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */
/*
* Abacus Electrics
*/
#define ABACUS_OPTICAL_PROBE_PID 0xf458 /* ABACUS ELECTRICS Optical Probe */
/*
* Oceanic product ids
*/

View File

@ -611,6 +611,7 @@ static void option_instat_callback(struct urb *urb);
/* Sierra Wireless products */
#define SIERRA_VENDOR_ID 0x1199
#define SIERRA_PRODUCT_EM9191 0x90d3
#define SIERRA_PRODUCT_EM9291 0x90e3
/* UNISOC (Spreadtrum) products */
#define UNISOC_VENDOR_ID 0x1782
@ -2432,6 +2433,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */

View File

@ -100,6 +100,11 @@ DEVICE(nokia, NOKIA_IDS);
{ USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */
DEVICE_N(novatel_gps, NOVATEL_IDS, 3);
/* OWON electronic test and measurement equipment driver */
#define OWON_IDS() \
{ USB_DEVICE(0x5345, 0x1234) } /* HDS200 oscilloscopes and others */
DEVICE(owon, OWON_IDS);
/* Siemens USB/MPI adapter */
#define SIEMENS_IDS() \
{ USB_DEVICE(0x908, 0x0004) }
@ -134,6 +139,7 @@ static struct usb_serial_driver * const serial_drivers[] = {
&motorola_tetra_device,
&nokia_device,
&novatel_gps_device,
&owon_device,
&siemens_mpi_device,
&suunto_device,
&vivopay_device,
@ -153,6 +159,7 @@ static const struct usb_device_id id_table[] = {
MOTOROLA_TETRA_IDS(),
NOKIA_IDS(),
NOVATEL_IDS(),
OWON_IDS(),
SIEMENS_IDS(),
SUUNTO_IDS(),
VIVOPAY_IDS(),

View File

@ -83,6 +83,13 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_REPORT_LUNS),
/* Reported-by: Oliver Neukum <oneukum@suse.com> */
UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160,
"ADATA",
"Portable HDD CH94",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_ATA_1X),
/* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
"Initio Corporation",

View File

@ -1052,9 +1052,11 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner->usb_mode = USB_MODE_USB3;
}
mutex_lock(&port->partner_link_lock);
ret = device_register(&partner->dev);
if (ret) {
dev_err(&port->dev, "failed to register partner (%d)\n", ret);
mutex_unlock(&port->partner_link_lock);
put_device(&partner->dev);
return ERR_PTR(ret);
}
@ -1063,6 +1065,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
typec_partner_link_device(partner, port->usb2_dev);
if (port->usb3_dev)
typec_partner_link_device(partner, port->usb3_dev);
mutex_unlock(&port->partner_link_lock);
return partner;
}
@ -1083,12 +1086,18 @@ void typec_unregister_partner(struct typec_partner *partner)
port = to_typec_port(partner->dev.parent);
if (port->usb2_dev)
mutex_lock(&port->partner_link_lock);
if (port->usb2_dev) {
typec_partner_unlink_device(partner, port->usb2_dev);
if (port->usb3_dev)
port->usb2_dev = NULL;
}
if (port->usb3_dev) {
typec_partner_unlink_device(partner, port->usb3_dev);
port->usb3_dev = NULL;
}
device_unregister(&partner->dev);
mutex_unlock(&port->partner_link_lock);
}
EXPORT_SYMBOL_GPL(typec_unregister_partner);
@ -2041,10 +2050,11 @@ static struct typec_partner *typec_get_partner(struct typec_port *port)
static void typec_partner_attach(struct typec_connector *con, struct device *dev)
{
struct typec_port *port = container_of(con, struct typec_port, con);
struct typec_partner *partner = typec_get_partner(port);
struct typec_partner *partner;
struct usb_device *udev = to_usb_device(dev);
enum usb_mode usb_mode;
mutex_lock(&port->partner_link_lock);
if (udev->speed < USB_SPEED_SUPER) {
usb_mode = USB_MODE_USB2;
port->usb2_dev = dev;
@ -2053,18 +2063,22 @@ static void typec_partner_attach(struct typec_connector *con, struct device *dev
port->usb3_dev = dev;
}
partner = typec_get_partner(port);
if (partner) {
typec_partner_set_usb_mode(partner, usb_mode);
typec_partner_link_device(partner, dev);
put_device(&partner->dev);
}
mutex_unlock(&port->partner_link_lock);
}
static void typec_partner_deattach(struct typec_connector *con, struct device *dev)
{
struct typec_port *port = container_of(con, struct typec_port, con);
struct typec_partner *partner = typec_get_partner(port);
struct typec_partner *partner;
mutex_lock(&port->partner_link_lock);
partner = typec_get_partner(port);
if (partner) {
typec_partner_unlink_device(partner, dev);
put_device(&partner->dev);
@ -2074,6 +2088,7 @@ static void typec_partner_deattach(struct typec_connector *con, struct device *d
port->usb2_dev = NULL;
else if (port->usb3_dev == dev)
port->usb3_dev = NULL;
mutex_unlock(&port->partner_link_lock);
}
/**
@ -2614,6 +2629,7 @@ struct typec_port *typec_register_port(struct device *parent,
ida_init(&port->mode_ids);
mutex_init(&port->port_type_lock);
mutex_init(&port->partner_link_lock);
port->id = id;
port->ops = cap->ops;

View File

@ -59,6 +59,7 @@ struct typec_port {
enum typec_port_type port_type;
enum usb_mode usb_mode;
struct mutex port_type_lock;
struct mutex partner_link_lock;
enum typec_orientation orientation;
struct typec_switch *sw;