Commit c4233573 authored by Felipe Balbi's avatar Felipe Balbi

usb: dwc3: gadget: prepare TRBs on update transfers too

If we're updating transfers, we can also prepare as
many TRBs as we can fit in the ring. Let's start
doing that.

This patch 'solves' a limitation of how many TRBs we
can prepare when we're getting close the end of the
ring. Instead driver to prepare only up to end of
the ring, we check if we have space to wrap around
the ring properly.

Note that this only happens when our enqueue and
dequeue pointers are equal (which is the case for
bulk endpoints after an XferComplete event).
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 7f370ed0
...@@ -880,16 +880,40 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, ...@@ -880,16 +880,40 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
trace_dwc3_prepare_trb(dep, trb); trace_dwc3_prepare_trb(dep, trb);
} }
static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
{
struct dwc3_trb *tmp;
/*
* If enqueue & dequeue are equal than it is either full or empty.
*
* One way to know for sure is if the TRB right before us has HWO bit
* set or not. If it has, then we're definitely full and can't fit any
* more transfers in our ring.
*/
if (dep->trb_enqueue == dep->trb_dequeue) {
/* If we're full, enqueue/dequeue are > 0 */
if (dep->trb_enqueue) {
tmp = &dep->trb_pool[dep->trb_enqueue - 1];
if (tmp->ctrl & DWC3_TRB_CTRL_HWO)
return 0;
}
return DWC3_TRB_NUM - 1;
}
return dep->trb_dequeue - dep->trb_enqueue;
}
/* /*
* dwc3_prepare_trbs - setup TRBs from requests * dwc3_prepare_trbs - setup TRBs from requests
* @dep: endpoint for which requests are being prepared * @dep: endpoint for which requests are being prepared
* @starting: true if the endpoint is idle and no requests are queued.
* *
* The function goes through the requests list and sets up TRBs for the * The function goes through the requests list and sets up TRBs for the
* transfers. The function returns once there are no more TRBs available or * transfers. The function returns once there are no more TRBs available or
* it runs out of requests. * it runs out of requests.
*/ */
static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) static void dwc3_prepare_trbs(struct dwc3_ep *dep)
{ {
struct dwc3_request *req, *n; struct dwc3_request *req, *n;
u32 trbs_left; u32 trbs_left;
...@@ -897,23 +921,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) ...@@ -897,23 +921,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
trbs_left = dep->trb_dequeue - dep->trb_enqueue; trbs_left = dwc3_calc_trbs_left(dep);
/*
* If enqueue & dequeue are equal than it is either full or empty. If we
* are starting to process requests then we are empty. Otherwise we are
* full and don't do anything
*/
if (!trbs_left) {
if (!starting)
return;
trbs_left = DWC3_TRB_NUM;
}
/* The last TRB is a link TRB, not used for xfer */
if (trbs_left <= 1)
return;
list_for_each_entry_safe(req, n, &dep->pending_list, list) { list_for_each_entry_safe(req, n, &dep->pending_list, list) {
unsigned length; unsigned length;
...@@ -996,12 +1004,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, ...@@ -996,12 +1004,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
*/ */
if (start_new) { if (start_new) {
if (list_empty(&dep->started_list)) if (list_empty(&dep->started_list))
dwc3_prepare_trbs(dep, start_new); dwc3_prepare_trbs(dep);
/* req points to the first request which will be sent */ /* req points to the first request which will be sent */
req = next_request(&dep->started_list); req = next_request(&dep->started_list);
} else { } else {
dwc3_prepare_trbs(dep, start_new); dwc3_prepare_trbs(dep);
/* /*
* req points to the first request where HWO changed from 0 to 1 * req points to the first request where HWO changed from 0 to 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment