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 f660afb..429d64e 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 3d583a1..63963c2 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;
 };