Commit a2841f41 authored by Thinh Nguyen's avatar Thinh Nguyen Committed by Felipe Balbi
Browse files

usb: dwc3: gadget: Improve TRB ZLP setup



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: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@kernel.org>
parent 2b80357b
Loading
Loading
Loading
Loading
+18 −32
Original line number Diff line number Diff line
@@ -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 */
			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,12 +1152,8 @@ 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,
			dwc3_prepare_one_trb(dep, req,
					req->direction ? 0 : maxp,
					false, 1, true);
		} else {
			dwc3_prepare_one_trb(dep, req, trb_length,
@@ -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 */
		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;
	}