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>
This commit is contained in:
Родитель
787f51f210
Коммит
2b2da6574e
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче