Commit fb22ae6c7e0ffe438103c948c87c5ddf2ef56e7e
Committed by
Marek Vasut
1 parent
ba9b42c81b
Exists in
v2017.01-smarct4x
and in
40 other branches
usb: ci_udc: fix interaction with CONFIG_USB_ETH_CDC
ci_udc.c's usb_gadget_unregister_driver() doesn't call driver->unbind() unlike other USB gadget drivers. Fix it to do this. Without this, when ether.c's CDC Ethernet device is torn down, eth_unbind() is never called, so dev->gadget is never set to NULL. For some reason, usb_eth_halt() is called both at the end of the first use of the Ethernet device, and prior to any subsequent use. Since dev->gadget is never cleared, all calls to usb_eth_halt() attempt to stop, disconnect, and clean up the device, resulting in double cleanup, which hangs U-Boot on my Tegra device at least. ci_udc allocates its own singleton EP0 request object, and cleans it up during usb_gadget_unregister_driver(). This appears necessary when using the USB gadget framework in U-Boot, since that does not allocate/free the EP0 request. However, the CDC Ethernet driver *does* allocate and free its own EP0 requests. Consequently, we must protect ci_ep_free_request() against double-freeing the request. Signed-off-by: Stephen Warren <swarren@nvidia.com>
Showing 1 changed file with 7 additions and 1 deletions Side-by-side Diff
drivers/usb/gadget/ci_udc.c
... | ... | @@ -226,8 +226,11 @@ |
226 | 226 | int num; |
227 | 227 | |
228 | 228 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
229 | - if (num == 0) | |
229 | + if (num == 0) { | |
230 | + if (!controller.ep0_req) | |
231 | + return; | |
230 | 232 | controller.ep0_req = 0; |
233 | + } | |
231 | 234 | |
232 | 235 | if (ci_req->b_buf) |
233 | 236 | free(ci_req->b_buf); |
... | ... | @@ -908,6 +911,9 @@ |
908 | 911 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) |
909 | 912 | { |
910 | 913 | udc_disconnect(); |
914 | + | |
915 | + driver->unbind(&controller.gadget); | |
916 | + controller.driver = NULL; | |
911 | 917 | |
912 | 918 | ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); |
913 | 919 | free(controller.items_mem); |