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.grzesc...@pengutronix.de>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to