| From da10bcdd6f70dc9977f2cf18f4783cf78520623a Mon Sep 17 00:00:00 2001 |
| From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| Date: Wed, 18 Dec 2019 18:14:50 -0800 |
| Subject: usb: dwc3: gadget: Delay starting transfer |
| |
| From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| |
| commit da10bcdd6f70dc9977f2cf18f4783cf78520623a upstream. |
| |
| If the END_TRANSFER command hasn't completed yet, then don't send the |
| START_TRANSFER command. The controller may not be able to start if |
| that's the case. Some controller revisions depend on this. See |
| commit 76a638f8ac0d ("usb: dwc3: gadget: wait for End Transfer to |
| complete"). Let's only send START_TRANSFER command after the |
| END_TRANSFER command had completed. |
| |
| Fixes: 3aec99154db3 ("usb: dwc3: gadget: remove DWC3_EP_END_TRANSFER_PENDING") |
| Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> |
| Signed-off-by: Felipe Balbi <balbi@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/dwc3/core.h | 1 + |
| drivers/usb/dwc3/gadget.c | 11 +++++++++++ |
| 2 files changed, 12 insertions(+) |
| |
| --- a/drivers/usb/dwc3/core.h |
| +++ b/drivers/usb/dwc3/core.h |
| @@ -690,6 +690,7 @@ struct dwc3_ep { |
| #define DWC3_EP_TRANSFER_STARTED BIT(3) |
| #define DWC3_EP_END_TRANSFER_PENDING BIT(4) |
| #define DWC3_EP_PENDING_REQUEST BIT(5) |
| +#define DWC3_EP_DELAY_START BIT(6) |
| |
| /* This last one is specific to EP0 */ |
| #define DWC3_EP0_DIR_IN BIT(31) |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -1447,6 +1447,12 @@ static int __dwc3_gadget_ep_queue(struct |
| list_add_tail(&req->list, &dep->pending_list); |
| req->status = DWC3_REQUEST_STATUS_QUEUED; |
| |
| + /* Start the transfer only after the END_TRANSFER is completed */ |
| + if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { |
| + dep->flags |= DWC3_EP_DELAY_START; |
| + return 0; |
| + } |
| + |
| /* |
| * NOTICE: Isochronous endpoints should NEVER be prestarted. We must |
| * wait for a XferNotReady event so we will know what's the current |
| @@ -2628,6 +2634,11 @@ static void dwc3_endpoint_interrupt(stru |
| dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; |
| dep->flags &= ~DWC3_EP_TRANSFER_STARTED; |
| dwc3_gadget_ep_cleanup_cancelled_requests(dep); |
| + if ((dep->flags & DWC3_EP_DELAY_START) && |
| + !usb_endpoint_xfer_isoc(dep->endpoint.desc)) |
| + __dwc3_gadget_kick_transfer(dep); |
| + |
| + dep->flags &= ~DWC3_EP_DELAY_START; |
| } |
| break; |
| case DWC3_DEPEVT_STREAMEVT: |