summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <felipe.balbi@linux.intel.com>2016-10-25 13:48:52 +0300
committerFelipe Balbi <felipe.balbi@linux.intel.com>2016-11-03 10:38:40 +0200
commitd86c5a676e5b1ee89da0cf9c845760c36cfde6d3 (patch)
treefe6d3403cd3c691453b25d5b9b94bba6fa09e02d /drivers/usb/dwc3
parente62c5bc57367ac277b932571943c9a09e737ad88 (diff)
downloadlinux-d86c5a676e5b1ee89da0cf9c845760c36cfde6d3.tar.bz2
usb: dwc3: gadget: always try to prepare on started_list first
In cases where we're given an SG-list which is longer than the amount of currently available TRBs, we will be left with the same request on started_list and we should prioritize that request over possible new requests on pending_list. That's a way to guarantee requests complete in order. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/gadget.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4e66e91fe883..317bb9aed4a4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1020,6 +1020,24 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
if (!dwc3_calc_trbs_left(dep))
return;
+ /*
+ * We can get in a situation where there's a request in the started list
+ * but there weren't enough TRBs to fully kick it in the first time
+ * around, so it has been waiting for more TRBs to be freed up.
+ *
+ * In that case, we should check if we have a request with pending_sgs
+ * in the started list and prepare TRBs for that request first,
+ * otherwise we will prepare TRBs completely out of order and that will
+ * break things.
+ */
+ list_for_each_entry(req, &dep->started_list, list) {
+ if (req->num_pending_sgs > 0)
+ dwc3_prepare_one_trb_sg(dep, req);
+
+ if (!dwc3_calc_trbs_left(dep))
+ return;
+ }
+
list_for_each_entry_safe(req, n, &dep->pending_list, list) {
if (req->num_pending_sgs > 0)
dwc3_prepare_one_trb_sg(dep, req);