We currently enable the udc on bind_to_driver. This breaks the de/activate mechanism for drivers that depent on userspace components. This patch fixes this by moving the pullup call to each bind. Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> --- drivers/usb/gadget/f_acm.c | 3 +++ drivers/usb/gadget/f_ecm.c | 3 +++ drivers/usb/gadget/f_eem.c | 3 +++ drivers/usb/gadget/f_fs.c | 5 +++++ drivers/usb/gadget/f_hid.c | 2 ++ drivers/usb/gadget/f_loopback.c | 3 +++ drivers/usb/gadget/f_mass_storage.c | 2 ++ drivers/usb/gadget/f_midi.c | 2 ++ drivers/usb/gadget/f_ncm.c | 3 +++ drivers/usb/gadget/f_phonet.c | 3 +++ drivers/usb/gadget/f_rndis.c | 3 +++ drivers/usb/gadget/f_serial.c | 3 +++ drivers/usb/gadget/f_sourcesink.c | 3 +++ drivers/usb/gadget/f_subset.c | 3 +++ drivers/usb/gadget/f_uac1.c | 3 +++ drivers/usb/gadget/f_uac2.c | 3 +++ drivers/usb/gadget/g_ffs.c | 6 +++++- drivers/usb/gadget/inode.c | 2 ++ drivers/usb/gadget/udc-core.c | 1 - 19 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index ab1065a..045176f 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -697,6 +697,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", acm->port.in->name, acm->port.out->name, acm->notify->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 8d9e6f7..58cb39a 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -813,6 +813,9 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ecm->port.in_ep->name, ecm->port.out_ep->name, ecm->notify->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index d61c11d..94cf705 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -322,6 +322,9 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", eem->port.in_ep->name, eem->port.out_ep->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 44cf775..a6349ee 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1496,6 +1496,11 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, if (unlikely(ret)) ffs_func_free(func); + /* Avoid letting this gadget enumerate until the userspace server is + * active. + */ + ret = usb_function_deactivate(&func->function); + return ret; } diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 6e69a8e..03cfa3ee 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -633,6 +633,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor); + usb_gadget_connect(c->cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 4a3873a..08ff937 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -225,6 +225,9 @@ autoconf_fail: (gadget_is_superspeed(c->cdev->gadget) ? "super" : (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), f->name, loop->in_ep->name, loop->out_ep->name); + + usb_gadget_connect(cdev->gadget); + return 0; } diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a03ba2c..20458bd 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3161,6 +3161,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) if (ret) goto autoconf_fail; + usb_gadget_connect(gadget); + return 0; autoconf_fail: diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 263e721..8589717 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -895,6 +895,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) kfree(midi_function); + usb_gadget_connect(cdev->gadget); + return 0; fail_f_midi: diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index 1c28fe1..40518ac 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1271,6 +1271,9 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ncm->port.in_ep->name, ncm->port.out_ep->name, ncm->notify->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index eb3aa81..72abd73 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -565,6 +565,9 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "USB CDC Phonet function\n"); INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name, fp->out_ep->name, fp->in_ep->name); + + usb_gadget_connect(cdev->gadget); + return 0; err_req: diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 717ed7f..3a3da34 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -807,6 +807,9 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", rndis->port.in_ep->name, rndis->port.out_ep->name, rndis->notify->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 981113c..19581d5 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -244,6 +244,9 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index a889585..43d5b10 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -484,6 +484,9 @@ no_iso: f->name, ss->in_ep->name, ss->out_ep->name, ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); + + usb_gadget_connect(cdev->gadget); + return 0; } diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 7c8674f..5aa743c 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -378,6 +378,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", geth->port.in_ep->name, geth->port.out_ep->name); + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c index 2b4c82d..00f9581 100644 --- a/drivers/usb/gadget/f_uac1.c +++ b/drivers/usb/gadget/f_uac1.c @@ -663,6 +663,9 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL); if (status) goto fail; + + usb_gadget_connect(cdev->gadget); + return 0; fail: diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index 2f23566..ac6d075 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -994,6 +994,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ret = alsa_uac2_init(agdev); if (ret) goto err; + + usb_gadget_connect(cdev->gadget); + return 0; err: kfree(agdev->uac2.p_prm.rbuf); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 2344efe..9f87c60 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -247,6 +247,7 @@ static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name) static int functionfs_ready_callback(struct ffs_data *ffs) { struct gfs_ffs_obj *ffs_obj; + struct ffs_function *func = ffs->func; int ret; ENTER(); @@ -277,9 +278,12 @@ static int functionfs_ready_callback(struct ffs_data *ffs) gfs_registered = true; ret = usb_composite_probe(&gfs_driver); - if (unlikely(ret < 0)) + if (unlikely(ret < 0)) { gfs_registered = false; + goto done; + } + ret = usb_function_activate(&func->function); done: mutex_unlock(&gfs_lock); return ret; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index b94c049..f30a6c5 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1844,6 +1844,7 @@ static ssize_t dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) { struct dev_data *dev = fd->private_data; + struct usb_gadget *gadget = dev->gadget; ssize_t value = len, length = len; unsigned total; u32 tag; @@ -1913,6 +1914,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) kfree (dev->buf); dev->buf = NULL; } else { + usb_gadget_connect(gadget); /* at this point "good" hardware has for the first time * let the USB the host see us. alternatively, if users * unplug/replug that will clear all the error state. diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 27768a7..b906ac7 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -351,7 +351,6 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver->unbind(udc->gadget); goto err1; } - usb_gadget_connect(udc->gadget); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html