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.ba...@linux.intel.com>
---
 drivers/usb/dwc3/gadget.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 84b449b17160..bca4150e3cf5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1023,6 +1023,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);
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to