[U-Boot] [PATCH 1/4] usb: ci_udc: call udc_disconnect() from ci_pullup()

From: Stephen Warren swarren@nvidia.com
ci_pullup()'s !is_on path contains a cut/paste copy of udc_disconnect(). Remove the duplication by simply calling udc_disconnect() instead.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/usb/gadget/ci_udc.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 6dc20c6c954c..5f308563e246 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -697,6 +697,17 @@ int usb_gadget_handle_interrupts(void) return value; }
+void udc_disconnect(void) +{ + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; + /* disable pullup */ + stop_activity(); + writel(USBCMD_FS2, &udc->usbcmd); + udelay(800); + if (controller.driver) + controller.driver->disconnect(&controller.gadget); +} + static int ci_pullup(struct usb_gadget *gadget, int is_on) { struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; @@ -715,27 +726,12 @@ static int ci_pullup(struct usb_gadget *gadget, int is_on) /* Turn on the USB connection by enabling the pullup resistor */ writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); } else { - stop_activity(); - writel(USBCMD_FS2, &udc->usbcmd); - udelay(800); - if (controller.driver) - controller.driver->disconnect(gadget); + udc_disconnect(); }
return 0; }
-void udc_disconnect(void) -{ - struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; - /* disable pullup */ - stop_activity(); - writel(USBCMD_FS2, &udc->usbcmd); - udelay(800); - if (controller.driver) - controller.driver->disconnect(&controller.gadget); -} - static int ci_udc_probe(void) { struct ept_queue_head *head;

From: Stephen Warren swarren@nvidia.com
ci_ep_alloc_request() avoids allocating multiple request objects for ep0 by keeping a record of the first req allocated for ep0, and always returning that instead of allocating a new req. However, if this req is ever freed, the record of the previous allocation is not cleared, so ci_ep_alloc_request() will keep returning this stale pointer. Fix ci_ep_free_request() to clear the record of the previous allocation.
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/usb/gadget/ci_udc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 5f308563e246..7a6563f83fd1 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -221,9 +221,14 @@ ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req) { - struct ci_req *ci_req; + struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); + struct ci_req *ci_req = container_of(req, struct ci_req, req); + int num; + + num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if (num == 0) + controller.ep0_req = 0;
- ci_req = container_of(req, struct ci_req, req); if (ci_req->b_buf) free(ci_req->b_buf); free(ci_req);

From: Stephen Warren swarren@nvidia.com
If allocation of the ep0 req fails, clean up all the allocations that were made in ci_udc_probe().
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/usb/gadget/ci_udc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 7a6563f83fd1..1428af85cffd 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -826,6 +826,7 @@ static int ci_udc_probe(void)
ci_ep_alloc_request(&controller.ep[0].ep, 0); if (!controller.ep0_req) { + free(controller.items_mem); free(controller.epts); return -ENOMEM; }

From: Stephen Warren swarren@nvidia.com
usb_gadget_unregister_driver() is called to tear down the USB device mode stack. Fix the driver to stop the USB HW (which causes any attached host to notice the disappearance of the device), and free all allocations (which obviously prevents memory leaks).
Signed-off-by: Stephen Warren swarren@nvidia.com --- drivers/usb/gadget/ci_udc.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 1428af85cffd..435a2720e96f 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -875,5 +875,11 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { + udc_disconnect(); + + ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); + free(controller.items_mem); + free(controller.epts); + return 0; }

On Tuesday, June 10, 2014 at 07:02:35 PM, Stephen Warren wrote:
From: Stephen Warren swarren@nvidia.com
ci_pullup()'s !is_on path contains a cut/paste copy of udc_disconnect(). Remove the duplication by simply calling udc_disconnect() instead.
Signed-off-by: Stephen Warren swarren@nvidia.com
Applied all, thanks.
Best regards, Marek Vasut
participants (2)
-
Marek Vasut
-
Stephen Warren