diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-08-06 21:41:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-13 20:32:57 -0400 |
commit | 672c4e1843c54227ff1bdf1fdd96f9c45c56aa85 (patch) | |
tree | 0058bc781a433751b193e92c6fc65dbcda2ef64e /drivers | |
parent | 1f1ba11b64947051fc32aa15fcccef6463b433f7 (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.c | 15 |
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); |