diff mbox series

[04/10] usb: dwc3: gadget: Improve TRB ZLP setup

Message ID a1af83c8fea6cccbb861ccb08d2776bfd1b525f7.1600935293.git.Thinh.Nguyen@synopsys.com
State New
Headers show
Series usb: dwc3: gadget: Revise preparation for extra TRBs | expand

Commit Message

Thinh Nguyen Sept. 24, 2020, 8:21 a.m. UTC
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>
---
 drivers/usb/dwc3/gadget.c | 50 ++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 32 deletions(-)
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c0309ad34d28..e49930a7acae 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -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);
 	}
@@ -2615,12 +2610,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;
 	}
@@ -2701,17 +2696,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;
 	}