From: Michal Nazarewicz on
The full speed descriptors were copied to the usb_function structure
in the fsg_bind_config function before call to the usb_ep_autoconfig.
The usb_ep_autoconfig was called in fsg_bind using the original
descriptors. In effect copied descriptors were not updated.

This patch changes the copy full speed descriptors after the call to
usb_op_autoconfig is performed. This way, copied full speed
descriptors have updated values.

Signed-off-by: Michal Nazarewicz <m.nazarewicz(a)samsung.com>
Cc: Kyungmin Park <kyungmin.park(a)samsung.com>
Reported-by: Dries Van Puymbroeck <Dries.VanPuymbroeck(a)dekimo.com>
Tested-by: Dries Van Puymbroeck <Dries.VanPuymbroeck(a)dekimo.com>
---
Greg, as a bug fix I believe this should be included in 2.6.35 (even
more so since the bug was introduced in .35).

drivers/usb/gadget/f_mass_storage.c | 34 ++++++++++++----------------------
1 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index dc3cec7..b35f0ad 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2998,7 +2998,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
- int rc;
int i;
struct usb_ep *ep;

@@ -3024,6 +3023,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;

+ /* Copy descriptors */
+ f->descriptors = usb_copy_descriptors(fsg_fs_function);
+ if (unlikely(!f->descriptors))
+ return -ENOMEM;
+
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3031,16 +3035,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
- if (unlikely(!f->hs_descriptors))
+ if (unlikely(!f->hs_descriptors)) {
+ usb_free_descriptors(f->descriptors);
return -ENOMEM;
+ }
}

return 0;

autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- rc = -ENOTSUPP;
- return rc;
+ return -ENOTSUPP;
}


@@ -3064,11 +3069,6 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,

fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
- 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;
@@ -3084,19 +3084,9 @@ static int fsg_bind_config(struct usb_composite_dev *cdev,

rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
- goto error_free_all;
-
- 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);
-
+ kfree(fsg);
+ else
+ fsg_common_get(fsg->common);
return rc;
}

--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/