usb: gadget: bind UDC by name passed via usb_gadget_driver structure
authorRuslan Bilovol <ruslan.bilovol@gmail.com>
Mon, 23 Nov 2015 08:56:35 +0000 (09:56 +0100)
committerFelipe Balbi <balbi@ti.com>
Wed, 16 Dec 2015 16:07:26 +0000 (10:07 -0600)
Introduce new 'udc_name' member to usb_gadget_driver structure.
The 'udc_name' is a name of UDC that usb_gadget_driver should
be bound to. If udc_name is NULL, it will be bound to any
available UDC.

Tested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/udc/udc-core.c
include/linux/usb/gadget.h

index f660afba715da9babd033892e7b08c6096abfed9..429d64e6794141cb212a35c4317d2baeb6d58596 100644 (file)
@@ -549,21 +549,35 @@ EXPORT_SYMBOL_GPL(usb_udc_attach_driver);
 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
 {
        struct usb_udc          *udc = NULL;
-       int                     ret;
+       int                     ret = -ENODEV;
 
        if (!driver || !driver->bind || !driver->setup)
                return -EINVAL;
 
        mutex_lock(&udc_lock);
-       list_for_each_entry(udc, &udc_list, list) {
-               /* For now we take the first one */
-               if (!udc->driver)
+       if (driver->udc_name) {
+               list_for_each_entry(udc, &udc_list, list) {
+                       ret = strcmp(driver->udc_name, dev_name(&udc->dev));
+                       if (!ret)
+                               break;
+               }
+               if (ret)
+                       ret = -ENODEV;
+               else if (udc->driver)
+                       ret = -EBUSY;
+               else
                        goto found;
+       } else {
+               list_for_each_entry(udc, &udc_list, list) {
+                       /* For now we take the first one */
+                       if (!udc->driver)
+                               goto found;
+               }
        }
 
        pr_debug("couldn't find an available UDC\n");
        mutex_unlock(&udc_lock);
-       return -ENODEV;
+       return ret;
 found:
        ret = udc_bind_to_driver(udc, driver);
        mutex_unlock(&udc_lock);
index 3d583a10b9269bd7a0f77c0eca1b1b037e11392d..63963c21866dfac63afa9a4d26a2c2b172f26aee 100644 (file)
@@ -1012,6 +1012,8 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget)
  * @reset: Invoked on USB bus reset. It is mandatory for all gadget drivers
  *     and should be called in_interrupt.
  * @driver: Driver model state for this driver.
+ * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
+ *     this driver will be bound to any available UDC.
  *
  * Devices are disabled till a gadget driver successfully bind()s, which
  * means the driver will handle setup() requests needed to enumerate (and
@@ -1072,6 +1074,8 @@ struct usb_gadget_driver {
 
        /* FIXME support safe rmmod */
        struct device_driver    driver;
+
+       char                    *udc_name;
 };