USB fixes for 5.1-rc3

Here are some small USB fixes for 5.1-rc3.
 
 Nothing major at all here, just a small collection of fixes for reported
 issues, and potential problems with error handling paths.  Also a few
 new device ids, as normal.
 
 All of these have been in linux-next with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXJ8wdQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yn4iwCeJJST7rZyr/PO5lD8nm90y6WesawAn0WR2jEZ
 TR6natKYdZq5SVfLo0y/
 =MFul
 -----END PGP SIGNATURE-----

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

Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 5.1-rc3.

  Nothing major at all here, just a small collection of fixes for
  reported issues, and potential problems with error handling paths.
  Also a few new device ids, as normal.

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (25 commits)
  USB: serial: option: add Olicard 600
  USB: serial: cp210x: add new device id
  usb: u132-hcd: fix resource leak
  usb: cdc-acm: fix race during wakeup blocking TX traffic
  usb: mtu3: fix EXTCON dependency
  usb: usb251xb: fix to avoid potential NULL pointer dereference
  usb: core: Try generic PHY_MODE_USB_HOST if usb_phy_roothub_set_mode fails
  phy: sun4i-usb: Support set_mode to USB_HOST for non-OTG PHYs
  xhci: Don't let USB3 ports stuck in polling state prevent suspend
  usb: xhci: dbc: Don't free all memory with spinlock held
  xhci: Fix port resume done detection for SS ports with LPM enabled
  USB: serial: mos7720: fix mos_parport refcount imbalance on error path
  USB: gadget: f_hid: fix deadlock in f_hidg_write()
  usb: gadget: net2272: Fix net2272_dequeue()
  usb: gadget: net2280: Fix net2280_dequeue()
  usb: gadget: net2280: Fix overrun of OUT messages
  usb: dwc3: pci: add support for Comet Lake PCH ID
  usb: usb251xb: Remove unnecessary comparison of unsigned integer with >= 0
  usb: common: Consider only available nodes for dr_mode
  usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps
  ...
This commit is contained in:
Linus Torvalds 2019-03-30 10:26:36 -07:00
commit 8d02a9a897
23 changed files with 110 additions and 37 deletions

View File

@ -485,8 +485,11 @@ static int sun4i_usb_phy_set_mode(struct phy *_phy,
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
int new_mode; int new_mode;
if (phy->index != 0) if (phy->index != 0) {
if (mode == PHY_MODE_USB_HOST)
return 0;
return -EINVAL; return -EINVAL;
}
switch (mode) { switch (mode) {
case PHY_MODE_USB_HOST: case PHY_MODE_USB_HOST:

View File

@ -558,10 +558,8 @@ static void acm_softint(struct work_struct *work)
clear_bit(EVENT_RX_STALL, &acm->flags); clear_bit(EVENT_RX_STALL, &acm->flags);
} }
if (test_bit(EVENT_TTY_WAKEUP, &acm->flags)) { if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
tty_port_tty_wakeup(&acm->port); tty_port_tty_wakeup(&acm->port);
clear_bit(EVENT_TTY_WAKEUP, &acm->flags);
}
} }
/* /*

View File

@ -145,6 +145,8 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
do { do {
controller = of_find_node_with_property(controller, "phys"); controller = of_find_node_with_property(controller, "phys");
if (!of_device_is_available(controller))
continue;
index = 0; index = 0;
do { do {
if (arg0 == -1) { if (arg0 == -1) {

View File

@ -2741,6 +2741,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
retval = usb_phy_roothub_set_mode(hcd->phy_roothub, retval = usb_phy_roothub_set_mode(hcd->phy_roothub,
PHY_MODE_USB_HOST_SS); PHY_MODE_USB_HOST_SS);
if (retval)
retval = usb_phy_roothub_set_mode(hcd->phy_roothub,
PHY_MODE_USB_HOST);
if (retval) if (retval)
goto err_usb_phy_roothub_power_on; goto err_usb_phy_roothub_power_on;

View File

@ -29,6 +29,7 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa #define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa #define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee #define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
@ -305,6 +306,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD), { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
(kernel_ulong_t) &dwc3_pci_mrfld_properties, }, (kernel_ulong_t) &dwc3_pci_mrfld_properties, },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
(kernel_ulong_t) &dwc3_pci_intel_properties, },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP), { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP),
(kernel_ulong_t) &dwc3_pci_intel_properties, }, (kernel_ulong_t) &dwc3_pci_intel_properties, },

View File

@ -391,20 +391,20 @@ try_again:
req->complete = f_hidg_req_complete; req->complete = f_hidg_req_complete;
req->context = hidg; req->context = hidg;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC); status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
if (status < 0) { if (status < 0) {
ERROR(hidg->func.config->cdev, ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status); "usb_ep_queue error on int endpoint %zd\n", status);
goto release_write_pending_unlocked; goto release_write_pending;
} else { } else {
status = count; status = count;
} }
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
return status; return status;
release_write_pending: release_write_pending:
spin_lock_irqsave(&hidg->write_spinlock, flags); spin_lock_irqsave(&hidg->write_spinlock, flags);
release_write_pending_unlocked:
hidg->write_pending = 0; hidg->write_pending = 0;
spin_unlock_irqrestore(&hidg->write_spinlock, flags); spin_unlock_irqrestore(&hidg->write_spinlock, flags);

View File

@ -945,6 +945,7 @@ net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req)
break; break;
} }
if (&req->req != _req) { if (&req->req != _req) {
ep->stopped = stopped;
spin_unlock_irqrestore(&ep->dev->lock, flags); spin_unlock_irqrestore(&ep->dev->lock, flags);
return -EINVAL; return -EINVAL;
} }

View File

@ -866,9 +866,6 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
(void) readl(&ep->dev->pci->pcimstctl); (void) readl(&ep->dev->pci->pcimstctl);
writel(BIT(DMA_START), &dma->dmastat); writel(BIT(DMA_START), &dma->dmastat);
if (!ep->is_in)
stop_out_naking(ep);
} }
static void start_dma(struct net2280_ep *ep, struct net2280_request *req) static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
@ -907,6 +904,7 @@ static void start_dma(struct net2280_ep *ep, struct net2280_request *req)
writel(BIT(DMA_START), &dma->dmastat); writel(BIT(DMA_START), &dma->dmastat);
return; return;
} }
stop_out_naking(ep);
} }
tmp = dmactl_default; tmp = dmactl_default;
@ -1275,9 +1273,9 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
break; break;
} }
if (&req->req != _req) { if (&req->req != _req) {
ep->stopped = stopped;
spin_unlock_irqrestore(&ep->dev->lock, flags); spin_unlock_irqrestore(&ep->dev->lock, flags);
dev_err(&ep->dev->pdev->dev, "%s: Request mismatch\n", ep_dbg(ep->dev, "%s: Request mismatch\n", __func__);
__func__);
return -EINVAL; return -EINVAL;
} }

View File

@ -3204,6 +3204,9 @@ static int __init u132_hcd_init(void)
printk(KERN_INFO "driver %s\n", hcd_name); printk(KERN_INFO "driver %s\n", hcd_name);
workqueue = create_singlethread_workqueue("u132"); workqueue = create_singlethread_workqueue("u132");
retval = platform_driver_register(&u132_platform_driver); retval = platform_driver_register(&u132_platform_driver);
if (retval)
destroy_workqueue(workqueue);
return retval; return retval;
} }

View File

@ -516,7 +516,6 @@ static int xhci_do_dbc_stop(struct xhci_hcd *xhci)
return -1; return -1;
writel(0, &dbc->regs->control); writel(0, &dbc->regs->control);
xhci_dbc_mem_cleanup(xhci);
dbc->state = DS_DISABLED; dbc->state = DS_DISABLED;
return 0; return 0;
@ -562,8 +561,10 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci)
ret = xhci_do_dbc_stop(xhci); ret = xhci_do_dbc_stop(xhci);
spin_unlock_irqrestore(&dbc->lock, flags); spin_unlock_irqrestore(&dbc->lock, flags);
if (!ret) if (!ret) {
xhci_dbc_mem_cleanup(xhci);
pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller); pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller);
}
} }
static void static void

View File

@ -1545,20 +1545,25 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
port_index = max_ports; port_index = max_ports;
while (port_index--) { while (port_index--) {
u32 t1, t2; u32 t1, t2;
int retries = 10;
retry:
t1 = readl(ports[port_index]->addr); t1 = readl(ports[port_index]->addr);
t2 = xhci_port_state_to_neutral(t1); t2 = xhci_port_state_to_neutral(t1);
portsc_buf[port_index] = 0; portsc_buf[port_index] = 0;
/* Bail out if a USB3 port has a new device in link training */ /*
if ((hcd->speed >= HCD_USB3) && * Give a USB3 port in link training time to finish, but don't
* prevent suspend as port might be stuck
*/
if ((hcd->speed >= HCD_USB3) && retries-- &&
(t1 & PORT_PLS_MASK) == XDEV_POLLING) { (t1 & PORT_PLS_MASK) == XDEV_POLLING) {
bus_state->bus_suspended = 0;
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "Bus suspend bailout, port in polling\n"); msleep(XHCI_PORT_POLLING_LFPS_TIME);
return -EBUSY; spin_lock_irqsave(&xhci->lock, flags);
xhci_dbg(xhci, "port %d polling in bus suspend, waiting\n",
port_index);
goto retry;
} }
/* suspend ports in U0, or bail out for new connect changes */ /* suspend ports in U0, or bail out for new connect changes */
if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) { if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
if ((t1 & PORT_CSC) && wake_enabled) { if ((t1 & PORT_CSC) && wake_enabled) {

View File

@ -246,6 +246,7 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
if (!xhci_rcar_wait_for_pll_active(hcd)) if (!xhci_rcar_wait_for_pll_active(hcd))
return -ETIMEDOUT; return -ETIMEDOUT;
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
return xhci_rcar_download_firmware(hcd); return xhci_rcar_download_firmware(hcd);
} }

View File

@ -1647,10 +1647,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
} }
} }
if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_U0 && if ((portsc & PORT_PLC) &&
DEV_SUPERSPEED_ANY(portsc)) { DEV_SUPERSPEED_ANY(portsc) &&
((portsc & PORT_PLS_MASK) == XDEV_U0 ||
(portsc & PORT_PLS_MASK) == XDEV_U1 ||
(portsc & PORT_PLS_MASK) == XDEV_U2)) {
xhci_dbg(xhci, "resume SS port %d finished\n", port_id); xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
/* We've just brought the device into U0 through either the /* We've just brought the device into U0/1/2 through either the
* Resume state after a device remote wakeup, or through the * Resume state after a device remote wakeup, or through the
* U3Exit state after a host-initiated resume. If it's a device * U3Exit state after a host-initiated resume. If it's a device
* initiated remote wake, don't pass up the link state change, * initiated remote wake, don't pass up the link state change,

View File

@ -452,6 +452,14 @@ struct xhci_op_regs {
*/ */
#define XHCI_DEFAULT_BESL 4 #define XHCI_DEFAULT_BESL 4
/*
* USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
* to complete link training. usually link trainig completes much faster
* so check status 10 times with 36ms sleep in places we need to wait for
* polling to complete.
*/
#define XHCI_PORT_POLLING_LFPS_TIME 36
/** /**
* struct xhci_intr_reg - Interrupt Register Set * struct xhci_intr_reg - Interrupt Register Set
* @irq_pending: IMAN - Interrupt Management Register. Used to enable * @irq_pending: IMAN - Interrupt Management Register. Used to enable

View File

@ -547,7 +547,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
*/ */
hub->port_swap = USB251XB_DEF_PORT_SWAP; hub->port_swap = USB251XB_DEF_PORT_SWAP;
of_property_for_each_u32(np, "swap-dx-lanes", prop, p, port) { of_property_for_each_u32(np, "swap-dx-lanes", prop, p, port) {
if ((port >= 0) && (port <= data->port_cnt)) if (port <= data->port_cnt)
hub->port_swap |= BIT(port); hub->port_swap |= BIT(port);
} }
@ -612,7 +612,7 @@ static int usb251xb_probe(struct usb251xb *hub)
dev); dev);
int err; int err;
if (np) { if (np && of_id) {
err = usb251xb_get_ofdata(hub, err = usb251xb_get_ofdata(hub,
(struct usb251xb_data *)of_id->data); (struct usb251xb_data *)of_id->data);
if (err) { if (err) {

View File

@ -6,6 +6,7 @@ config USB_MTU3
tristate "MediaTek USB3 Dual Role controller" tristate "MediaTek USB3 Dual Role controller"
depends on USB || USB_GADGET depends on USB || USB_GADGET
depends on ARCH_MEDIATEK || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST
depends on EXTCON || !EXTCON
select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD
help help
Say Y or M here if your system runs on MediaTek SoCs with Say Y or M here if your system runs on MediaTek SoCs with

View File

@ -80,6 +80,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */ { USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
{ USB_DEVICE(0x10C4, 0x8056) }, /* Lorenz Messtechnik devices */
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */ { USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */

View File

@ -609,6 +609,8 @@ static const struct usb_device_id id_table_combined[] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLX_PLUS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORION_IO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },

View File

@ -567,7 +567,9 @@
/* /*
* NovaTech product ids (FTDI_VID) * NovaTech product ids (FTDI_VID)
*/ */
#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ #define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
#define FTDI_NT_ORIONLX_PLUS_PID 0x7c91 /* OrionLX+ Substation Automation Platform */
#define FTDI_NT_ORION_IO_PID 0x7c92 /* Orion I/O */
/* /*
* Synapse Wireless product ids (FTDI_VID) * Synapse Wireless product ids (FTDI_VID)

View File

@ -366,8 +366,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
if (!urbtrack) if (!urbtrack)
return -ENOMEM; return -ENOMEM;
kref_get(&mos_parport->ref_count);
urbtrack->mos_parport = mos_parport;
urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC); urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urbtrack->urb) { if (!urbtrack->urb) {
kfree(urbtrack); kfree(urbtrack);
@ -388,6 +386,8 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
usb_sndctrlpipe(usbdev, 0), usb_sndctrlpipe(usbdev, 0),
(unsigned char *)urbtrack->setup, (unsigned char *)urbtrack->setup,
NULL, 0, async_complete, urbtrack); NULL, 0, async_complete, urbtrack);
kref_get(&mos_parport->ref_count);
urbtrack->mos_parport = mos_parport;
kref_init(&urbtrack->ref_count); kref_init(&urbtrack->ref_count);
INIT_LIST_HEAD(&urbtrack->urblist_entry); INIT_LIST_HEAD(&urbtrack->urblist_entry);

View File

@ -246,6 +246,7 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_EC25 0x0125 #define QUECTEL_PRODUCT_EC25 0x0125
#define QUECTEL_PRODUCT_BG96 0x0296 #define QUECTEL_PRODUCT_BG96 0x0296
#define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EP06 0x0306
#define QUECTEL_PRODUCT_EM12 0x0512
#define CMOTECH_VENDOR_ID 0x16d8 #define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001 #define CMOTECH_PRODUCT_6001 0x6001
@ -1066,7 +1067,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(3) }, .driver_info = RSVD(3) },
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */
.driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) },
/* Quectel products using Qualcomm vendor ID */ /* Quectel products using Qualcomm vendor ID */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
@ -1087,6 +1089,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@ -1940,10 +1945,12 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */
.driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
{ USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) }, { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },

View File

@ -37,6 +37,7 @@
S(SRC_ATTACHED), \ S(SRC_ATTACHED), \
S(SRC_STARTUP), \ S(SRC_STARTUP), \
S(SRC_SEND_CAPABILITIES), \ S(SRC_SEND_CAPABILITIES), \
S(SRC_SEND_CAPABILITIES_TIMEOUT), \
S(SRC_NEGOTIATE_CAPABILITIES), \ S(SRC_NEGOTIATE_CAPABILITIES), \
S(SRC_TRANSITION_SUPPLY), \ S(SRC_TRANSITION_SUPPLY), \
S(SRC_READY), \ S(SRC_READY), \
@ -2966,10 +2967,34 @@ static void run_state_machine(struct tcpm_port *port)
/* port->hard_reset_count = 0; */ /* port->hard_reset_count = 0; */
port->caps_count = 0; port->caps_count = 0;
port->pd_capable = true; port->pd_capable = true;
tcpm_set_state_cond(port, hard_reset_state(port), tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
PD_T_SEND_SOURCE_CAP); PD_T_SEND_SOURCE_CAP);
} }
break; break;
case SRC_SEND_CAPABILITIES_TIMEOUT:
/*
* Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
*
* PD 2.0 sinks are supposed to accept src-capabilities with a
* 3.0 header and simply ignore any src PDOs which the sink does
* not understand such as PPS but some 2.0 sinks instead ignore
* the entire PD_DATA_SOURCE_CAP message, causing contract
* negotiation to fail.
*
* After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
* sending src-capabilities with a lower PD revision to
* make these broken sinks work.
*/
if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
tcpm_set_state(port, HARD_RESET_SEND, 0);
} else if (port->negotiated_rev > PD_REV20) {
port->negotiated_rev--;
port->hard_reset_count = 0;
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
} else {
tcpm_set_state(port, hard_reset_state(port), 0);
}
break;
case SRC_NEGOTIATE_CAPABILITIES: case SRC_NEGOTIATE_CAPABILITIES:
ret = tcpm_pd_check_request(port); ret = tcpm_pd_check_request(port);
if (ret < 0) { if (ret < 0) {

View File

@ -615,8 +615,13 @@ static int wcove_typec_probe(struct platform_device *pdev)
wcove->dev = &pdev->dev; wcove->dev = &pdev->dev;
wcove->regmap = pmic->regmap; wcove->regmap = pmic->regmap;
irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq = platform_get_irq(pdev, 0);
platform_get_irq(pdev, 0)); if (irq < 0) {
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
return irq;
}
irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq);
if (irq < 0) if (irq < 0)
return irq; return irq;