usb: dwc3: gadget: Improve TRB ZLP setup
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Thu, 24 Sep 2020 08:21:36 +0000 (01:21 -0700)
committerFelipe Balbi <balbi@kernel.org>
Fri, 2 Oct 2020 06:57:44 +0000 (09:57 +0300)
For OUT requests that requires extra TRBs for ZLP. We don't need to
prepare the 0-length TRB and simply prepare the MPS size TRB. This
reduces 1 TRB needed to prepare for ZLP.

Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/dwc3/gadget.c

index e74d97a..97790f5 100644 (file)
@@ -1132,11 +1132,12 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
                        chain = false;
 
                if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
-                       req->needs_extra_trb = true;
-
                        /* prepare normal TRB */
-                       dwc3_prepare_one_trb(dep, req, trb_length,
+                       if (req->request.length) {
+                               req->needs_extra_trb = true;
+                               dwc3_prepare_one_trb(dep, req, trb_length,
                                        true, i, false);
+                       }
 
                        /* Now prepare one extra TRB to align transfer size */
                        dwc3_prepare_one_trb(dep, req, maxp - rem,
@@ -1151,13 +1152,9 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
                                        true, i, false);
 
                        /* Prepare one extra TRB to handle ZLP */
-                       dwc3_prepare_one_trb(dep, req, 0,
-                                       !req->direction, 1, true);
-
-                       /* Prepare one more TRB to handle MPS alignment */
-                       if (!req->direction)
-                               dwc3_prepare_one_trb(dep, req, maxp,
-                                               false, 1, true);
+                       dwc3_prepare_one_trb(dep, req,
+                                       req->direction ? 0 : maxp,
+                                       false, 1, true);
                } else {
                        dwc3_prepare_one_trb(dep, req, trb_length,
                                        chain, i, false);
@@ -1198,10 +1195,11 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
        unsigned int rem = length % maxp;
 
        if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
-               req->needs_extra_trb = true;
-
                /* prepare normal TRB */
-               dwc3_prepare_one_trb(dep, req, length, true, 0, false);
+               if (req->request.length) {
+                       req->needs_extra_trb = true;
+                       dwc3_prepare_one_trb(dep, req, length, true, 0, false);
+               }
 
                /* Now prepare one extra TRB to align transfer size */
                dwc3_prepare_one_trb(dep, req, maxp - rem, false, 1, true);
@@ -1214,11 +1212,8 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
                dwc3_prepare_one_trb(dep, req, length, true, 0, false);
 
                /* Prepare one extra TRB to handle ZLP */
-               dwc3_prepare_one_trb(dep, req, 0, !req->direction, 1, true);
-
-               /* Prepare one more TRB to handle MPS alignment for OUT */
-               if (!req->direction)
-                       dwc3_prepare_one_trb(dep, req, maxp, false, 1, true);
+               dwc3_prepare_one_trb(dep, req, req->direction ? 0 : maxp,
+                               false, 1, true);
        } else {
                dwc3_prepare_one_trb(dep, req, length, false, 0, false);
        }
@@ -2621,12 +2616,12 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
        }
 
        /*
-        * If we're dealing with unaligned size OUT transfer, we will be left
-        * with one TRB pending in the ring. We need to manually clear HWO bit
-        * from that TRB.
+        * We use bounce buffer for requests that needs extra TRB or OUT ZLP. If
+        * this TRB points to the bounce buffer address, it's a MPS alignment
+        * TRB. Don't add it to req->remaining calculation.
         */
-
-       if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) {
+       if (trb->bpl == lower_32_bits(dep->dwc->bounce_addr) &&
+           trb->bph == upper_32_bits(dep->dwc->bounce_addr)) {
                trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
                return 1;
        }
@@ -2707,17 +2702,8 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
                goto out;
 
        if (req->needs_extra_trb) {
-               unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
-
                ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
                                status);
-
-               /* Reclaim MPS padding TRB for ZLP */
-               if (!req->direction && req->request.zero && req->request.length &&
-                   !usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                   (IS_ALIGNED(req->request.length, maxp)))
-                       ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status);
-
                req->needs_extra_trb = false;
        }