diff options
author | Felipe Balbi | 2017-04-07 16:34:38 +0300 |
---|---|---|
committer | Felipe Balbi | 2017-04-11 10:58:29 +0300 |
commit | d6e5a549cc4dba504a62855d9613836f76950790 (patch) | |
tree | 1804ea4768e2e880ae475f31ba3bf8b26c3c7dc3 /drivers/usb/dwc3/ep0.c | |
parent | 4199c5f8bccd7ff6923c32af0f8ef0224eeaa651 (diff) |
usb: dwc3: simplify ZLP handling
It's much simpler to just add one extra TRB chained to previous TRB to
handle ZLP. This helps us reduce pointless allocations and simplifies
the code a little bit.
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc3/ep0.c')
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 04249243e4d3..a78c78e7a8c3 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -873,34 +873,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = ur->length - length; ur->actual += transferred; - if (dwc->ep0_bounced) { + if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && + ur->length && ur->zero) || dwc->ep0_bounced) { trb++; trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + trace_dwc3_complete_trb(ep0, trb); ep0->trb_enqueue = 0; dwc->ep0_bounced = false; } - if ((epnum & 1) && ur->actual < ur->length) { - /* for some reason we did not get everything out */ - + if ((epnum & 1) && ur->actual < ur->length) dwc3_ep0_stall_and_restart(dwc); - } else { + else dwc3_gadget_giveback(ep0, r, 0); - - if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && - ur->length && ur->zero) { - struct dwc3_ep *dep; - int ret; - - dwc->ep0_next_event = DWC3_EP0_COMPLETE; - - dep = dwc->eps[epnum]; - dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, - 0, DWC3_TRBCTL_CONTROL_DATA, false); - ret = dwc3_ep0_start_trans(dep); - WARN_ON(ret < 0); - } - } } static void dwc3_ep0_complete_status(struct dwc3 *dwc, @@ -1005,6 +990,30 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dep); + } else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && + req->request.length && req->request.zero) { + u32 maxpacket; + u32 rem; + + ret = usb_gadget_map_request_by_dev(dwc->sysdev, + &req->request, dep->number); + if (ret) + return; + + maxpacket = dep->endpoint.maxpacket; + rem = req->request.length % maxpacket; + + /* prepare normal TRB */ + dwc3_ep0_prepare_one_trb(dep, req->request.dma, + req->request.length, + DWC3_TRBCTL_CONTROL_DATA, + true); + + /* Now prepare one extra TRB to align transfer size */ + dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, + 0, DWC3_TRBCTL_CONTROL_DATA, + false); + ret = dwc3_ep0_start_trans(dep); } else { ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->number); |