Loading drivers/usb/dwc3/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -725,6 +725,7 @@ struct dwc3_hwparams { * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb * @unaligned: true for OUT endpoints with length not divisible by maxp * @direction: IN or OUT direction flag * @mapped: true when request has been dma-mapped * @queued: true when request has been queued to HW Loading @@ -741,6 +742,7 @@ struct dwc3_request { struct dwc3_trb *trb; dma_addr_t trb_dma; unsigned unaligned:1; unsigned direction:1; unsigned mapped:1; unsigned started:1; Loading drivers/usb/dwc3/gadget.c +61 −8 Original line number Diff line number Diff line Loading @@ -992,12 +992,33 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, int i; for_each_sg(sg, s, req->num_pending_sgs, i) { unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; unsigned chain = true; if (sg_is_last(s)) chain = false; if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; req->unaligned = true; /* prepare normal TRB */ dwc3_prepare_one_trb(dep, req, true, i); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, false, 0, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt); } else { dwc3_prepare_one_trb(dep, req, chain, i); } if (!dwc3_calc_trbs_left(dep)) break; Loading @@ -1007,8 +1028,29 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, struct dwc3_request *req) { unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; req->unaligned = true; /* prepare normal TRB */ dwc3_prepare_one_trb(dep, req, true, 0); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, false, 0, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt); } else { dwc3_prepare_one_trb(dep, req, false, 0); } } /* * dwc3_prepare_trbs - setup TRBs from requests Loading Loading @@ -2031,6 +2073,16 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) trb->ctrl &= ~DWC3_TRB_CTRL_HWO; /* * 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. */ if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { trb->ctrl &= ~DWC3_TRB_CTRL_HWO; return 1; } if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) return 1; Loading Loading @@ -2120,6 +2172,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, event, status, chain); } if (req->unaligned) { trb = &dep->trb_pool[dep->trb_dequeue]; ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status, false); req->unaligned = false; } req->request.actual = length - req->remaining; if ((req->request.actual < length) && req->num_pending_sgs) Loading Loading @@ -3058,12 +3117,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = dwc->maximum_speed; /* * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize * on ep out. */ dwc->gadget.quirk_ep_out_aligned_size = true; /* * REVISIT: Here we should clear all pending IRQs to be * sure we're starting from a well known location. Loading Loading
drivers/usb/dwc3/core.h +2 −0 Original line number Diff line number Diff line Loading @@ -725,6 +725,7 @@ struct dwc3_hwparams { * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb * @unaligned: true for OUT endpoints with length not divisible by maxp * @direction: IN or OUT direction flag * @mapped: true when request has been dma-mapped * @queued: true when request has been queued to HW Loading @@ -741,6 +742,7 @@ struct dwc3_request { struct dwc3_trb *trb; dma_addr_t trb_dma; unsigned unaligned:1; unsigned direction:1; unsigned mapped:1; unsigned started:1; Loading
drivers/usb/dwc3/gadget.c +61 −8 Original line number Diff line number Diff line Loading @@ -992,12 +992,33 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, int i; for_each_sg(sg, s, req->num_pending_sgs, i) { unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; unsigned chain = true; if (sg_is_last(s)) chain = false; if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; req->unaligned = true; /* prepare normal TRB */ dwc3_prepare_one_trb(dep, req, true, i); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, false, 0, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt); } else { dwc3_prepare_one_trb(dep, req, chain, i); } if (!dwc3_calc_trbs_left(dep)) break; Loading @@ -1007,8 +1028,29 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, struct dwc3_request *req) { unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; req->unaligned = true; /* prepare normal TRB */ dwc3_prepare_one_trb(dep, req, true, 0); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, false, 0, req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt); } else { dwc3_prepare_one_trb(dep, req, false, 0); } } /* * dwc3_prepare_trbs - setup TRBs from requests Loading Loading @@ -2031,6 +2073,16 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) trb->ctrl &= ~DWC3_TRB_CTRL_HWO; /* * 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. */ if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { trb->ctrl &= ~DWC3_TRB_CTRL_HWO; return 1; } if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) return 1; Loading Loading @@ -2120,6 +2172,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, event, status, chain); } if (req->unaligned) { trb = &dep->trb_pool[dep->trb_dequeue]; ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status, false); req->unaligned = false; } req->request.actual = length - req->remaining; if ((req->request.actual < length) && req->num_pending_sgs) Loading Loading @@ -3058,12 +3117,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = dwc->maximum_speed; /* * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize * on ep out. */ dwc->gadget.quirk_ep_out_aligned_size = true; /* * REVISIT: Here we should clear all pending IRQs to be * sure we're starting from a well known location. Loading