diff mbox

[U-Boot,3/4] usb: ci_udc: pre-allocate ep0 req

Message ID 1401396783-21873-3-git-send-email-swarren@wwwdotorg.org
State Accepted
Delegated to: Marek Vasut
Headers show

Commit Message

Stephen Warren May 29, 2014, 8:53 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

Allocate ep0's USB request object when the UDC driver is probed. This
solves a couple of issues in the current code:

a) A request object always exists for ep0. Prior to this patch, if setup
transactions arrived in an unexpected order, handle_setup() would need
to reply to a setup transaction before any ep0 usb_req was created.

This issue was introduced in commit 2813006fecda "usb: ci_udc: allow
multiple buffer allocs per ep."

b) handle_ep_complete no longer /has/ to queue the ep0 request again
after every single request completion. This is currently required, since
handle_setup() assumes it can find some request object in ep0's request
queue. This patch doesn't actually stop handle_ep_complete() from always
requeueing the request, but the next patch will.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 drivers/usb/gadget/ci_udc.c | 17 ++++++++++++++++-
 drivers/usb/gadget/ci_udc.h |  1 +
 2 files changed, 17 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 77f8c9ef7f0f..03ad23164fe1 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -198,8 +198,14 @@  static void ci_invalidate_qtd(int ep_num)
 static struct usb_request *
 ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
 {
+	struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+	int num;
 	struct ci_req *ci_req;
 
+	num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	if (num == 0 && controller.ep0_req)
+		return &controller.ep0_req->req;
+
 	ci_req = memalign(ARCH_DMA_MINALIGN, sizeof(*ci_req));
 	if (!ci_req)
 		return NULL;
@@ -207,6 +213,9 @@  ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
 	INIT_LIST_HEAD(&ci_req->queue);
 	ci_req->b_buf = 0;
 
+	if (num == 0)
+		controller.ep0_req = ci_req;
+
 	return &ci_req->req;
 }
 
@@ -471,7 +480,7 @@  static void handle_setup(void)
 	int num, in, _num, _in, i;
 	char *buf;
 
-	ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
+	ci_req = controller.ep0_req;
 	req = &ci_req->req;
 	head = ci_get_qh(0, 0);	/* EP0 OUT */
 
@@ -780,6 +789,12 @@  static int ci_udc_probe(void)
 			      &controller.gadget.ep_list);
 	}
 
+	ci_ep_alloc_request(&controller.ep[0].ep, 0);
+	if (!controller.ep0_req) {
+		free(controller.epts);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 23cff56d7ec9..7d76af84f037 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -97,6 +97,7 @@  struct ci_ep {
 
 struct ci_drv {
 	struct usb_gadget		gadget;
+	struct ci_req			*ep0_req;
 	struct usb_gadget_driver	*driver;
 	struct ehci_ctrl		*ctrl;
 	struct ept_queue_head		*epts;