]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
usb: dwc3: gadget: Delay starting transfer
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Thu, 19 Dec 2019 02:14:50 +0000 (18:14 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2020 12:36:41 +0000 (04:36 -0800)
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
drivers/usb/dwc3/gadget.c

index da0af11fbc1a12b61cdcaa0c9efc54e78dfb9948..77c4a9abe3652679993bfb92527dc666083f4226 100644 (file)
@@ -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)
index 25d237d0f6a9f83d490f9b631c947fce8db11b97..8b95be8970784c6c826df955e8eacd1e5fdf9cfa 100644 (file)
@@ -1447,6 +1447,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
        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(struct dwc3 *dwc,
                        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: