- Deciding configfs device_driver's name according to creating
sequence, it is still RFC
- Register gadget driver at gadgets_make
- Delete gadget_cdev_desc_UDC_store and gadget_cdev_desc_UDC_show
interface, we can use standard device-model bind/unbind entry to
bind specific udc to gadgetfs driver after disable gadget_bus's
drivers_autoprobe

Signed-off-by: Peter Chen <peter.c...@freescale.com>
---
 drivers/usb/gadget/configfs.c |  115 +++++++++++++++++++---------------------
 1 files changed, 55 insertions(+), 60 deletions(-)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 2ddcd63..32655da 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -3,12 +3,14 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/nls.h>
+#include <linux/idr.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/gadget_configfs.h>
 #include "configfs.h"
 #include "u_f.h"
 #include "u_os_desc.h"
 
+static DEFINE_IDA(gadget_ida);
 int check_user_usb_string(const char *name,
                struct usb_gadget_strings *stringtab_dev)
 {
@@ -54,7 +56,6 @@ struct gadget_info {
        struct list_head string_list;
        struct list_head available_func;
 
-       const char *udc_name;
 #ifdef CONFIG_USB_OTG
        struct usb_otg_descriptor otg;
 #endif
@@ -63,6 +64,7 @@ struct gadget_info {
        bool use_os_desc;
        char b_vendor_code;
        char qw_sign[OS_STRING_QW_SIGN_LEN];
+       int id;
 };
 
 struct config_usb_cfg {
@@ -228,62 +230,16 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct 
gadget_info *gi,
        return len;
 }
 
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
-{
-       return sprintf(page, "%s\n", gi->udc_name ?: "");
-}
-
 static int unregister_gadget(struct gadget_info *gi)
 {
        int ret;
 
-       if (!gi->udc_name)
-               return -ENODEV;
-
        ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
        if (ret)
                return ret;
-       kfree(gi->udc_name);
-       gi->udc_name = NULL;
        return 0;
 }
 
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
-               const char *page, size_t len)
-{
-       char *name;
-       int ret;
-
-       name = kstrdup(page, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
-       if (name[len - 1] == '\n')
-               name[len - 1] = '\0';
-
-       mutex_lock(&gi->lock);
-
-       if (!strlen(name)) {
-               ret = unregister_gadget(gi);
-               if (ret)
-                       goto err;
-       } else {
-               if (gi->udc_name) {
-                       ret = -EBUSY;
-                       goto err;
-               }
-               ret = udc_attach_driver(name, &gi->composite.gadget_driver);
-               if (ret)
-                       goto err;
-               gi->udc_name = name;
-       }
-       mutex_unlock(&gi->lock);
-       return len;
-err:
-       kfree(name);
-       mutex_unlock(&gi->lock);
-       return ret;
-}
-
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
 GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
@@ -292,7 +248,6 @@ GI_DEVICE_DESC_ITEM_ATTR(idVendor);
 GI_DEVICE_DESC_ITEM_ATTR(idProduct);
 GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
 GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
 
 static struct configfs_attribute *gadget_root_attrs[] = {
        &gadget_cdev_desc_bDeviceClass.attr,
@@ -303,7 +258,6 @@ static struct configfs_attribute *gadget_root_attrs[] = {
        &gadget_cdev_desc_idProduct.attr,
        &gadget_cdev_desc_bcdDevice.attr,
        &gadget_cdev_desc_bcdUSB.attr,
-       &gadget_cdev_desc_UDC.attr,
        NULL,
 };
 
@@ -346,6 +300,7 @@ static void gadget_info_attr_release(struct config_item 
*item)
        WARN_ON(!list_empty(&gi->string_list));
        WARN_ON(!list_empty(&gi->available_func));
        kfree(gi->composite.gadget_driver.function);
+       ida_simple_remove(&gadget_ida, gi->id);
        kfree(gi);
 }
 
@@ -438,9 +393,7 @@ static int config_usb_cfg_unlink(
         * remove the function.
         */
        mutex_lock(&gi->lock);
-       if (gi->udc_name)
-               unregister_gadget(gi);
-       WARN_ON(gi->udc_name);
+       unregister_gadget(gi);
 
        list_for_each_entry(f, &cfg->func_list, list) {
                if (f->fi == fi) {
@@ -917,10 +870,8 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
        struct usb_composite_dev *cdev = &gi->cdev;
 
        mutex_lock(&gi->lock);
-       if (gi->udc_name)
-               unregister_gadget(gi);
+       unregister_gadget(gi);
        cdev->os_desc_config = NULL;
-       WARN_ON(gi->udc_name);
        mutex_unlock(&gi->lock);
        return 0;
 }
@@ -1456,20 +1407,54 @@ static const struct usb_gadget_driver 
configfs_driver_template = {
        .max_speed      = USB_SPEED_SUPER,
        .driver = {
                .owner          = THIS_MODULE,
-               .name           = "configfs-gadget",
        },
 };
 
+static int configfs_register_driver(struct gadget_info *gi)
+{
+       struct usb_gadget_driver *gadget_driver = &gi->composite.gadget_driver;
+       struct device_driver *driver = &gadget_driver->driver;
+
+       /* Finalize driver name first */
+       switch (gi->id) {
+       case 0:
+               driver->name = "configfs-gadget.0";
+               break;
+       case 1:
+               driver->name = "configfs-gadget.1";
+               break;
+       case 2:
+               driver->name = "configfs-gadget.2";
+               break;
+       case 3:
+               driver->name = "configfs-gadget.3";
+               break;
+       default:
+               printk(KERN_WARNING
+                       "more than 4 udcs, the API needs to rewrite\n");
+               driver->name = "configfs-gadget.4";
+       }
+
+       return usb_gadget_probe_driver(gadget_driver);
+}
+
 static struct config_group *gadgets_make(
                struct config_group *group,
                const char *name)
 {
        struct gadget_info *gi;
+       int ret;
 
        gi = kzalloc(sizeof(*gi), GFP_KERNEL);
        if (!gi)
                return ERR_PTR(-ENOMEM);
 
+       gi->id = ida_simple_get(&gadget_ida, 0, 0xffff, GFP_KERNEL);
+       if (gi->id < 0) {
+               ret = gi->id;
+               goto err;
+       }
+
        gi->group.default_groups = gi->default_groups;
        gi->group.default_groups[0] = &gi->functions_group;
        gi->group.default_groups[1] = &gi->configs_group;
@@ -1505,8 +1490,10 @@ static struct config_group *gadgets_make(
        gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
        gi->composite.name = gi->composite.gadget_driver.function;
 
-       if (!gi->composite.gadget_driver.function)
-               goto err;
+       if (!gi->composite.gadget_driver.function) {
+               ret = -ENOMEM;
+               goto err1;
+       }
 
 #ifdef CONFIG_USB_OTG
        gi->otg.bLength = sizeof(struct usb_otg_descriptor);
@@ -1516,10 +1503,18 @@ static struct config_group *gadgets_make(
 
        config_group_init_type_name(&gi->group, name,
                                &gadget_root_type);
-       return &gi->group;
+
+       ret = configfs_register_driver(gi);
+       if (!ret)
+               return &gi->group;
+
+       /* free the allocation for kstrdup */
+       kfree(gi->composite.name);
+err1:
+       ida_simple_remove(&gadget_ida, gi->id);
 err:
        kfree(gi);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(ret);
 }
 
 static void gadgets_drop(struct config_group *group, struct config_item *item)
-- 
1.7.8

--
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