From f1d47b5138b26d327c0424fb1dfb2107fe07e6fb Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 1 Sep 2022 12:36:21 -0700 Subject: [PATCH] UPSTREAM: 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. Change-Id: I576922c1a9566507f8ac268a4fc2c4bfb4129aee Reviewed-by: Thinh Nguyen Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/r/20220901193625.8727-2-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit 2b2da6574e77ebf83c0df6d8b838bc37764c4bfa) --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 5 ++++- drivers/usb/dwc3/gadget.c | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 89d6d0fe0759..8930145d412c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1576,6 +1576,7 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd, u32 param); void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt); 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; } diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 980367d3c3c1..7ae1b4a663d1 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -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); } } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 28115d6672e8..9c0ed2496785 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1099,12 +1099,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);