summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorRakesh Bodla <rbodla@nvidia.com>2014-06-05 12:01:12 +0530
committerMandar Padmawar <mpadmawar@nvidia.com>2014-06-23 02:10:09 -0700
commitbce4b76d14e5bc53cf20d931c7ab1bd8cbbd7f69 (patch)
tree6979664864d6a3115acc22cf7bb7de6193cbee15 /drivers/usb
parent62eacecc64fc7f62205173941e1786cc7f5983b6 (diff)
usb: free up composite gadget string ids on unbind
There are only 254 USB composite gadget string_ids available. When switching gadget mode such as mtp and acm repeatedly, they will be exhausted. This bug has been brought up since android composite driver introduced a way to switch gadget modes while the composite driver is still holding its bind. Fix this by reset next_string_id and clean up gstrings when android gadgets are disabled. Also by removing the condition comparing gadgets' string id to 0 because gadget string id has to be re-assigned whenever the string count is reset. The codes removed the condition check will work as the same as before they have changed if the gadgets are used by other composite drivers other than android since all of them call bind only once and never unbind it hence no side effects considered. Ported from https://android-review.googlesource.com/#/c/95366/ Bug 200001941 Change-Id: I1e2fbe0f59fe05b89052db62e0b61b074d8f032b Signed-off-by: Rakesh Bodla <rbodla@nvidia.com> Reviewed-on: http://git-master/r/425165 (cherry picked from commit fc71534a90787bd763b7bd0f7c698b76b66ad251) Reviewed-on: http://git-master/r/419340 Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/android.c18
-rw-r--r--drivers/usb/gadget/f_accessory.c12
-rw-r--r--drivers/usb/gadget/f_mass_storage.c16
-rw-r--r--drivers/usb/gadget/f_mtp.c13
-rw-r--r--drivers/usb/gadget/f_rndis.c16
5 files changed, 42 insertions, 33 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index e33641c28153..af027f9506cb 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -100,6 +100,7 @@ struct android_dev {
bool sw_connected;
struct work_struct work;
char ffs_aliases[256];
+ unsigned short ffs_string_ids;
};
static struct class *android_class;
@@ -152,6 +153,20 @@ static struct usb_configuration android_config_driver = {
.bConfigurationValue = 1,
};
+static void android_gstring_cleanup(struct android_dev *dev)
+{
+ struct usb_composite_dev *cdev = dev->cdev;
+ struct usb_gadget_string_container *uc, *tmp;
+
+ list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) {
+ list_del(&uc->list);
+ kfree(uc);
+ }
+ /* reserve unfreed string ids */
+ cdev->next_string_id = ARRAY_SIZE(strings_dev) +
+ dev->ffs_string_ids - 1;
+}
+
static void android_work(struct work_struct *data)
{
struct android_dev *dev = container_of(data, struct android_dev, work);
@@ -202,6 +217,7 @@ static void android_disable(struct android_dev *dev)
/* Cancel pending control requests */
usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
usb_remove_config(cdev, &android_config_driver);
+ android_gstring_cleanup(dev);
}
}
@@ -327,6 +343,7 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
config->data = ffs;
config->opened = true;
+ dev->ffs_string_ids = ffs->strings_count;
if (config->enabled)
android_enable(dev);
@@ -350,6 +367,7 @@ static void functionfs_closed_callback(struct ffs_data *ffs)
config->data = NULL;
functionfs_unbind(ffs);
+ dev->ffs_string_ids = 0;
mutex_unlock(&dev->mutex);
}
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c
index 456e33f7aeda..ea85e604822a 100644
--- a/drivers/usb/gadget/f_accessory.c
+++ b/drivers/usb/gadget/f_accessory.c
@@ -1139,13 +1139,11 @@ static int acc_bind_config(struct usb_configuration *c)
printk(KERN_INFO "acc_bind_config\n");
/* allocate a string ID for our interface */
- if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
- ret = usb_string_id(c->cdev);
- if (ret < 0)
- return ret;
- acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
- acc_interface_desc.iInterface = ret;
- }
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ return ret;
+ acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
+ acc_interface_desc.iInterface = ret;
dev->cdev = c->cdev;
dev->function.name = "accessory";
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index c35a9ecc576b..832b64261c05 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2656,15 +2656,6 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
common->ep0req = cdev->req;
common->cdev = cdev;
- /* Maybe allocate device-global string IDs, and patch descriptors */
- if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
- rc = usb_string_id(cdev);
- if (unlikely(rc < 0))
- goto error_release;
- fsg_strings[FSG_STRING_INTERFACE].id = rc;
- fsg_intf_desc.iInterface = rc;
- }
-
/*
* Create the LUNs, open their backing files, and register the
* LUN devices in sysfs.
@@ -2953,6 +2944,13 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,
struct fsg_dev *fsg;
int rc;
+ /* allocate device-global string IDs, and patch descriptors */
+ rc = usb_string_id(cdev);
+ if (unlikely(rc < 0))
+ return rc;
+ fsg_strings[FSG_STRING_INTERFACE].id = rc;
+ fsg_intf_desc.iInterface = rc;
+
fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
if (unlikely(!fsg))
return -ENOMEM;
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 647b6fef8ad9..108e12292718 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -1258,14 +1258,11 @@ static int mtp_bind_config(struct usb_configuration *c, bool ptp_config)
printk(KERN_INFO "mtp_bind_config\n");
- /* allocate a string ID for our interface */
- if (mtp_string_defs[INTERFACE_STRING_INDEX].id == 0) {
- ret = usb_string_id(c->cdev);
- if (ret < 0)
- return ret;
- mtp_string_defs[INTERFACE_STRING_INDEX].id = ret;
- mtp_interface_desc.iInterface = ret;
- }
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ return ret;
+ mtp_string_defs[INTERFACE_STRING_INDEX].id = ret;
+ mtp_interface_desc.iInterface = ret;
dev->cdev = c->cdev;
dev->function.name = "mtp";
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index e627a276a092..fcdee12863cf 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -847,15 +847,13 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
if (status < 0)
return status;
- if (rndis_string_defs[0].id == 0) {
- status = usb_string_ids_tab(c->cdev, rndis_string_defs);
- if (status)
- return status;
-
- rndis_control_intf.iInterface = rndis_string_defs[0].id;
- rndis_data_intf.iInterface = rndis_string_defs[1].id;
- rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
- }
+ status = usb_string_ids_tab(c->cdev, rndis_string_defs);
+ if (status)
+ return status;
+
+ rndis_control_intf.iInterface = rndis_string_defs[0].id;
+ rndis_data_intf.iInterface = rndis_string_defs[1].id;
+ rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
/* allocate and initialize one new instance */
status = -ENOMEM;