On EXDEV/Missed status interrupt, the handler has to stop the running transfer and ensure that every request complete call will not run kick on the current transfer. This is achieved by calling dwc3_stop_active_transfer early before cleaning up the started request list. If the current transfer was stopped we can not keep all requests in the hardware and have to reclaim them all. Since the requests could have no_interrupt bit the cleanup on an stopped pipeline has to remove every request and may not stop on the one that has the IOC bit set. To ensure that the dwc3_gadget_ep_cleanup_completed_request will iterate over every request in that case, we skip the stop condition in reclaim_completed_trb if the current transfer was stopped by checking for DWC3_EP_END_TRANSFER_PENDING bit set. Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> --- drivers/usb/dwc3/gadget.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 40c52dbc28d3b..b9fce7b1dcdec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3404,7 +3404,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC) return 1; - if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || + if (((trb->ctrl & DWC3_TRB_CTRL_IOC) && + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) || (trb->ctrl & DWC3_TRB_CTRL_LST)) return 1; @@ -3568,6 +3569,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, struct dwc3 *dwc = dep->dwc; bool no_started_trb = true; + if (status == -EXDEV) + dwc3_stop_active_transfer(dep, true, true); + dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) @@ -3578,7 +3582,7 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && list_empty(&dep->started_list) && - (list_empty(&dep->pending_list) || status == -EXDEV)) + (list_empty(&dep->pending_list))) dwc3_stop_active_transfer(dep, true, true); else if (dwc3_gadget_ep_should_continue(dep)) if (__dwc3_gadget_kick_transfer(dep) == 0) -- 2.39.2