提交 a6829706 编写于 作者: F Felipe Balbi

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: NFelipe Balbi <balbi@ti.com>
上级 5812b1c2
......@@ -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);
......@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册