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>
This commit is contained in:
parent
2b80357b77
commit
a2841f41d0
@ -1132,11 +1132,12 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
|
|||||||
chain = false;
|
chain = false;
|
||||||
|
|
||||||
if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
|
if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
|
||||||
req->needs_extra_trb = true;
|
|
||||||
|
|
||||||
/* prepare normal TRB */
|
/* 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);
|
true, i, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now prepare one extra TRB to align transfer size */
|
/* Now prepare one extra TRB to align transfer size */
|
||||||
dwc3_prepare_one_trb(dep, req, maxp - rem,
|
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);
|
true, i, false);
|
||||||
|
|
||||||
/* Prepare one extra TRB to handle ZLP */
|
/* Prepare one extra TRB to handle ZLP */
|
||||||
dwc3_prepare_one_trb(dep, req, 0,
|
dwc3_prepare_one_trb(dep, req,
|
||||||
!req->direction, 1, true);
|
req->direction ? 0 : maxp,
|
||||||
|
false, 1, true);
|
||||||
/* Prepare one more TRB to handle MPS alignment */
|
|
||||||
if (!req->direction)
|
|
||||||
dwc3_prepare_one_trb(dep, req, maxp,
|
|
||||||
false, 1, true);
|
|
||||||
} else {
|
} else {
|
||||||
dwc3_prepare_one_trb(dep, req, trb_length,
|
dwc3_prepare_one_trb(dep, req, trb_length,
|
||||||
chain, i, false);
|
chain, i, false);
|
||||||
@ -1198,10 +1195,11 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
|
|||||||
unsigned int rem = length % maxp;
|
unsigned int rem = length % maxp;
|
||||||
|
|
||||||
if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
|
if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
|
||||||
req->needs_extra_trb = true;
|
|
||||||
|
|
||||||
/* prepare normal TRB */
|
/* 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 */
|
/* Now prepare one extra TRB to align transfer size */
|
||||||
dwc3_prepare_one_trb(dep, req, maxp - rem, false, 1, true);
|
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);
|
dwc3_prepare_one_trb(dep, req, length, true, 0, false);
|
||||||
|
|
||||||
/* Prepare one extra TRB to handle ZLP */
|
/* Prepare one extra TRB to handle ZLP */
|
||||||
dwc3_prepare_one_trb(dep, req, 0, !req->direction, 1, true);
|
dwc3_prepare_one_trb(dep, req, req->direction ? 0 : maxp,
|
||||||
|
false, 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);
|
|
||||||
} else {
|
} else {
|
||||||
dwc3_prepare_one_trb(dep, req, length, false, 0, false);
|
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
|
* We use bounce buffer for requests that needs extra TRB or OUT ZLP. If
|
||||||
* with one TRB pending in the ring. We need to manually clear HWO bit
|
* this TRB points to the bounce buffer address, it's a MPS alignment
|
||||||
* from that TRB.
|
* TRB. Don't add it to req->remaining calculation.
|
||||||
*/
|
*/
|
||||||
|
if (trb->bpl == lower_32_bits(dep->dwc->bounce_addr) &&
|
||||||
if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) {
|
trb->bph == upper_32_bits(dep->dwc->bounce_addr)) {
|
||||||
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
|
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2707,17 +2702,8 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (req->needs_extra_trb) {
|
if (req->needs_extra_trb) {
|
||||||
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
|
|
||||||
|
|
||||||
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
|
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
|
||||||
status);
|
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;
|
req->needs_extra_trb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user