diff options
author | Wesley Cheng <quic_wcheng@quicinc.com> | 2022-09-20 01:12:13 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-09-22 15:52:29 +0200 |
commit | 76bff31c7fba6cc21bf8f9785572484d54d31878 (patch) | |
tree | b43fb6909a133801663e419b7b1e412a0f991b20 | |
parent | usb: mon: make mmapped memory read only (diff) | |
download | linux-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.c | 11 |
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; } |