summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 113ec80dcc26..356a5a2af750 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1115,16 +1115,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
dep->name);
}
- /*
- * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
- * uframe number.
- */
- if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
- (dep->flags & DWC3_EP_MISSED_ISOC)) {
- __dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
- dep->flags &= ~DWC3_EP_MISSED_ISOC;
- }
-
return 0;
}
@@ -1686,14 +1676,29 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
dep->name);
- dep->current_uf = event->parameters &
- ~(dep->interval - 1);
+ /*
+ * If missed isoc occurred and there is
+ * no request queued then issue END
+ * TRANSFER, so that core generates
+ * next xfernotready and we will issue
+ * a fresh START TRANSFER.
+ * If there are still queued request
+ * then wait, do not issue either END
+ * or UPDATE TRANSFER, just attach next
+ * request in request_list during
+ * giveback.If any future queued request
+ * is successfully transferred then we
+ * will issue UPDATE TRANSFER for all
+ * request in the request_list.
+ */
dep->flags |= DWC3_EP_MISSED_ISOC;
} else {
dev_err(dwc->dev, "incomplete IN transfer %s\n",
dep->name);
status = -ECONNRESET;
}
+ } else {
+ dep->flags &= ~DWC3_EP_MISSED_ISOC;
}
} else {
if (count && (event->status & DEPEVT_STATUS_SHORT))
@@ -1720,6 +1725,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
break;
} while (1);
+ if (list_empty(&dep->req_queued) &&
+ (dep->flags & DWC3_EP_MISSED_ISOC)) {
+ dwc3_stop_active_transfer(dwc, dep->number);
+ dep->flags &= ~DWC3_EP_MISSED_ISOC;
+ return 1;
+ }
+
if ((event->status & DEPEVT_STATUS_IOC) &&
(trb->ctrl & DWC3_TRB_CTRL_IOC))
return 0;