From c5a80540e425a5f9a82b0f3163e3b6a4331f33bc Mon Sep 17 00:00:00 2001 From: Dominik Andreas Schorpp Date: Thu, 22 Apr 2021 09:58:52 +0200 Subject: USB: serial: ftdi_sio: add IDs for IDS GmbH Products Add the IDS GmbH Vendor ID and the Product IDs for SI31A (2xRS232) and CM31A (LoRaWAN Modem). Signed-off-by: Dominik Andreas Schorpp Signed-off-by: Juergen Borleis Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6f2659e59b2e..369ef140df78 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1034,6 +1034,9 @@ static const struct usb_device_id id_table_combined[] = { /* Sienna devices */ { USB_DEVICE(FTDI_VID, FTDI_SIENNA_PID) }, { USB_DEVICE(ECHELON_VID, ECHELON_U20_PID) }, + /* IDS GmbH devices */ + { USB_DEVICE(IDS_VID, IDS_SI31A_PID) }, + { USB_DEVICE(IDS_VID, IDS_CM31A_PID) }, /* U-Blox devices */ { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 3d47c6d72256..d854e04a4286 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1567,6 +1567,13 @@ #define UNJO_VID 0x22B7 #define UNJO_ISODEBUG_V1_PID 0x150D +/* + * IDS GmbH + */ +#define IDS_VID 0x2CAF +#define IDS_SI31A_PID 0x13A2 +#define IDS_CM31A_PID 0x13A3 + /* * U-Blox products (http://www.u-blox.com). */ -- cgit From e467714f822b5d167a7fb03d34af91b5b6af1827 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Wed, 28 Apr 2021 09:26:34 +0200 Subject: USB: serial: option: add Telit LE910-S1 compositions 0x7010, 0x7011 Add support for the following Telit LE910-S1 compositions: 0x7010: rndis, tty, tty, tty 0x7011: ecm, tty, tty, tty Signed-off-by: Daniele Palmas Link: https://lore.kernel.org/r/20210428072634.5091-1-dnlplm@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3e79a543d3e7..7608584ef4fe 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1240,6 +1240,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */ .driver_info = NCTRL(0) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7010, 0xff), /* Telit LE910-S1 (RNDIS) */ + .driver_info = NCTRL(2) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */ + .driver_info = NCTRL(2) }, { USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */ .driver_info = NCTRL(0) | ZLP }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ -- cgit From 89b1a3d811e6f8065d6ae8a25e7682329b4a31e2 Mon Sep 17 00:00:00 2001 From: Sean MacLennan Date: Sat, 1 May 2021 20:40:45 -0400 Subject: USB: serial: ti_usb_3410_5052: add startech.com device id This adds support for the Startech.com generic serial to USB converter. It seems to be a bone stock TI_3410. I have been using this patch for years. Signed-off-by: Sean MacLennan Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/ti_usb_3410_5052.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index caa46ac23db9..310db5abea9d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -37,6 +37,7 @@ /* Vendor and product ids */ #define TI_VENDOR_ID 0x0451 #define IBM_VENDOR_ID 0x04b3 +#define STARTECH_VENDOR_ID 0x14b0 #define TI_3410_PRODUCT_ID 0x3410 #define IBM_4543_PRODUCT_ID 0x4543 #define IBM_454B_PRODUCT_ID 0x454b @@ -370,6 +371,7 @@ static const struct usb_device_id ti_id_table_3410[] = { { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) }, { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) }, { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) }, + { USB_DEVICE(STARTECH_VENDOR_ID, TI_3410_PRODUCT_ID) }, { } /* terminator */ }; @@ -408,6 +410,7 @@ static const struct usb_device_id ti_id_table_combined[] = { { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) }, { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) }, { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) }, + { USB_DEVICE(STARTECH_VENDOR_ID, TI_3410_PRODUCT_ID) }, { } /* terminator */ }; -- cgit From f8e8c1b2f782e7391e8a1c25648ce756e2a7d481 Mon Sep 17 00:00:00 2001 From: Zolton Jheng Date: Mon, 10 May 2021 10:32:00 +0800 Subject: USB: serial: pl2303: add device id for ADLINK ND-6530 GC This adds the device id for the ADLINK ND-6530 which is a PL2303GC based device. Signed-off-by: Zolton Jheng Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index fd773d252691..940050c31482 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -113,6 +113,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, + { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530GC_PRODUCT_ID) }, { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, { USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) }, { } /* Terminating entry */ diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 0f681ddbfd28..6097ee8fccb2 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -158,6 +158,7 @@ /* ADLINK ND-6530 RS232,RS485 and RS422 adapter */ #define ADLINK_VENDOR_ID 0x0b63 #define ADLINK_ND6530_PRODUCT_ID 0x6530 +#define ADLINK_ND6530GC_PRODUCT_ID 0x653a /* SMART USB Serial Adapter */ #define SMART_VENDOR_ID 0x0b8c -- cgit From 07adc0225484fc199e3dc15ec889f75f498c4fca Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Mon, 12 Apr 2021 13:49:07 +0800 Subject: usb: cdns3: Fix runtime PM imbalance on error When cdns3_gadget_start() fails, a pairing PM usage counter decrement is needed to keep the counter balanced. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20210412054908.7975-1-dinghao.liu@zju.edu.cn Signed-off-by: Peter Chen --- drivers/usb/cdns3/cdns3-gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 9b1bd417cec0..a8b7b50abf64 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -3268,8 +3268,10 @@ static int __cdns3_gadget_init(struct cdns *cdns) pm_runtime_get_sync(cdns->dev); ret = cdns3_gadget_start(cdns); - if (ret) + if (ret) { + pm_runtime_put_sync(cdns->dev); return ret; + } /* * Because interrupt line can be shared with other components in -- cgit From 3b414d1b0107fa51ad6063de9752d4b2a8063980 Mon Sep 17 00:00:00 2001 From: Pawel Laszczak Date: Tue, 20 Apr 2021 06:28:13 +0200 Subject: usb: cdnsp: Fix lack of removing request from pending list. Patch fixes lack of removing request from ep->pending_list on failure of the stop endpoint command. Driver even after failing this command must remove request from ep->pending_list. Without this fix driver can stuck in cdnsp_gadget_ep_disable function in loop: while (!list_empty(&pep->pending_list)) { preq = next_request(&pep->pending_list); cdnsp_ep_dequeue(pep, preq); } Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Signed-off-by: Pawel Laszczak Link: https://lore.kernel.org/r/20210420042813.34917-1-pawell@gli-login.cadence.com Signed-off-by: Peter Chen --- drivers/usb/cdns3/cdnsp-gadget.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c index 56707b6b0f57..c083985e387b 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.c +++ b/drivers/usb/cdns3/cdnsp-gadget.c @@ -422,17 +422,17 @@ unmap: int cdnsp_ep_dequeue(struct cdnsp_ep *pep, struct cdnsp_request *preq) { struct cdnsp_device *pdev = pep->pdev; - int ret; + int ret_stop = 0; + int ret_rem; trace_cdnsp_request_dequeue(preq); - if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_RUNNING) { - ret = cdnsp_cmd_stop_ep(pdev, pep); - if (ret) - return ret; - } + if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_RUNNING) + ret_stop = cdnsp_cmd_stop_ep(pdev, pep); + + ret_rem = cdnsp_remove_request(pdev, preq, pep); - return cdnsp_remove_request(pdev, preq, pep); + return ret_rem ? ret_rem : ret_stop; } static void cdnsp_zero_in_ctx(struct cdnsp_device *pdev) -- cgit From 9e3927f6373da54cb17e17f4bd700907e1123d2f Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 14 May 2021 18:59:44 +0800 Subject: usb: chipidea: udc: assign interrupt number to USB gadget structure Chipidea also need sync interrupt before unbind the udc while gadget remove driver, otherwise setup irq handling may happen while unbind, see below dump generated from android function switch stress test: [ 4703.503056] android_work: sent uevent USB_STATE=CONNECTED [ 4703.514642] android_work: sent uevent USB_STATE=DISCONNECTED [ 4703.651339] android_work: sent uevent USB_STATE=CONNECTED [ 4703.661806] init: Control message: Processed ctl.stop for 'adbd' from pid: 561 (system_server) [ 4703.673469] init: processing action (init.svc.adbd=stopped) from (/system/etc/init/hw/init.usb.configfs.rc:14) [ 4703.676451] Unable to handle kernel read from unreadable memory at virtual address 0000000000000090 [ 4703.676454] Mem abort info: [ 4703.676458] ESR = 0x96000004 [ 4703.676461] EC = 0x25: DABT (current EL), IL = 32 bits [ 4703.676464] SET = 0, FnV = 0 [ 4703.676466] EA = 0, S1PTW = 0 [ 4703.676468] Data abort info: [ 4703.676471] ISV = 0, ISS = 0x00000004 [ 4703.676473] CM = 0, WnR = 0 [ 4703.676478] user pgtable: 4k pages, 48-bit VAs, pgdp=000000004a867000 [ 4703.676481] [0000000000000090] pgd=0000000000000000, p4d=0000000000000000 [ 4703.676503] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 4703.758297] Modules linked in: synaptics_dsx_i2c moal(O) mlan(O) [ 4703.764327] CPU: 0 PID: 235 Comm: lmkd Tainted: G W O 5.10.9-00001-g3f5fd8487c38-dirty #63 [ 4703.773720] Hardware name: NXP i.MX8MNano EVK board (DT) [ 4703.779033] pstate: 60400085 (nZCv daIf +PAN -UAO -TCO BTYPE=--) [ 4703.785046] pc : _raw_write_unlock_bh+0xc0/0x2c8 [ 4703.789667] lr : android_setup+0x4c/0x168 [ 4703.793676] sp : ffff80001256bd80 [ 4703.796989] x29: ffff80001256bd80 x28: 00000000000000a8 [ 4703.802304] x27: ffff800012470000 x26: ffff80006d923000 [ 4703.807616] x25: ffff800012471000 x24: ffff00000b091140 [ 4703.812929] x23: ffff0000077dbd38 x22: ffff0000077da490 [ 4703.818242] x21: ffff80001256be30 x20: 0000000000000000 [ 4703.823554] x19: 0000000000000080 x18: ffff800012561048 [ 4703.828867] x17: 0000000000000000 x16: 0000000000000039 [ 4703.834180] x15: ffff8000106ad258 x14: ffff80001194c277 [ 4703.839493] x13: 0000000000003934 x12: 0000000000000000 [ 4703.844805] x11: 0000000000000000 x10: 0000000000000001 [ 4703.850117] x9 : 0000000000000000 x8 : 0000000000000090 [ 4703.855429] x7 : 6f72646e61203a70 x6 : ffff8000124f2450 [ 4703.860742] x5 : ffffffffffffffff x4 : 0000000000000009 [ 4703.866054] x3 : ffff8000108a290c x2 : ffff00007fb3a9c8 [ 4703.871367] x1 : 0000000000000000 x0 : 0000000000000090 [ 4703.876681] Call trace: [ 4703.879129] _raw_write_unlock_bh+0xc0/0x2c8 [ 4703.883397] android_setup+0x4c/0x168 [ 4703.887059] udc_irq+0x824/0xa9c [ 4703.890287] ci_irq+0x124/0x148 [ 4703.893429] __handle_irq_event_percpu+0x84/0x268 [ 4703.898131] handle_irq_event+0x64/0x14c [ 4703.902054] handle_fasteoi_irq+0x110/0x210 [ 4703.906236] __handle_domain_irq+0x8c/0xd4 [ 4703.910332] gic_handle_irq+0x6c/0x124 [ 4703.914081] el1_irq+0xdc/0x1c0 [ 4703.917221] _raw_spin_unlock_irq+0x20/0x54 [ 4703.921405] finish_task_switch+0x84/0x224 [ 4703.925502] __schedule+0x4a4/0x734 [ 4703.928990] schedule+0xa0/0xe8 [ 4703.932132] do_notify_resume+0x150/0x184 [ 4703.936140] work_pending+0xc/0x40c [ 4703.939633] Code: d5384613 521b0a69 d5184609 f9800111 (885ffd01) [ 4703.945732] ---[ end trace ba5c1875ae49d53c ]--- [ 4703.950350] Kernel panic - not syncing: Oops: Fatal exception in interrupt [ 4703.957223] SMP: stopping secondary CPUs [ 4703.961151] Kernel Offset: disabled [ 4703.964638] CPU features: 0x0240002,2000200c [ 4703.968905] Memory Limit: none [ 4703.971963] Rebooting in 5 seconds.. Tested-by: faqiang.zhu Signed-off-by: Li Jun Link: https://lore.kernel.org/r/1620989984-7653-1-git-send-email-jun.li@nxp.com Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c16d900cdaee..393f216b9161 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -2061,6 +2061,7 @@ static int udc_start(struct ci_hdrc *ci) ci->gadget.name = ci->platdata->name; ci->gadget.otg_caps = otg_caps; ci->gadget.sg_supported = 1; + ci->gadget.irq = ci->irq; if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA) ci->gadget.quirk_avoids_skb_reserve = 1; -- cgit From 4f2629ea67e7225c3fd292c7fe4f5b3c9d6392de Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 18 May 2021 16:18:35 -0400 Subject: USB: usbfs: Don't WARN about excessively large memory allocations Syzbot found that the kernel generates a WARNing if the user tries to submit a bulk transfer through usbfs with a buffer that is way too large. This isn't a bug in the kernel; it's merely an invalid request from the user and the usbfs code does handle it correctly. In theory the same thing can happen with async transfers, or with the packet descriptor table for isochronous transfers. To prevent the MM subsystem from complaining about these bad allocation requests, add the __GFP_NOWARN flag to the kmalloc calls for these buffers. CC: Andrew Morton CC: Reported-and-tested-by: syzbot+882a85c0c8ec4a3e2281@syzkaller.appspotmail.com Signed-off-by: Alan Stern Link: https://lore.kernel.org/r/20210518201835.GA1140918@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 533236366a03..2218941d35a3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1218,7 +1218,12 @@ static int do_proc_bulk(struct usb_dev_state *ps, ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); if (ret) return ret; - tbuf = kmalloc(len1, GFP_KERNEL); + + /* + * len1 can be almost arbitrarily large. Don't WARN if it's + * too big, just fail the request. + */ + tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN); if (!tbuf) { ret = -ENOMEM; goto done; @@ -1696,7 +1701,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb if (num_sgs) { as->urb->sg = kmalloc_array(num_sgs, sizeof(struct scatterlist), - GFP_KERNEL); + GFP_KERNEL | __GFP_NOWARN); if (!as->urb->sg) { ret = -ENOMEM; goto error; @@ -1731,7 +1736,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb (uurb_start - as->usbm->vm_start); } else { as->urb->transfer_buffer = kmalloc(uurb->buffer_length, - GFP_KERNEL); + GFP_KERNEL | __GFP_NOWARN); if (!as->urb->transfer_buffer) { ret = -ENOMEM; goto error; -- cgit From 25dda9fc56bd90d45f9a4516bcfa5211e61b4290 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Wed, 12 May 2021 20:17:09 -0700 Subject: usb: dwc3: gadget: Properly track pending and queued SG The driver incorrectly uses req->num_pending_sgs to track both the number of pending and queued SG entries. It only prepares the next request if the previous is done, and it doesn't update num_pending_sgs until there is TRB completion interrupt. This may starve the controller of more TRBs until the num_pending_sgs is decremented. Fix this by decrementing the num_pending_sgs after they are queued and properly track both num_mapped_sgs and num_queued_sgs. Fixes: c96e6725db9d ("usb: dwc3: gadget: Correct the logic for queuing sgs") Cc: Reported-by: Michael Grzeschik Tested-by: Michael Grzeschik Acked-by: Felipe Balbi Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/ba24591dbcaad8f244a3e88bd449bb7205a5aec3.1620874069.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 49ca5da5e279..612825a39f82 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1244,6 +1244,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep, req->start_sg = sg_next(s); req->num_queued_sgs++; + req->num_pending_sgs--; /* * The number of pending SG entries may not correspond to the @@ -1251,7 +1252,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep, * don't include unused SG entries. */ if (length == 0) { - req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; + req->num_pending_sgs = 0; break; } @@ -2873,15 +2874,15 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue]; struct scatterlist *sg = req->sg; struct scatterlist *s; - unsigned int pending = req->num_pending_sgs; + unsigned int num_queued = req->num_queued_sgs; unsigned int i; int ret = 0; - for_each_sg(sg, s, pending, i) { + for_each_sg(sg, s, num_queued, i) { trb = &dep->trb_pool[dep->trb_dequeue]; req->sg = sg_next(s); - req->num_pending_sgs--; + req->num_queued_sgs--; ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, trb, event, status, true); @@ -2904,7 +2905,7 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep, static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req) { - return req->num_pending_sgs == 0; + return req->num_pending_sgs == 0 && req->num_queued_sgs == 0; } static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, @@ -2913,7 +2914,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, { int ret; - if (req->num_pending_sgs) + if (req->request.num_mapped_sgs) ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event, status); else -- cgit From dcb4b8ad6a448532d8b681b5d1a7036210b622de Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Fri, 14 May 2021 20:43:48 +0800 Subject: misc/uss720: fix memory leak in uss720_probe uss720_probe forgets to decrease the refcount of usbdev in uss720_probe. Fix this by decreasing the refcount of usbdev by usb_put_dev. BUG: memory leak unreferenced object 0xffff888101113800 (size 2048): comm "kworker/0:1", pid 7, jiffies 4294956777 (age 28.870s) hex dump (first 32 bytes): ff ff ff ff 31 00 00 00 00 00 00 00 00 00 00 00 ....1........... 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 ................ backtrace: [] kmalloc include/linux/slab.h:554 [inline] [] kzalloc include/linux/slab.h:684 [inline] [] usb_alloc_dev+0x32/0x450 drivers/usb/core/usb.c:582 [] hub_port_connect drivers/usb/core/hub.c:5129 [inline] [] hub_port_connect_change drivers/usb/core/hub.c:5363 [inline] [] port_event drivers/usb/core/hub.c:5509 [inline] [] hub_event+0x1171/0x20c0 drivers/usb/core/hub.c:5591 [] process_one_work+0x2c9/0x600 kernel/workqueue.c:2275 [] worker_thread+0x59/0x5d0 kernel/workqueue.c:2421 [] kthread+0x178/0x1b0 kernel/kthread.c:292 [] ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:294 Fixes: 0f36163d3abe ("[PATCH] usb: fix uss720 schedule with interrupts off") Cc: stable Reported-by: syzbot+636c58f40a86b4a879e7@syzkaller.appspotmail.com Signed-off-by: Dongliang Mu Link: https://lore.kernel.org/r/20210514124348.6587-1-mudongliangabcd@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/uss720.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index b5d661644263..748139d26263 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -736,6 +736,7 @@ static int uss720_probe(struct usb_interface *intf, parport_announce_port(pp); usb_set_intfdata(intf, pp); + usb_put_dev(usbdev); return 0; probe_abort: -- cgit From acf5631c239dfc53489f739c4ad47f490c5181ff Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 15 May 2021 20:47:30 -0700 Subject: usb: typec: mux: Fix matching with typec_altmode_desc In typec_mux_match() "nval" is assigned the number of elements in the "svid" fwnode property, then the variable is used to store the success of the read and finally attempts to loop between 0 and "success" - i.e. not at all - and the code returns indicating that no match was found. Fix this by using a separate variable to track the success of the read, to allow the loop to get a change to find a match. Fixes: 96a6d031ca99 ("usb: typec: mux: Find the muxes by also matching against the device node") Reviewed-by: Heikki Krogerus Cc: stable Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210516034730.621461-1-bjorn.andersson@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/mux.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index 9da22ae3006c..8514bec7e1b8 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -191,6 +191,7 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, bool match; int nval; u16 *val; + int ret; int i; /* @@ -218,10 +219,10 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, if (!val) return ERR_PTR(-ENOMEM); - nval = fwnode_property_read_u16_array(fwnode, "svid", val, nval); - if (nval < 0) { + ret = fwnode_property_read_u16_array(fwnode, "svid", val, nval); + if (ret < 0) { kfree(val); - return ERR_PTR(nval); + return ERR_PTR(ret); } for (i = 0; i < nval; i++) { -- cgit From 8c9b3caab3ac26db1da00b8117901640c55a69dd Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sat, 15 May 2021 21:09:53 -0700 Subject: usb: typec: ucsi: Clear pending after acking connector change It's possible that the interrupt handler for the UCSI driver signals a connector changes after the handler clears the PENDING bit, but before it has sent the acknowledge request. The result is that the handler is invoked yet again, to ack the same connector change. At least some versions of the Qualcomm UCSI firmware will not handle the second - "spurious" - acknowledgment gracefully. So make sure to not clear the pending flag until the change is acknowledged. Any connector changes coming in after the acknowledgment, that would have the pending flag incorrectly cleared, would afaict be covered by the subsequent connector status check. Fixes: 217504a05532 ("usb: typec: ucsi: Work around PPM losing change information") Cc: stable Reviewed-by: Heikki Krogerus Acked-By: Benjamin Berg Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210516040953.622409-1-bjorn.andersson@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 1d8b7df59ff4..b433169ef6fa 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -717,8 +717,8 @@ static void ucsi_handle_connector_change(struct work_struct *work) ucsi_send_command(con->ucsi, command, NULL, 0); /* 3. ACK connector change */ - clear_bit(EVENT_PENDING, &ucsi->flags); ret = ucsi_acknowledge_connector_change(ucsi); + clear_bit(EVENT_PENDING, &ucsi->flags); if (ret) { dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); goto out_unlock; -- cgit From c58bbe3477f75deb7883983e6cf428404a107555 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 19 May 2021 13:03:58 +0300 Subject: usb: typec: tcpm: Use LE to CPU conversion when accessing msg->header Sparse is not happy about strict type handling: .../typec/tcpm/tcpm.c:2720:27: warning: restricted __le16 degrades to integer .../typec/tcpm/tcpm.c:2814:32: warning: restricted __le16 degrades to integer Fix this by converting LE to CPU before use. Fixes: ae8a2ca8a221 ("usb: typec: Group all TCPCI/TCPM code together") Fixes: 64f7c494a3c0 ("typec: tcpm: Add support for sink PPS related messages") Cc: stable Cc: Adam Thomson Reviewed-by: Guenter Roeck Reviewed-by: Adam Thomson Reviewed-by: Heikki Krogerus Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210519100358.64018-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 64133e586c64..8fdfd7f65ad7 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2717,7 +2717,7 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port, enum pd_ext_msg_type type = pd_header_type_le(msg->header); unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); - if (!(msg->ext_msg.header & PD_EXT_HDR_CHUNKED)) { + if (!(le16_to_cpu(msg->ext_msg.header) & PD_EXT_HDR_CHUNKED)) { tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS); tcpm_log(port, "Unchunked extended messages unsupported"); return; @@ -2811,7 +2811,7 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) "Data role mismatch, initiating error recovery"); tcpm_set_state(port, ERROR_RECOVERY, 0); } else { - if (msg->header & PD_HEADER_EXT_HDR) + if (le16_to_cpu(msg->header) & PD_HEADER_EXT_HDR) tcpm_pd_ext_msg_request(port, msg); else if (cnt) tcpm_pd_data_request(port, msg); -- cgit From 746e4acf87bcacf1406e05ef24a0b7139147c63e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 21 May 2021 15:31:09 +0200 Subject: USB: trancevibrator: fix control-request direction The direction of the pipe argument must match the request-type direction bit or control requests may fail depending on the host-controller-driver implementation. Fix the set-speed request which erroneously used USB_DIR_IN and update the default timeout argument to match (same value). Fixes: 5638e4d92e77 ("USB: add PlayStation 2 Trance Vibrator driver") Cc: stable@vger.kernel.org # 2.6.19 Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210521133109.17396-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/trancevibrator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c index a3dfc77578ea..26baba3ab7d7 100644 --- a/drivers/usb/misc/trancevibrator.c +++ b/drivers/usb/misc/trancevibrator.c @@ -61,9 +61,9 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr, /* Set speed */ retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), 0x01, /* vendor request: set speed */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, tv->speed, /* speed value */ - 0, NULL, 0, USB_CTRL_GET_TIMEOUT); + 0, NULL, 0, USB_CTRL_SET_TIMEOUT); if (retval) { tv->speed = old; dev_dbg(&tv->udev->dev, "retval = %d\n", retval); -- cgit From 0bc3ee92880d910a1d100b73a781904f359e1f1c Mon Sep 17 00:00:00 2001 From: Kyle Tso Date: Sun, 23 May 2021 09:58:54 +0800 Subject: usb: typec: tcpm: Properly interrupt VDM AMS When a VDM AMS is interrupted by Messages other than VDM, the AMS needs to be finished properly. Also start a VDM AMS if receiving SVDM Commands from the port partner to complement the functionality of tcpm_vdm_ams(). Fixes: 0908c5aca31e ("usb: typec: tcpm: AMS and Collision Avoidance") Cc: stable Reviewed-by: Guenter Roeck Acked-by: Heikki Krogerus Signed-off-by: Kyle Tso Link: https://lore.kernel.org/r/20210523015855.1785484-2-kyletso@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 8fdfd7f65ad7..6ea5df3782cf 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -1550,6 +1550,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, if (PD_VDO_SVDM_VER(p[0]) < svdm_version) typec_partner_set_svdm_version(port->partner, PD_VDO_SVDM_VER(p[0])); + + tcpm_ams_start(port, DISCOVER_IDENTITY); /* 6.4.4.3.1: Only respond as UFP (device) */ if (port->data_role == TYPEC_DEVICE && port->nr_snk_vdo) { @@ -1568,14 +1570,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, } break; case CMD_DISCOVER_SVID: + tcpm_ams_start(port, DISCOVER_SVIDS); break; case CMD_DISCOVER_MODES: + tcpm_ams_start(port, DISCOVER_MODES); break; case CMD_ENTER_MODE: + tcpm_ams_start(port, DFP_TO_UFP_ENTER_MODE); break; case CMD_EXIT_MODE: + tcpm_ams_start(port, DFP_TO_UFP_EXIT_MODE); break; case CMD_ATTENTION: + tcpm_ams_start(port, ATTENTION); /* Attention command does not have response */ *adev_action = ADEV_ATTENTION; return 0; @@ -2287,6 +2294,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port, bool frs_enable; int ret; + if (tcpm_vdm_ams(port) && type != PD_DATA_VENDOR_DEF) { + port->vdm_state = VDM_STATE_ERR_BUSY; + tcpm_ams_finish(port); + mod_vdm_delayed_work(port, 0); + } + switch (type) { case PD_DATA_SOURCE_CAP: for (i = 0; i < cnt; i++) @@ -2459,6 +2472,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); enum tcpm_state next_state; + /* + * Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in + * VDM AMS if waiting for VDM responses and will be handled later. + */ + if (tcpm_vdm_ams(port) && type != PD_CTRL_NOT_SUPP && type != PD_CTRL_GOOD_CRC) { + port->vdm_state = VDM_STATE_ERR_BUSY; + tcpm_ams_finish(port); + mod_vdm_delayed_work(port, 0); + } + switch (type) { case PD_CTRL_GOOD_CRC: case PD_CTRL_PING: @@ -2717,6 +2740,13 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port, enum pd_ext_msg_type type = pd_header_type_le(msg->header); unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + /* stopping VDM state machine if interrupted by other Messages */ + if (tcpm_vdm_ams(port)) { + port->vdm_state = VDM_STATE_ERR_BUSY; + tcpm_ams_finish(port); + mod_vdm_delayed_work(port, 0); + } + if (!(le16_to_cpu(msg->ext_msg.header) & PD_EXT_HDR_CHUNKED)) { tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS); tcpm_log(port, "Unchunked extended messages unsupported"); -- cgit From a20dcf53ea9836387b229c4878f9559cf1b55b71 Mon Sep 17 00:00:00 2001 From: Kyle Tso Date: Sun, 23 May 2021 09:58:55 +0800 Subject: usb: typec: tcpm: Respond Not_Supported if no snk_vdo If snk_vdo is not populated from fwnode, it implies the port does not support responding to SVDM commands. Not_Supported Message shall be sent if the contract is in PD3. And for PD2, the port shall ignore the commands. Fixes: 193a68011fdc ("staging: typec: tcpm: Respond to Discover Identity commands") Cc: stable Reviewed-by: Guenter Roeck Acked-by: Heikki Krogerus Signed-off-by: Kyle Tso Link: https://lore.kernel.org/r/20210523015855.1785484-3-kyletso@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 6ea5df3782cf..9ce8c9af4da5 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2430,7 +2430,10 @@ static void tcpm_pd_data_request(struct tcpm_port *port, NONE_AMS); break; case PD_DATA_VENDOR_DEF: - tcpm_handle_vdm_request(port, msg->payload, cnt); + if (tcpm_vdm_ams(port) || port->nr_snk_vdo) + tcpm_handle_vdm_request(port, msg->payload, cnt); + else if (port->negotiated_rev > PD_REV20) + tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS); break; case PD_DATA_BIST: port->bist_request = le32_to_cpu(msg->payload[0]); -- cgit From e752dbc59e1241b13b8c4f7b6eb582862e7668fe Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 24 May 2021 15:01:55 +0900 Subject: usb: gadget: udc: renesas_usb3: Fix a race in usb3_start_pipen() The usb3_start_pipen() is called by renesas_usb3_ep_queue() and usb3_request_done_pipen() so that usb3_start_pipen() is possible to cause a race when getting usb3_first_req like below: renesas_usb3_ep_queue() spin_lock_irqsave() list_add_tail() spin_unlock_irqrestore() usb3_start_pipen() usb3_first_req = usb3_get_request() --- [1] --- interrupt --- usb3_irq_dma_int() usb3_request_done_pipen() usb3_get_request() usb3_start_pipen() usb3_first_req = usb3_get_request() ... (the req is possible to be finished in the interrupt) The usb3_first_req [1] above may have been finished after the interrupt ended so that this driver caused to start a transfer wrongly. To fix this issue, getting/checking the usb3_first_req are under spin_lock_irqsave() in the same section. Fixes: 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller") Cc: stable Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210524060155.1178724-1-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/renesas_usb3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 0c418ce50ba0..f1b35a39d1ba 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1488,7 +1488,7 @@ static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep, struct renesas_usb3_request *usb3_req) { struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep); - struct renesas_usb3_request *usb3_req_first = usb3_get_request(usb3_ep); + struct renesas_usb3_request *usb3_req_first; unsigned long flags; int ret = -EAGAIN; u32 enable_bits = 0; @@ -1496,7 +1496,8 @@ static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep, spin_lock_irqsave(&usb3->lock, flags); if (usb3_ep->halt || usb3_ep->started) goto out; - if (usb3_req != usb3_req_first) + usb3_req_first = __usb3_get_request(usb3_ep); + if (!usb3_req_first || usb3_req != usb3_req_first) goto out; if (usb3_pn_change(usb3, usb3_ep->num) < 0) -- cgit From a80c203c3f1c06d2201c19ae071d0ae770a2b1ca Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 25 May 2021 10:40:59 +0300 Subject: xhci: fix giving back URB with incorrect status regression in 5.12 5.12 kernel changes how xhci handles cancelled URBs and halted endpoints. Among these changes cancelled and stalled URBs are no longer given back before they are cleared from xHC hardware cache. These changes unfortunately cleared the -EPIPE status of a stalled transfer in one case before giving bak the URB, causing a USB card reader to fail from working. Fixes: 674f8438c121 ("xhci: split handling halted endpoints into two steps") Cc: # 5.12 Reported-by: Peter Ganzhorn Tested-by: Peter Ganzhorn Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20210525074100.1154090-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a8e4189277da..256d336354a0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -828,14 +828,10 @@ static void xhci_giveback_invalidated_tds(struct xhci_virt_ep *ep) list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) { - /* - * Doesn't matter what we pass for status, since the core will - * just overwrite it (because the URB has been unlinked). - */ ring = xhci_urb_to_transfer_ring(ep->xhci, td->urb); if (td->cancel_status == TD_CLEARED) - xhci_td_cleanup(ep->xhci, td, ring, 0); + xhci_td_cleanup(ep->xhci, td, ring, td->status); if (ep->xhci->xhc_state & XHCI_STATE_DYING) return; -- cgit From a7f2e9272aff1ccfe0fc801dab1d5a7a1c6b7ed2 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 25 May 2021 10:41:00 +0300 Subject: xhci: Fix 5.12 regression of missing xHC cache clearing command after a Stall If endpoints halts due to a stall then the dequeue pointer read from hardware may already be set ahead of the stalled TRB. After commit 674f8438c121 ("xhci: split handling halted endpoints into two steps") in 5.12 xhci driver won't issue a Set TR Dequeue if hardware dequeue pointer is already in the right place. Turns out the "Set TR Dequeue pointer" command is anyway needed as it in addition to moving the dequeue pointer also clears endpoint state and cache. Fixes: 674f8438c121 ("xhci: split handling halted endpoints into two steps") Cc: # 5.12 Reported-by: Peter Ganzhorn Tested-by: Peter Ganzhorn Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20210525074100.1154090-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 256d336354a0..6acd2329e08d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -933,14 +933,18 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) continue; } /* - * If ring stopped on the TD we need to cancel, then we have to + * If a ring stopped on the TD we need to cancel then we have to * move the xHC endpoint ring dequeue pointer past this TD. + * Rings halted due to STALL may show hw_deq is past the stalled + * TD, but still require a set TR Deq command to flush xHC cache. */ hw_deq = xhci_get_hw_deq(xhci, ep->vdev, ep->ep_index, td->urb->stream_id); hw_deq &= ~0xf; - if (trb_in_td(xhci, td->start_seg, td->first_trb, + if (td->cancel_status == TD_HALTED) { + cached_td = td; + } else if (trb_in_td(xhci, td->start_seg, td->first_trb, td->last_trb, hw_deq, false)) { switch (td->cancel_status) { case TD_CLEARED: /* TD is already no-op */ -- cgit