summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2020-09-24 01:21:36 -0700
committerFelipe Balbi <balbi@kernel.org>2020-10-02 09:57:44 +0300
commita2841f41d07fc85cf47d13fda30e254c5413e514 (patch)
tree7d6abc7062551b4b4af847f596e7932a80357d09 /drivers/usb/dwc3
parent2b80357b773c4c572233d191cd849d25311c48fd (diff)
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: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/gadget.c50
1 files changed, 18 insertions, 32 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e74d97aa8b53..97790f55be1a 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);
}
@@ -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;
}