diff options
Diffstat (limited to 'drivers/usb/gadget/udc/core.c')
-rw-r--r-- | drivers/usb/gadget/udc/core.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 83fd1de14784..7166d1117742 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -40,6 +40,7 @@ static const struct bus_type gadget_bus_type; * @allow_connect: Indicates whether UDC is allowed to be pulled up. * Set/cleared by gadget_(un)bind_driver() after gadget driver is bound or * unbound. + * @vbus_work: work routine to handle VBUS status change notifications. * @connect_lock: protects udc->started, gadget->connect, * gadget->allow_connect and gadget->deactivate. The routines * usb_gadget_connect_locked(), usb_gadget_disconnect_locked(), @@ -61,7 +62,7 @@ struct usb_udc { struct mutex connect_lock; }; -static struct class *udc_class; +static const struct class udc_class; static LIST_HEAD(udc_list); /* Protects udc_list, udc->driver, driver->is_bound, and related calls */ @@ -822,6 +823,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect); * usb_gadget_activate() is called. For example, user mode components may * need to be activated before the system can talk to hosts. * + * This routine may sleep; it must not be called in interrupt context + * (such as from within a gadget driver's disconnect() callback). + * * Returns zero on success, else negative errno. */ int usb_gadget_deactivate(struct usb_gadget *gadget) @@ -860,6 +864,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate); * This routine activates gadget which was previously deactivated with * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. * + * This routine may sleep; it must not be called in interrupt context. + * * Returns zero on success, else negative errno. */ int usb_gadget_activate(struct usb_gadget *gadget) @@ -878,7 +884,6 @@ int usb_gadget_activate(struct usb_gadget *gadget) */ if (gadget->connected) ret = usb_gadget_connect_locked(gadget); - mutex_unlock(&gadget->udc->connect_lock); unlock: mutex_unlock(&gadget->udc->connect_lock); @@ -1378,7 +1383,7 @@ int usb_add_gadget(struct usb_gadget *gadget) device_initialize(&udc->dev); udc->dev.release = usb_udc_release; - udc->dev.class = udc_class; + udc->dev.class = &udc_class; udc->dev.groups = usb_udc_attr_groups; udc->dev.parent = gadget->dev.parent; ret = dev_set_name(&udc->dev, "%s", @@ -1639,7 +1644,11 @@ static void gadget_unbind_driver(struct device *dev) usb_gadget_disable_async_callbacks(udc); if (gadget->irq) synchronize_irq(gadget->irq); + mutex_unlock(&udc->connect_lock); + udc->driver->unbind(gadget); + + mutex_lock(&udc->connect_lock); usb_gadget_udc_stop_locked(udc); mutex_unlock(&udc->connect_lock); @@ -1856,6 +1865,11 @@ static int usb_udc_uevent(const struct device *dev, struct kobj_uevent_env *env) return 0; } +static const struct class udc_class = { + .name = "udc", + .dev_uevent = usb_udc_uevent, +}; + static const struct bus_type gadget_bus_type = { .name = "gadget", .probe = gadget_bind_driver, @@ -1867,18 +1881,13 @@ static int __init usb_udc_init(void) { int rc; - udc_class = class_create("udc"); - if (IS_ERR(udc_class)) { - pr_err("failed to create udc class --> %ld\n", - PTR_ERR(udc_class)); - return PTR_ERR(udc_class); - } - - udc_class->dev_uevent = usb_udc_uevent; + rc = class_register(&udc_class); + if (rc) + return rc; rc = bus_register(&gadget_bus_type); if (rc) - class_destroy(udc_class); + class_unregister(&udc_class); return rc; } subsys_initcall(usb_udc_init); @@ -1886,7 +1895,7 @@ subsys_initcall(usb_udc_init); static void __exit usb_udc_exit(void) { bus_unregister(&gadget_bus_type); - class_destroy(udc_class); + class_unregister(&udc_class); } module_exit(usb_udc_exit); |