diff options
| author | 2016-10-25 13:48:52 +0300 | |
|---|---|---|
| committer | 2016-11-03 10:38:40 +0200 | |
| commit | d86c5a676e5b1ee89da0cf9c845760c36cfde6d3 (patch) | |
| tree | fe6d3403cd3c691453b25d5b9b94bba6fa09e02d | |
| parent | usb: dwc3: gadget: tracking per-TRB remaining bytes (diff) | |
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>
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 18 |
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); |
