summaryrefslogtreecommitdiff
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2010-02-03 19:10:22 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 01:54:54 +0300
commit2b626dc134d38d0001b98acf8c7293b6bc5ee86d (patch)
tree7ebdb76b970f985c210d78dbd25f71ea9d957250 /drivers/usb/class
parentd7e18a9f2c506467ec7a9c066da45a0f60c6f5a6 (diff)
downloadlinux-2b626dc134d38d0001b98acf8c7293b6bc5ee86d.tar.xz
USB: cdc-acm: fix possible deadlock with multiple openers
The lock must be dropped before usb_autopm_interface_put() is called Signed-off-by: Oliver Neukum <oliver@neukum.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-acm.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 5155ff2b2282..b97f9309c827 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -553,7 +553,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
acm = acm_table[tty->index];
if (!acm || !acm->dev)
- goto err_out;
+ goto out;
else
rv = 0;
@@ -569,8 +569,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
mutex_lock(&acm->mutex);
if (acm->port.count++) {
+ mutex_unlock(&acm->mutex);
usb_autopm_put_interface(acm->control);
- goto done;
+ goto out;
}
acm->ctrlurb->dev = acm->dev;
@@ -599,18 +600,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
rv = tty_port_block_til_ready(&acm->port, tty, filp);
tasklet_schedule(&acm->urb_task);
-done:
+
mutex_unlock(&acm->mutex);
-err_out:
+out:
mutex_unlock(&open_mutex);
return rv;
full_bailout:
usb_kill_urb(acm->ctrlurb);
bail_out:
- usb_autopm_put_interface(acm->control);
acm->port.count--;
mutex_unlock(&acm->mutex);
+ usb_autopm_put_interface(acm->control);
early_bail:
mutex_unlock(&open_mutex);
tty_port_tty_set(&acm->port, NULL);