| From 1211eb6fd52b86078bdcc07add8cb2401b9bae05 Mon Sep 17 00:00:00 2001 |
| From: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com> |
| Date: Mon, 27 Jan 2020 19:30:46 +0000 |
| Subject: [PATCH] usb: dwc3: gadget: Check for IOC/LST bit in TRB->ctrl fields |
| |
| commit 5ee858975b13a9b40db00f456989a689fdbb296c upstream. |
| |
| The current code in dwc3_gadget_ep_reclaim_completed_trb() will |
| check for IOC/LST bit in the event->status and returns if |
| IOC/LST bit is set. This logic doesn't work if multiple TRBs |
| are queued per request and the IOC/LST bit is set on the last |
| TRB of that request. |
| |
| Consider an example where a queued request has multiple queued |
| TRBs and IOC/LST bit is set only for the last TRB. In this case, |
| the core generates XferComplete/XferInProgress events only for |
| the last TRB (since IOC/LST are set only for the last TRB). As |
| per the logic in dwc3_gadget_ep_reclaim_completed_trb() |
| event->status is checked for IOC/LST bit and returns on the |
| first TRB. This leaves the remaining TRBs left unhandled. |
| |
| Similarly, if the gadget function enqueues an unaligned request |
| with sglist already in it, it should fail the same way, since we |
| will append another TRB to something that already uses more than |
| one TRB. |
| |
| To aviod this, this patch changes the code to check for IOC/LST |
| bits in TRB->ctrl instead. |
| |
| At a practical level, this patch resolves USB transfer stalls seen |
| with adb on dwc3 based HiKey960 after functionfs gadget added |
| scatter-gather support around v4.20. |
| |
| Cc: Felipe Balbi <balbi@kernel.org> |
| Cc: Yang Fei <fei.yang@intel.com> |
| Cc: Thinh Nguyen <thinhn@synopsys.com> |
| Cc: Tejas Joglekar <tejas.joglekar@synopsys.com> |
| Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com> |
| Cc: Jack Pham <jackp@codeaurora.org> |
| Cc: Todd Kjos <tkjos@google.com> |
| Cc: Greg KH <gregkh@linuxfoundation.org> |
| Cc: Linux USB List <linux-usb@vger.kernel.org> |
| Cc: stable <stable@vger.kernel.org> |
| Tested-by: Tejas Joglekar <tejas.joglekar@synopsys.com> |
| Reviewed-by: Thinh Nguyen <thinhn@synopsys.com> |
| Signed-off-by: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com> |
| [jstultz: forward ported to mainline, reworded commit log, reworked |
| to only check trb->ctrl as suggested by Felipe] |
| Signed-off-by: John Stultz <john.stultz@linaro.org> |
| Signed-off-by: Felipe Balbi <balbi@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c |
| index 989388505650..c34202029724 100644 |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -2388,7 +2388,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, |
| if (event->status & DEPEVT_STATUS_SHORT && !chain) |
| return 1; |
| |
| - if (event->status & DEPEVT_STATUS_IOC) |
| + if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || |
| + (trb->ctrl & DWC3_TRB_CTRL_LST)) |
| return 1; |
| |
| return 0; |
| -- |
| 2.7.4 |
| |