aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
authorWesley Cheng <quic_wcheng@quicinc.com>2022-09-01 12:36:21 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-07 16:26:26 +0200
commit2b2da6574e77ebf83c0df6d8b838bc37764c4bfa (patch)
tree7b5923d829149b0a0b27890cf669c89afc325f61 /drivers/usb/dwc3/gadget.c
parentUSB/ARM: Switch S3C2410 UDC to GPIO descriptors (diff)
downloadlinux-dev-2b2da6574e77ebf83c0df6d8b838bc37764c4bfa.tar.xz
linux-dev-2b2da6574e77ebf83c0df6d8b838bc37764c4bfa.zip
usb: dwc3: Avoid unmapping USB requests if endxfer is not complete
If DWC3_EP_DELAYED_STOP is set during stop active transfers, then do not continue attempting to unmap request buffers during dwc3_remove_requests(). This can lead to SMMU faults, as the controller has not stopped the processing of the TRB. Defer this sequence to the EP0 out start, which ensures that there are no pending SETUP transactions before issuing the endxfer. Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> Link: https://lore.kernel.org/r/20220901193625.8727-2-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3a344ba0b292..b9189045e4cb 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -965,12 +965,16 @@ out:
return 0;
}
-static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status)
+void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status)
{
struct dwc3_request *req;
dwc3_stop_active_transfer(dep, true, false);
+ /* If endxfer is delayed, avoid unmapping requests */
+ if (dep->flags & DWC3_EP_DELAY_STOP)
+ return;
+
/* - giveback all requests to gadget driver */
while (!list_empty(&dep->started_list)) {
req = next_request(&dep->started_list);