diff options
-rw-r--r-- | drivers/usb/gadget/udc-core.c | 29 | ||||
-rw-r--r-- | include/linux/usb/gadget.h | 3 |
2 files changed, 31 insertions, 1 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 5514822114a5..80ea4ed7bcc0 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -46,6 +46,7 @@ struct usb_udc { static struct class *udc_class; static LIST_HEAD(udc_list); +static LIST_HEAD(driver_list); static DEFINE_MUTEX(udc_lock); /* ------------------------------------------------------------------------- */ @@ -172,6 +173,9 @@ static void usb_udc_nop_release(struct device *dev) dev_vdbg(dev, "%s\n", __func__); } +static int udc_bind_to_driver(struct usb_udc *udc, + struct usb_gadget_driver *driver); + /** * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list * @parent: the parent device to this udc. Usually the controller driver's @@ -227,6 +231,20 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); + if (!list_empty(&driver_list)) { + struct usb_gadget_driver *driver; + list_for_each_entry(driver, &driver_list, list) { + if (driver->attached) + continue; + ret = udc_bind_to_driver(udc, driver); + if (ret) + goto err4; + else + break; + } + + } + mutex_unlock(&udc_lock); return 0; @@ -336,6 +354,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri goto err1; } usb_gadget_connect(udc->gadget); + driver->attached = true; kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; @@ -391,8 +410,13 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) pr_debug("couldn't find an available UDC\n"); mutex_unlock(&udc_lock); - return -ENODEV; + + driver->attached = false; + list_add_tail(&driver->list, &driver_list); + + return 0; found: + list_add_tail(&driver->list, &driver_list); ret = udc_bind_to_driver(udc, driver); mutex_unlock(&udc_lock); return ret; @@ -415,6 +439,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) break; } + driver->attached = false; + list_del(&driver->list); + mutex_unlock(&udc_lock); return ret; } diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index f1b0dca60f12..aab3f10cca3c 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -832,6 +832,9 @@ struct usb_gadget_driver { /* FIXME support safe rmmod */ struct device_driver driver; + + bool attached; + struct list_head list; }; |