summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWesley Cheng <quic_wcheng@quicinc.com>2022-09-20 01:12:13 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-22 15:52:29 +0200
commit76bff31c7fba6cc21bf8f9785572484d54d31878 (patch)
treeb43fb6909a133801663e419b7b1e412a0f991b20
parentusb: mon: make mmapped memory read only (diff)
downloadlinux-76bff31c7fba6cc21bf8f9785572484d54d31878.tar.xz
linux-76bff31c7fba6cc21bf8f9785572484d54d31878.zip
usb: dwc3: gadget: Do not clear ep delayed stop flag during ep disable
DWC3_EP_DELAYED_STOP is utilized to defer issuing the end transfer command until the subsequent SETUP stage, in order to avoid end transfer timeouts. During cable disconnect scenarios, __dwc3_gadget_ep_disable() is responsible for ensuring endpoints have no active transfers pending. Since dwc3_remove_request() can now exit early if the EP delayed stop is set, avoid clearing all DEP flags, otherwise the transition back into the SETUP stage won't issue an endxfer command. Fixes: 2b2da6574e77 ("usb: dwc3: Avoid unmapping USB requests if endxfer is not complete") Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> Link: https://lore.kernel.org/r/20220919231213.21364-1-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/gadget.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index bedda57a5015..079cd333632e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1011,6 +1011,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
u32 reg;
+ u32 mask;
trace_dwc3_gadget_ep_disable(dep);
@@ -1032,7 +1033,15 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->stream_capable = false;
dep->type = 0;
- dep->flags &= DWC3_EP_TXFIFO_RESIZED;
+ mask = DWC3_EP_TXFIFO_RESIZED;
+ /*
+ * dwc3_remove_requests() can exit early if DWC3 EP delayed stop is
+ * set. Do not clear DEP flags, so that the end transfer command will
+ * be reattempted during the next SETUP stage.
+ */
+ if (dep->flags & DWC3_EP_DELAY_STOP)
+ mask |= (DWC3_EP_DELAY_STOP | DWC3_EP_TRANSFER_STARTED);
+ dep->flags &= mask;
return 0;
}