usb: dwc3: Avoid unmapping USB requests if endxfer is not complete
authorWesley Cheng <quic_wcheng@quicinc.com>
Thu, 1 Sep 2022 19:36:21 +0000 (12:36 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Sep 2022 14:26:26 +0000 (16:26 +0200)
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>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c

index 4fe4287dc934e7f441166f89018a87774268d44f..7c9368145f3771462cc3640efe255a365f4fa516 100644 (file)
@@ -1560,6 +1560,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
 int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
                u32 param);
 void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
+void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status);
 #else
 static inline int dwc3_gadget_init(struct dwc3 *dwc)
 { return 0; }
index 33cee0089609a084f11c3653499189aa7b5022ec..61de693461da4780bb9017b67a0d37e823b1b7ee 100644 (file)
@@ -293,7 +293,10 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
                        continue;
 
                dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP;
-               dwc3_stop_active_transfer(dwc3_ep, true, true);
+               if (dwc->connected)
+                       dwc3_stop_active_transfer(dwc3_ep, true, true);
+               else
+                       dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
        }
 }
 
index 3a344ba0b2927f7ae336994f736d914202099a12..b9189045e4cb7d933f84d2a713d53867595ea7ad 100644 (file)
@@ -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);