]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
usb: dwc3: gadget: Check END_TRANSFER completion
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Thu, 19 Dec 2019 02:14:44 +0000 (18:14 -0800)
committerPaolo Pisati <paolo.pisati@canonical.com>
Mon, 17 Feb 2020 09:57:38 +0000 (10:57 +0100)
BugLink: https://bugs.launchpad.net/bugs/1863588
commit c58d8bfc77a2c7f6ff6339b58c9fca7ae6f57e70 upstream.

While the END_TRANSFER command is sent but not completed, any request
dequeue during this time will cause the driver to issue the END_TRANSFER
command. The driver needs to submit the command only once to stop the
controller from processing further. The controller may take more time to
process the same command multiple times unnecessarily. Let's add a flag
DWC3_EP_END_TRANSFER_PENDING to check for this condition.

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>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c

index 1c8b349379af24fcd9c1e6e48e137799398363a7..da0af11fbc1a12b61cdcaa0c9efc54e78dfb9948 100644 (file)
@@ -688,6 +688,7 @@ struct dwc3_ep {
 #define DWC3_EP_STALL          BIT(1)
 #define DWC3_EP_WEDGE          BIT(2)
 #define DWC3_EP_TRANSFER_STARTED BIT(3)
+#define DWC3_EP_END_TRANSFER_PENDING BIT(4)
 #define DWC3_EP_PENDING_REQUEST        BIT(5)
 
        /* This last one is specific to EP0 */
index fd1b100d2927eecb57c2fb86f1d52ee24bfaa57b..6dee4dabc0a435f72e18527e0d05814284d278dc 100644 (file)
@@ -1136,8 +1136,10 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
        case DWC3_DEPEVT_EPCMDCMPLT:
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
-               if (cmd == DWC3_DEPCMD_ENDTRANSFER)
+               if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
+                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
                        dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+               }
                break;
        }
 }
index 154f3f3e8cff849754904721e2f0730f25fff7cd..25d237d0f6a9f83d490f9b631c947fce8db11b97 100644 (file)
@@ -2625,6 +2625,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
                if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
+                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
                        dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
                        dwc3_gadget_ep_cleanup_cancelled_requests(dep);
                }
@@ -2683,7 +2684,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
        u32 cmd;
        int ret;
 
-       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
+       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
+           (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
                return;
 
        /*
@@ -2728,6 +2730,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
 
        if (!interrupt)
                dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+       else
+               dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
 
        if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
                udelay(100);