usb: dwc3: gadget: Refactor preparing extra TRB
When the driver prepares the extra TRB, it uses bounce buffer. If we just add a new parameter to dwc3_prepare_one_trb() to indicate this, then we can refactor and simplify the driver quite a bit. dwc3_prepare_one_trb() also checks if a request had been moved to the started list. This is a prerequisite to subsequence patches improving the handling of extra TRBs. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
This commit is contained in:
parent
690e5c2dc2
commit
2b80357b77
|
@ -1060,10 +1060,11 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
|
||||||
* @trb_length: buffer size of the TRB
|
* @trb_length: buffer size of the TRB
|
||||||
* @chain: should this TRB be chained to the next?
|
* @chain: should this TRB be chained to the next?
|
||||||
* @node: only for isochronous endpoints. First TRB needs different type.
|
* @node: only for isochronous endpoints. First TRB needs different type.
|
||||||
|
* @use_bounce_buffer: set to use bounce buffer
|
||||||
*/
|
*/
|
||||||
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
|
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
|
||||||
struct dwc3_request *req, unsigned int trb_length,
|
struct dwc3_request *req, unsigned int trb_length,
|
||||||
unsigned int chain, unsigned int node)
|
unsigned int chain, unsigned int node, bool use_bounce_buffer)
|
||||||
{
|
{
|
||||||
struct dwc3_trb *trb;
|
struct dwc3_trb *trb;
|
||||||
dma_addr_t dma;
|
dma_addr_t dma;
|
||||||
|
@ -1072,7 +1073,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
|
||||||
unsigned int no_interrupt = req->request.no_interrupt;
|
unsigned int no_interrupt = req->request.no_interrupt;
|
||||||
unsigned int is_last = req->request.is_last;
|
unsigned int is_last = req->request.is_last;
|
||||||
|
|
||||||
if (req->request.num_sgs > 0)
|
if (use_bounce_buffer)
|
||||||
|
dma = dep->dwc->bounce_addr;
|
||||||
|
else if (req->request.num_sgs > 0)
|
||||||
dma = sg_dma_address(req->start_sg);
|
dma = sg_dma_address(req->start_sg);
|
||||||
else
|
else
|
||||||
dma = req->request.dma;
|
dma = req->request.dma;
|
||||||
|
@ -1129,56 +1132,35 @@ 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) {
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
struct dwc3_trb *trb;
|
|
||||||
|
|
||||||
req->needs_extra_trb = true;
|
req->needs_extra_trb = true;
|
||||||
|
|
||||||
/* prepare normal TRB */
|
/* prepare normal TRB */
|
||||||
dwc3_prepare_one_trb(dep, req, trb_length, true, i);
|
dwc3_prepare_one_trb(dep, req, trb_length,
|
||||||
|
true, i, false);
|
||||||
|
|
||||||
/* Now prepare one extra TRB to align transfer size */
|
/* Now prepare one extra TRB to align transfer size */
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, maxp - rem,
|
||||||
req->num_trbs++;
|
false, 1, true);
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
|
|
||||||
maxp - rem, false, 1,
|
|
||||||
req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
} else if (req->request.zero && req->request.length &&
|
} else if (req->request.zero && req->request.length &&
|
||||||
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
||||||
!rem && !chain) {
|
!rem && !chain) {
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
struct dwc3_trb *trb;
|
|
||||||
|
|
||||||
req->needs_extra_trb = true;
|
req->needs_extra_trb = true;
|
||||||
|
|
||||||
/* Prepare normal TRB */
|
/* Prepare normal TRB */
|
||||||
dwc3_prepare_one_trb(dep, req, trb_length, true, i);
|
dwc3_prepare_one_trb(dep, req, trb_length,
|
||||||
|
true, i, false);
|
||||||
|
|
||||||
/* Prepare one extra TRB to handle ZLP */
|
/* Prepare one extra TRB to handle ZLP */
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, 0,
|
||||||
req->num_trbs++;
|
!req->direction, 1, true);
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
|
|
||||||
!req->direction, 1,
|
|
||||||
req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
|
|
||||||
/* Prepare one more TRB to handle MPS alignment */
|
/* Prepare one more TRB to handle MPS alignment */
|
||||||
if (!req->direction) {
|
if (!req->direction)
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, maxp,
|
||||||
req->num_trbs++;
|
false, 1, true);
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
|
|
||||||
false, 1, req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dwc3_prepare_one_trb(dep, req, trb_length, chain, i);
|
dwc3_prepare_one_trb(dep, req, trb_length,
|
||||||
|
chain, i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1216,54 +1198,29 @@ 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)) {
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
struct dwc3_trb *trb;
|
|
||||||
|
|
||||||
req->needs_extra_trb = true;
|
req->needs_extra_trb = true;
|
||||||
|
|
||||||
/* prepare normal TRB */
|
/* prepare normal TRB */
|
||||||
dwc3_prepare_one_trb(dep, req, length, true, 0);
|
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 */
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, maxp - rem, false, 1, true);
|
||||||
req->num_trbs++;
|
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
|
|
||||||
false, 1, req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
} else if (req->request.zero && req->request.length &&
|
} else if (req->request.zero && req->request.length &&
|
||||||
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
||||||
(IS_ALIGNED(req->request.length, maxp))) {
|
(IS_ALIGNED(req->request.length, maxp))) {
|
||||||
struct dwc3 *dwc = dep->dwc;
|
|
||||||
struct dwc3_trb *trb;
|
|
||||||
|
|
||||||
req->needs_extra_trb = true;
|
req->needs_extra_trb = true;
|
||||||
|
|
||||||
/* prepare normal TRB */
|
/* prepare normal TRB */
|
||||||
dwc3_prepare_one_trb(dep, req, length, true, 0);
|
dwc3_prepare_one_trb(dep, req, length, true, 0, false);
|
||||||
|
|
||||||
/* Prepare one extra TRB to handle ZLP */
|
/* Prepare one extra TRB to handle ZLP */
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, 0, !req->direction, 1, true);
|
||||||
req->num_trbs++;
|
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
|
|
||||||
!req->direction, 1, req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
|
|
||||||
/* Prepare one more TRB to handle MPS alignment for OUT */
|
/* Prepare one more TRB to handle MPS alignment for OUT */
|
||||||
if (!req->direction) {
|
if (!req->direction)
|
||||||
trb = &dep->trb_pool[dep->trb_enqueue];
|
dwc3_prepare_one_trb(dep, req, maxp, false, 1, true);
|
||||||
req->num_trbs++;
|
|
||||||
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
|
|
||||||
false, 1, req->request.stream_id,
|
|
||||||
req->request.short_not_ok,
|
|
||||||
req->request.no_interrupt,
|
|
||||||
req->request.is_last);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dwc3_prepare_one_trb(dep, req, length, false, 0);
|
dwc3_prepare_one_trb(dep, req, length, false, 0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue