summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-03-29 14:01:32 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 13:21:36 -0700
commit0fb2c2a1692b8f77be25d38f8802b0142cb6e6bc (patch)
treea9fee9add6aef38f6ddc2d70e1c94750366d7864
parentdd0543ecc638947d67bdd3a8a41b95ed3c7b885e (diff)
downloadlinux-stable-0fb2c2a1692b8f77be25d38f8802b0142cb6e6bc.tar.gz
linux-stable-0fb2c2a1692b8f77be25d38f8802b0142cb6e6bc.tar.bz2
linux-stable-0fb2c2a1692b8f77be25d38f8802b0142cb6e6bc.zip
USB: gadget: f_mass_storage: per function
Mass Storage Function (MSF) used the same descriptors for each usb_function instance (meaning usb_function::descriptors of different functions pointed to the same static area (the same was true for usb_function::hs_descriptors)). This would leads to problems if MSF were used in several USB configurations with different interface and/or endpoint numbers. Descriptors for all configurations would have interface/endpoint numbers overwritten by the values valid for the last configuration. This patch adds code that copies the descriptors each time MSF is added to USB configuration (that is for each usb_function). Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com>
-rw-r--r--drivers/usb/gadget/f_mass_storage.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 218f51db9721..9dbe86dec332 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2919,6 +2919,8 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(fsg, "unbind\n");
fsg_common_put(fsg->common);
+ usb_free_descriptors(fsg->function.descriptors);
+ usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
}
@@ -2959,7 +2961,9 @@ static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
- f->hs_descriptors = fsg_hs_function;
+ f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
+ if (unlikely(!f->hs_descriptors))
+ return -ENOMEM;
}
return 0;
@@ -2991,7 +2995,11 @@ static int fsg_add(struct usb_composite_dev *cdev,
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
- fsg->function.descriptors = fsg_fs_function;
+ fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
+ if (unlikely(!fsg->function.descriptors)) {
+ rc = -ENOMEM;
+ goto error_free_fsg;
+ }
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@@ -3006,11 +3014,19 @@ static int fsg_add(struct usb_composite_dev *cdev,
* call to usb_add_function() was successful. */
rc = usb_add_function(c, &fsg->function);
+ if (unlikely(rc))
+ goto error_free_all;
- if (likely(rc == 0))
- fsg_common_get(fsg->common);
- else
- kfree(fsg);
+ fsg_common_get(fsg->common);
+ return 0;
+
+error_free_all:
+ usb_free_descriptors(fsg->function.descriptors);
+ /* fsg_bind() might have copied those; or maybe not? who cares
+ * -- free it just in case. */
+ usb_free_descriptors(fsg->function.hs_descriptors);
+error_free_fsg:
+ kfree(fsg);
return rc;
}