Skip to content

Commit

Permalink
usb: dwc3: ep0: add handling for unaligned OUT transfers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felipe Balbi committed Sep 9, 2011
1 parent 5812b1c commit a682970
Showing 1 changed file with 32 additions and 5 deletions.
37 changes: 32 additions & 5 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,29 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
req->epnum = dep->number;

list_add_tail(&req->list, &dep->request_list);
dwc3_map_buffer_to_dma(req);
if (req->request.length == 0) {
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ctrl_req_addr, 0);
} else if ((req->request.length % dep->endpoint.maxpacket)
&& (dep->number == 0)) {
dwc->ep0_bounced = true;

WARN_ON(req->request.length > dep->endpoint.maxpacket);

/*
* REVISIT in case request length is bigger than EP0
* wMaxPacketSize, we will need two chained TRBs to handle
* the transfer.
*/
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ep0_bounce_addr, dep->endpoint.maxpacket);
} else {
dwc3_map_buffer_to_dma(req);

ret = dwc3_ep0_start_trans(dwc, dep->number,
req->request.dma, req->request.length);
}

ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
req->request.length);
if (ret < 0) {
list_del(&req->list);
dwc3_unmap_buffer_from_dma(req);
Expand Down Expand Up @@ -655,8 +674,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,

dwc3_trb_to_nat(dwc->ep0_trb, &trb);

transferred = ur->length - trb.length;
ur->actual += transferred;
if (dwc->ep0_bounced) {
struct dwc3_ep *ep0 = dwc->eps[0];

transferred = min(ur->length, dep->endpoint.maxpacket - trb.length);
memcpy(ur->buf, dwc->ep0_bounce, transferred);
dwc->ep0_bounced = false;
} else {
transferred = ur->length - trb.length;
ur->actual += transferred;
}

if ((epnum & 1) && ur->actual < ur->length) {
/* for some reason we did not get everything out */
Expand Down

0 comments on commit a682970

Please sign in to comment.