This new internal function will be used to solve a minor issue with dwc3 which exists in regards to short packets with OUT endpoints. Currently we're asking gadget driver to *always* send us aligned requests; however if we have enough TRBs we can easily append one extra TRB chained to the previous and keep a throw away 1024 byte buffer around for that. The actual fix will come in a separate patch, this is merely in preparation for such fix. Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx> --- drivers/usb/dwc3/gadget.c | 58 +++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index cd410a720aa2..f1ffbf789e0a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -833,29 +833,13 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep); -/** - * dwc3_prepare_one_trb - setup one TRB from one request - * @dep: endpoint for which this request is prepared - * @req: dwc3_request pointer - */ -static void dwc3_prepare_one_trb(struct dwc3_ep *dep, - struct dwc3_request *req, unsigned chain, unsigned node) +static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, + dma_addr_t dma, unsigned length, unsigned chain, unsigned node, + unsigned stream_id, unsigned short_not_ok, unsigned no_interrupt) { - struct dwc3_trb *trb; struct dwc3 *dwc = dep->dwc; struct usb_gadget *gadget = &dwc->gadget; enum usb_device_speed speed = gadget->speed; - unsigned length = req->request.length; - dma_addr_t dma = req->request.dma; - - trb = &dep->trb_pool[dep->trb_enqueue]; - - if (!req->trb) { - dwc3_gadget_move_started_request(req); - req->trb = trb; - req->trb_dma = dwc3_trb_dma_offset(dep, trb); - dep->queued_requests++; - } dwc3_ep_inc_enq(dep); @@ -901,11 +885,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, if (usb_endpoint_dir_out(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_CSP; - if (req->request.short_not_ok) + if (short_not_ok) trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; } - if ((!req->request.no_interrupt && !chain) || + if ((!no_interrupt && !chain) || (dwc3_calc_trbs_left(dep) == 0)) trb->ctrl |= DWC3_TRB_CTRL_IOC; @@ -913,7 +897,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_CHN; if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) - trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); + trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id); trb->ctrl |= DWC3_TRB_CTRL_HWO; @@ -921,6 +905,36 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } /** + * dwc3_prepare_one_trb - setup one TRB from one request + * @dep: endpoint for which this request is prepared + * @req: dwc3_request pointer + * @chain: should this TRB be chained to the next? + * @node: only for isochronous endpoints. First TRB needs different type. + */ +static void dwc3_prepare_one_trb(struct dwc3_ep *dep, + struct dwc3_request *req, unsigned chain, unsigned node) +{ + struct dwc3_trb *trb; + unsigned length = req->request.length; + unsigned stream_id = req->request.stream_id; + unsigned short_not_ok = req->request.short_not_ok; + unsigned no_interrupt = req->request.no_interrupt; + dma_addr_t dma = req->request.dma; + + trb = &dep->trb_pool[dep->trb_enqueue]; + + if (!req->trb) { + dwc3_gadget_move_started_request(req); + req->trb = trb; + req->trb_dma = dwc3_trb_dma_offset(dep, trb); + dep->queued_requests++; + } + + __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, + stream_id, short_not_ok, no_interrupt); +} + +/** * dwc3_ep_prev_trb() - Returns the previous TRB in the ring * @dep: The endpoint with the TRB ring * @index: The index of the current TRB in the ring -- 2.11.0.295.gd7dffce1ce -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html