summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2014-05-29 14:53:02 -0600
committerMarek Vasut <marex@denx.de>2014-06-01 19:22:40 +0200
commita2d8f929857b7bc50528114c29e48a99cbcee1f1 (patch)
tree73efb517d9edb37c45ee59aff6e81326038158b4 /drivers
parent054731b09e1944cdb130b755ac0f6c188920e98a (diff)
downloadblackbird-obmc-uboot-a2d8f929857b7bc50528114c29e48a99cbcee1f1.tar.gz
blackbird-obmc-uboot-a2d8f929857b7bc50528114c29e48a99cbcee1f1.zip
usb: ci_udc: pre-allocate ep0 req
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/ci_udc.c17
-rw-r--r--drivers/usb/gadget/ci_udc.h1
2 files changed, 17 insertions, 1 deletions
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 77f8c9ef7f..03ad23164f 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 23cff56d7e..7d76af84f0 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;
OpenPOWER on IntegriCloud