usb: dwc3: gadget: prepare TRBs on update transfers too
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 12 May 2016 11:08:34 +0000 (14:08 +0300)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 20 Jun 2016 09:30:05 +0000 (12:30 +0300)
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: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc3/gadget.c

index ae55f500cdbd2b6e8b505a3a60bfc9e70ebb92c5..236c231114df288dd6ad5c4158a1bd13287d97b2 100644 (file)
@@ -880,16 +880,40 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
        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
  * @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
  * transfers. The function returns once there are no more TRBs available or
  * 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;
        u32                     trbs_left;
@@ -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);
 
-       trbs_left = dep->trb_dequeue - dep->trb_enqueue;
-
-       /*
-        * 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;
+       trbs_left = dwc3_calc_trbs_left(dep);
 
        list_for_each_entry_safe(req, n, &dep->pending_list, list) {
                unsigned        length;
@@ -996,12 +1004,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
         */
        if (start_new) {
                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 = next_request(&dep->started_list);
        } else {
-               dwc3_prepare_trbs(dep, start_new);
+               dwc3_prepare_trbs(dep);
 
                /*
                 * req points to the first request where HWO changed from 0 to 1