aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-08-27 15:18:09 -0400
committerFelipe Balbi <balbi@ti.com>2011-09-09 06:02:05 -0400
commita6829706ce0bae7e4623ea987a639d91a721eee2 (patch)
tree094bcdbe1c8588c85d45cadfec91782f884614c6 /drivers/usb/dwc3
parent5812b1c236774ea580b6af39411eb4f7297d7623 (diff)
usb: dwc3: ep0: add handling for unaligned OUT transfers
In case we have transfers which aren't aligned to wMaxPacketSize, we need to be careful with how we start the transfer with the HW. OUT transfers _must_ be aligned with wMaxPacketSize and in order to guarantee that, we use a bounce buffer. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/ep0.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a6fc5c316743..f1e0a5eb0544 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -185,10 +185,29 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
185 req->epnum = dep->number; 185 req->epnum = dep->number;
186 186
187 list_add_tail(&req->list, &dep->request_list); 187 list_add_tail(&req->list, &dep->request_list);
188 dwc3_map_buffer_to_dma(req); 188 if (req->request.length == 0) {
189 ret = dwc3_ep0_start_trans(dwc, dep->number,
190 dwc->ctrl_req_addr, 0);
191 } else if ((req->request.length % dep->endpoint.maxpacket)
192 && (dep->number == 0)) {
193 dwc->ep0_bounced = true;
194
195 WARN_ON(req->request.length > dep->endpoint.maxpacket);
196
197 /*
198 * REVISIT in case request length is bigger than EP0
199 * wMaxPacketSize, we will need two chained TRBs to handle
200 * the transfer.
201 */
202 ret = dwc3_ep0_start_trans(dwc, dep->number,
203 dwc->ep0_bounce_addr, dep->endpoint.maxpacket);
204 } else {
205 dwc3_map_buffer_to_dma(req);
206
207 ret = dwc3_ep0_start_trans(dwc, dep->number,
208 req->request.dma, req->request.length);
209 }
189 210
190 ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
191 req->request.length);
192 if (ret < 0) { 211 if (ret < 0) {
193 list_del(&req->list); 212 list_del(&req->list);
194 dwc3_unmap_buffer_from_dma(req); 213 dwc3_unmap_buffer_from_dma(req);
@@ -655,8 +674,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
655 674
656 dwc3_trb_to_nat(dwc->ep0_trb, &trb); 675 dwc3_trb_to_nat(dwc->ep0_trb, &trb);
657 676
658 transferred = ur->length - trb.length; 677 if (dwc->ep0_bounced) {
659 ur->actual += transferred; 678 struct dwc3_ep *ep0 = dwc->eps[0];
679
680 transferred = min(ur->length, dep->endpoint.maxpacket - trb.length);
681 memcpy(ur->buf, dwc->ep0_bounce, transferred);
682 dwc->ep0_bounced = false;
683 } else {
684 transferred = ur->length - trb.length;
685 ur->actual += transferred;
686 }
660 687
661 if ((epnum & 1) && ur->actual < ur->length) { 688 if ((epnum & 1) && ur->actual < ur->length) {
662 /* for some reason we did not get everything out */ 689 /* for some reason we did not get everything out */