usb: dwc3: gadget: Wait for transfer completion
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Wed, 6 May 2020 02:46:57 +0000 (19:46 -0700)
committerFelipe Balbi <balbi@kernel.org>
Mon, 25 May 2020 08:09:41 +0000 (11:09 +0300)
If a transfer is in-progress, any new request should not kick off
another transfer. The driver needs to wait for the current transfer to
complete before starting off the next transfer. Introduce a new flag
DWC3_EP_WAIT_TRANSFER_COMPLETE for this.

Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index 7204a83..b11183a 100644 (file)
@@ -701,6 +701,7 @@ struct dwc3_ep {
 #define DWC3_EP_END_TRANSFER_PENDING BIT(4)
 #define DWC3_EP_PENDING_REQUEST        BIT(5)
 #define DWC3_EP_DELAY_START    BIT(6)
+#define DWC3_EP_WAIT_TRANSFER_COMPLETE BIT(7)
 
        /* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN                BIT(31)
index 052f6dc..97c6a57 100644 (file)
@@ -1292,6 +1292,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
                return ret;
        }
 
+       if (dep->stream_capable && req->request.is_last)
+               dep->flags |= DWC3_EP_WAIT_TRANSFER_COMPLETE;
+
        return 0;
 }
 
@@ -1498,6 +1501,9 @@ 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;
 
+       if (dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE)
+               return 0;
+
        /* Start the transfer only after the END_TRANSFER is completed */
        if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
                dep->flags |= DWC3_EP_DELAY_START;
@@ -2735,7 +2741,8 @@ static void dwc3_gadget_endpoint_transfer_complete(struct dwc3_ep *dep,
        if (event->status & DEPEVT_STATUS_BUSERR)
                status = -ECONNRESET;
 
-       dwc3_gadget_endpoint_trbs_complete(dep, event, status);
+       if (dwc3_gadget_endpoint_trbs_complete(dep, event, status))
+               dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE;
 }
 
 static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep,