aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-08-06 21:41:12 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-13 20:32:57 -0400
commit672c4e1843c54227ff1bdf1fdd96f9c45c56aa85 (patch)
tree0058bc781a433751b193e92c6fc65dbcda2ef64e /drivers
parent1f1ba11b64947051fc32aa15fcccef6463b433f7 (diff)
usb: cdc-acm: bugfix release()
Bugfixes to the usb_driver_release_interface() usage; (a) make sure releasing *either* interface first will release the other, instead of insisting it be the control interface; (b) remove the recently-added self-deadlock. (The "fix disconnect bug in cdc-acm" patch was incomplete and incorrect.) Plus a small "sparse" fix: rename a local variable so it doesn't shadow a function parameter. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/class/cdc-acm.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index a92395bf5f5b..910247d191e8 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1108,9 +1108,11 @@ skip_normal_probe:
1108 rcv->instance = acm; 1108 rcv->instance = acm;
1109 } 1109 }
1110 for (i = 0; i < num_rx_buf; i++) { 1110 for (i = 0; i < num_rx_buf; i++) {
1111 struct acm_rb *buf = &(acm->rb[i]); 1111 struct acm_rb *rb = &(acm->rb[i]);
1112 1112
1113 if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { 1113 rb->base = usb_buffer_alloc(acm->dev, readsize,
1114 GFP_KERNEL, &rb->dma);
1115 if (!rb->base) {
1114 dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); 1116 dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
1115 goto alloc_fail7; 1117 goto alloc_fail7;
1116 } 1118 }
@@ -1172,6 +1174,7 @@ skip_countries:
1172 acm_set_line(acm, &acm->line); 1174 acm_set_line(acm, &acm->line);
1173 1175
1174 usb_driver_claim_interface(&acm_driver, data_interface, acm); 1176 usb_driver_claim_interface(&acm_driver, data_interface, acm);
1177 usb_set_intfdata(data_interface, acm);
1175 1178
1176 usb_get_intf(control_interface); 1179 usb_get_intf(control_interface);
1177 tty_register_device(acm_tty_driver, minor, &control_interface->dev); 1180 tty_register_device(acm_tty_driver, minor, &control_interface->dev);
@@ -1221,11 +1224,11 @@ static void acm_disconnect(struct usb_interface *intf)
1221 struct acm *acm = usb_get_intfdata(intf); 1224 struct acm *acm = usb_get_intfdata(intf);
1222 struct usb_device *usb_dev = interface_to_usbdev(intf); 1225 struct usb_device *usb_dev = interface_to_usbdev(intf);
1223 1226
1224 mutex_lock(&open_mutex); 1227 /* sibling interface is already cleaning up */
1225 if (!acm || !acm->dev) { 1228 if (!acm)
1226 mutex_unlock(&open_mutex);
1227 return; 1229 return;
1228 } 1230
1231 mutex_lock(&open_mutex);
1229 if (acm->country_codes){ 1232 if (acm->country_codes){
1230 device_remove_file(&acm->control->dev, 1233 device_remove_file(&acm->control->dev,
1231 &dev_attr_wCountryCodes); 1234 &dev_attr_wCountryCodes);