Skip to content

Commit 8d02a9a

Browse files
committed
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 ...
2 parents 782492a + d65d25b commit 8d02a9a

File tree

23 files changed

+110
-37
lines changed

23 files changed

+110
-37
lines changed

drivers/phy/allwinner/phy-sun4i-usb.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,11 @@ static int sun4i_usb_phy_set_mode(struct phy *_phy,
485485
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
486486
int new_mode;
487487

488-
if (phy->index != 0)
488+
if (phy->index != 0) {
489+
if (mode == PHY_MODE_USB_HOST)
490+
return 0;
489491
return -EINVAL;
492+
}
490493

491494
switch (mode) {
492495
case PHY_MODE_USB_HOST:

drivers/usb/class/cdc-acm.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,8 @@ static void acm_softint(struct work_struct *work)
558558
clear_bit(EVENT_RX_STALL, &acm->flags);
559559
}
560560

561-
if (test_bit(EVENT_TTY_WAKEUP, &acm->flags)) {
561+
if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
562562
tty_port_tty_wakeup(&acm->port);
563-
clear_bit(EVENT_TTY_WAKEUP, &acm->flags);
564-
}
565563
}
566564

567565
/*

drivers/usb/common/common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
145145

146146
do {
147147
controller = of_find_node_with_property(controller, "phys");
148+
if (!of_device_is_available(controller))
149+
continue;
148150
index = 0;
149151
do {
150152
if (arg0 == -1) {

drivers/usb/core/hcd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
27412741

27422742
retval = usb_phy_roothub_set_mode(hcd->phy_roothub,
27432743
PHY_MODE_USB_HOST_SS);
2744+
if (retval)
2745+
retval = usb_phy_roothub_set_mode(hcd->phy_roothub,
2746+
PHY_MODE_USB_HOST);
27442747
if (retval)
27452748
goto err_usb_phy_roothub_power_on;
27462749

drivers/usb/dwc3/dwc3-pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
3030
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
3131
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
32+
#define PCI_DEVICE_ID_INTEL_CMLH 0x02ee
3233
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa
3334
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
3435
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
@@ -305,6 +306,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
305306
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
306307
(kernel_ulong_t) &dwc3_pci_mrfld_properties, },
307308

309+
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
310+
(kernel_ulong_t) &dwc3_pci_intel_properties, },
311+
308312
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP),
309313
(kernel_ulong_t) &dwc3_pci_intel_properties, },
310314

drivers/usb/gadget/function/f_hid.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,20 +391,20 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
391391
req->complete = f_hidg_req_complete;
392392
req->context = hidg;
393393

394+
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
395+
394396
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
395397
if (status < 0) {
396398
ERROR(hidg->func.config->cdev,
397399
"usb_ep_queue error on int endpoint %zd\n", status);
398-
goto release_write_pending_unlocked;
400+
goto release_write_pending;
399401
} else {
400402
status = count;
401403
}
402-
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
403404

404405
return status;
405406
release_write_pending:
406407
spin_lock_irqsave(&hidg->write_spinlock, flags);
407-
release_write_pending_unlocked:
408408
hidg->write_pending = 0;
409409
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
410410

drivers/usb/gadget/udc/net2272.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req)
945945
break;
946946
}
947947
if (&req->req != _req) {
948+
ep->stopped = stopped;
948949
spin_unlock_irqrestore(&ep->dev->lock, flags);
949950
return -EINVAL;
950951
}

drivers/usb/gadget/udc/net2280.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -866,9 +866,6 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
866866
(void) readl(&ep->dev->pci->pcimstctl);
867867

868868
writel(BIT(DMA_START), &dma->dmastat);
869-
870-
if (!ep->is_in)
871-
stop_out_naking(ep);
872869
}
873870

874871
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)
907904
writel(BIT(DMA_START), &dma->dmastat);
908905
return;
909906
}
907+
stop_out_naking(ep);
910908
}
911909

912910
tmp = dmactl_default;
@@ -1275,9 +1273,9 @@ static int net2280_dequeue(struct usb_ep *_ep, struct usb_request *_req)
12751273
break;
12761274
}
12771275
if (&req->req != _req) {
1276+
ep->stopped = stopped;
12781277
spin_unlock_irqrestore(&ep->dev->lock, flags);
1279-
dev_err(&ep->dev->pdev->dev, "%s: Request mismatch\n",
1280-
__func__);
1278+
ep_dbg(ep->dev, "%s: Request mismatch\n", __func__);
12811279
return -EINVAL;
12821280
}
12831281

drivers/usb/host/u132-hcd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,9 @@ static int __init u132_hcd_init(void)
32043204
printk(KERN_INFO "driver %s\n", hcd_name);
32053205
workqueue = create_singlethread_workqueue("u132");
32063206
retval = platform_driver_register(&u132_platform_driver);
3207+
if (retval)
3208+
destroy_workqueue(workqueue);
3209+
32073210
return retval;
32083211
}
32093212

drivers/usb/host/xhci-dbgcap.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,6 @@ static int xhci_do_dbc_stop(struct xhci_hcd *xhci)
516516
return -1;
517517

518518
writel(0, &dbc->regs->control);
519-
xhci_dbc_mem_cleanup(xhci);
520519
dbc->state = DS_DISABLED;
521520

522521
return 0;
@@ -562,8 +561,10 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci)
562561
ret = xhci_do_dbc_stop(xhci);
563562
spin_unlock_irqrestore(&dbc->lock, flags);
564563

565-
if (!ret)
564+
if (!ret) {
565+
xhci_dbc_mem_cleanup(xhci);
566566
pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller);
567+
}
567568
}
568569

569570
static void

drivers/usb/host/xhci-hub.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,20 +1545,25 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
15451545
port_index = max_ports;
15461546
while (port_index--) {
15471547
u32 t1, t2;
1548-
1548+
int retries = 10;
1549+
retry:
15491550
t1 = readl(ports[port_index]->addr);
15501551
t2 = xhci_port_state_to_neutral(t1);
15511552
portsc_buf[port_index] = 0;
15521553

1553-
/* Bail out if a USB3 port has a new device in link training */
1554-
if ((hcd->speed >= HCD_USB3) &&
1554+
/*
1555+
* Give a USB3 port in link training time to finish, but don't
1556+
* prevent suspend as port might be stuck
1557+
*/
1558+
if ((hcd->speed >= HCD_USB3) && retries-- &&
15551559
(t1 & PORT_PLS_MASK) == XDEV_POLLING) {
1556-
bus_state->bus_suspended = 0;
15571560
spin_unlock_irqrestore(&xhci->lock, flags);
1558-
xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
1559-
return -EBUSY;
1561+
msleep(XHCI_PORT_POLLING_LFPS_TIME);
1562+
spin_lock_irqsave(&xhci->lock, flags);
1563+
xhci_dbg(xhci, "port %d polling in bus suspend, waiting\n",
1564+
port_index);
1565+
goto retry;
15601566
}
1561-
15621567
/* suspend ports in U0, or bail out for new connect changes */
15631568
if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
15641569
if ((t1 & PORT_CSC) && wake_enabled) {

drivers/usb/host/xhci-rcar.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
246246
if (!xhci_rcar_wait_for_pll_active(hcd))
247247
return -ETIMEDOUT;
248248

249+
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
249250
return xhci_rcar_download_firmware(hcd);
250251
}
251252

drivers/usb/host/xhci-ring.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,10 +1647,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
16471647
}
16481648
}
16491649

1650-
if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_U0 &&
1651-
DEV_SUPERSPEED_ANY(portsc)) {
1650+
if ((portsc & PORT_PLC) &&
1651+
DEV_SUPERSPEED_ANY(portsc) &&
1652+
((portsc & PORT_PLS_MASK) == XDEV_U0 ||
1653+
(portsc & PORT_PLS_MASK) == XDEV_U1 ||
1654+
(portsc & PORT_PLS_MASK) == XDEV_U2)) {
16521655
xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
1653-
/* We've just brought the device into U0 through either the
1656+
/* We've just brought the device into U0/1/2 through either the
16541657
* Resume state after a device remote wakeup, or through the
16551658
* U3Exit state after a host-initiated resume. If it's a device
16561659
* initiated remote wake, don't pass up the link state change,

drivers/usb/host/xhci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,14 @@ struct xhci_op_regs {
452452
*/
453453
#define XHCI_DEFAULT_BESL 4
454454

455+
/*
456+
* USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
457+
* to complete link training. usually link trainig completes much faster
458+
* so check status 10 times with 36ms sleep in places we need to wait for
459+
* polling to complete.
460+
*/
461+
#define XHCI_PORT_POLLING_LFPS_TIME 36
462+
455463
/**
456464
* struct xhci_intr_reg - Interrupt Register Set
457465
* @irq_pending: IMAN - Interrupt Management Register. Used to enable

drivers/usb/misc/usb251xb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
547547
*/
548548
hub->port_swap = USB251XB_DEF_PORT_SWAP;
549549
of_property_for_each_u32(np, "swap-dx-lanes", prop, p, port) {
550-
if ((port >= 0) && (port <= data->port_cnt))
550+
if (port <= data->port_cnt)
551551
hub->port_swap |= BIT(port);
552552
}
553553

@@ -612,7 +612,7 @@ static int usb251xb_probe(struct usb251xb *hub)
612612
dev);
613613
int err;
614614

615-
if (np) {
615+
if (np && of_id) {
616616
err = usb251xb_get_ofdata(hub,
617617
(struct usb251xb_data *)of_id->data);
618618
if (err) {

drivers/usb/mtu3/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config USB_MTU3
66
tristate "MediaTek USB3 Dual Role controller"
77
depends on USB || USB_GADGET
88
depends on ARCH_MEDIATEK || COMPILE_TEST
9+
depends on EXTCON || !EXTCON
910
select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD
1011
help
1112
Say Y or M here if your system runs on MediaTek SoCs with

drivers/usb/serial/cp210x.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static const struct usb_device_id id_table[] = {
8080
{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
8181
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
8282
{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
83+
{ USB_DEVICE(0x10C4, 0x8056) }, /* Lorenz Messtechnik devices */
8384
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
8485
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
8586
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */

drivers/usb/serial/ftdi_sio.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,8 @@ static const struct usb_device_id id_table_combined[] = {
609609
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
610610
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
611611
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
612+
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLX_PLUS_PID) },
613+
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORION_IO_PID) },
612614
{ USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
613615
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
614616
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },

drivers/usb/serial/ftdi_sio_ids.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,9 @@
567567
/*
568568
* NovaTech product ids (FTDI_VID)
569569
*/
570-
#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
570+
#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
571+
#define FTDI_NT_ORIONLX_PLUS_PID 0x7c91 /* OrionLX+ Substation Automation Platform */
572+
#define FTDI_NT_ORION_IO_PID 0x7c92 /* Orion I/O */
571573

572574
/*
573575
* Synapse Wireless product ids (FTDI_VID)

drivers/usb/serial/mos7720.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
366366
if (!urbtrack)
367367
return -ENOMEM;
368368

369-
kref_get(&mos_parport->ref_count);
370-
urbtrack->mos_parport = mos_parport;
371369
urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC);
372370
if (!urbtrack->urb) {
373371
kfree(urbtrack);
@@ -388,6 +386,8 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
388386
usb_sndctrlpipe(usbdev, 0),
389387
(unsigned char *)urbtrack->setup,
390388
NULL, 0, async_complete, urbtrack);
389+
kref_get(&mos_parport->ref_count);
390+
urbtrack->mos_parport = mos_parport;
391391
kref_init(&urbtrack->ref_count);
392392
INIT_LIST_HEAD(&urbtrack->urblist_entry);
393393

drivers/usb/serial/option.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ static void option_instat_callback(struct urb *urb);
246246
#define QUECTEL_PRODUCT_EC25 0x0125
247247
#define QUECTEL_PRODUCT_BG96 0x0296
248248
#define QUECTEL_PRODUCT_EP06 0x0306
249+
#define QUECTEL_PRODUCT_EM12 0x0512
249250

250251
#define CMOTECH_VENDOR_ID 0x16d8
251252
#define CMOTECH_PRODUCT_6001 0x6001
@@ -1066,7 +1067,8 @@ static const struct usb_device_id option_ids[] = {
10661067
.driver_info = RSVD(3) },
10671068
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
10681069
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
1069-
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
1070+
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */
1071+
.driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) },
10701072
/* Quectel products using Qualcomm vendor ID */
10711073
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
10721074
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
@@ -1087,6 +1089,9 @@ static const struct usb_device_id option_ids[] = {
10871089
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
10881090
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
10891091
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
1092+
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
1093+
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
1094+
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
10901095
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
10911096
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
10921097
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1940,10 +1945,12 @@ static const struct usb_device_id option_ids[] = {
19401945
.driver_info = RSVD(4) },
19411946
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */
19421947
.driver_info = RSVD(4) },
1943-
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
1944-
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
1945-
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */
1946-
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
1948+
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
1949+
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
1950+
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */
1951+
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */
1952+
.driver_info = RSVD(4) },
1953+
{ USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
19471954
{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
19481955
{ USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
19491956
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
S(SRC_ATTACHED), \
3838
S(SRC_STARTUP), \
3939
S(SRC_SEND_CAPABILITIES), \
40+
S(SRC_SEND_CAPABILITIES_TIMEOUT), \
4041
S(SRC_NEGOTIATE_CAPABILITIES), \
4142
S(SRC_TRANSITION_SUPPLY), \
4243
S(SRC_READY), \
@@ -2966,10 +2967,34 @@ static void run_state_machine(struct tcpm_port *port)
29662967
/* port->hard_reset_count = 0; */
29672968
port->caps_count = 0;
29682969
port->pd_capable = true;
2969-
tcpm_set_state_cond(port, hard_reset_state(port),
2970+
tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
29702971
PD_T_SEND_SOURCE_CAP);
29712972
}
29722973
break;
2974+
case SRC_SEND_CAPABILITIES_TIMEOUT:
2975+
/*
2976+
* Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
2977+
*
2978+
* PD 2.0 sinks are supposed to accept src-capabilities with a
2979+
* 3.0 header and simply ignore any src PDOs which the sink does
2980+
* not understand such as PPS but some 2.0 sinks instead ignore
2981+
* the entire PD_DATA_SOURCE_CAP message, causing contract
2982+
* negotiation to fail.
2983+
*
2984+
* After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
2985+
* sending src-capabilities with a lower PD revision to
2986+
* make these broken sinks work.
2987+
*/
2988+
if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
2989+
tcpm_set_state(port, HARD_RESET_SEND, 0);
2990+
} else if (port->negotiated_rev > PD_REV20) {
2991+
port->negotiated_rev--;
2992+
port->hard_reset_count = 0;
2993+
tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
2994+
} else {
2995+
tcpm_set_state(port, hard_reset_state(port), 0);
2996+
}
2997+
break;
29732998
case SRC_NEGOTIATE_CAPABILITIES:
29742999
ret = tcpm_pd_check_request(port);
29753000
if (ret < 0) {

0 commit comments

Comments
 (0)