[PATCH v2 5/7] usb: dwc3: ep0: add handling for unaligned OUT transfers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxx>
---
 drivers/usb/dwc3/ep0.c |   37 ++++++++++++++++++++++++++++++++-----
 1 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a6fc5c3..f1e0a5e 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,
 	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 */
-- 
1.7.6.396.ge0613

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux