diff mbox series

[1/3] usb: dwc3: gadget: reclaim the whole started list when request was missed

Message ID 20240307-dwc3-gadget-complete-irq-v1-1-4fe9ac0ba2b7@pengutronix.de (mailing list archive)
State New
Headers show
Series usb: dwc3: gadget: improve abbort transfer abort by adding more conditions | expand

Commit Message

Michael Grzeschik March 7, 2024, 3:22 p.m. UTC
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@pengutronix.de>
---
 drivers/usb/dwc3/gadget.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff mbox series

Patch

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)