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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux