@@ -3563,6 +3563,21 @@ static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep,
dep->frame_number = event->parameters;
}
+static int dwc3_gadget_ep_check_missed_requests(struct dwc3_ep *dep)
+{
+ struct dwc3_request *req;
+ struct dwc3_request *tmp;
+
+ list_for_each_entry_safe(req, tmp, &dep->started_list, list) {
+ struct dwc3_trb *trb = req->trb;
+
+ if (DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC)
+ return -EXDEV;
+ }
+
+ return 0;
+}
+
static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
const struct dwc3_event_depevt *event, int status)
{
@@ -3584,7 +3599,7 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
transfer_in_flight = trb->ctrl & DWC3_TRB_CTRL_HWO;
}
- if (status == -EXDEV || !transfer_in_flight)
+ if (status == -EXDEV || !transfer_in_flight || dwc3_gadget_ep_check_missed_requests(dep))
dwc3_stop_active_transfer(dep, true, true);
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
The function dwc3_gadget_endpoint_trbs_complete will be called with the interrupt event. This event is only representing the interrupt reason of the exact trb that had IOC enabled. In the current approach the function dwc3_gadget_ep_cleanup_completed_requests will give back and complete the requests with the corresponding trb status and therefor will correctly return the missed requests that are already finished. Since inbetween those complete functioncalls of the properly finished and the missed trbs, a missed transfer could get new trbs enqueued with the updatecmd, this will just lead to more missed trbs. To break the cascading scenario this patch is checking all trbs from the started list for any trb that has the missed trb status before even calling the complete handler but stopping the transfer instead. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> --- drivers/usb/dwc3/gadget.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)