diff options
author | Oliver Neukum <oliver@neukum.org> | 2010-02-03 17:10:22 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 14:54:54 -0800 |
commit | 2b626dc134d38d0001b98acf8c7293b6bc5ee86d (patch) | |
tree | 7ebdb76b970f985c210d78dbd25f71ea9d957250 | |
parent | d7e18a9f2c506467ec7a9c066da45a0f60c6f5a6 (diff) | |
download | kernel_samsung_aries-2b626dc134d38d0001b98acf8c7293b6bc5ee86d.zip kernel_samsung_aries-2b626dc134d38d0001b98acf8c7293b6bc5ee86d.tar.gz kernel_samsung_aries-2b626dc134d38d0001b98acf8c7293b6bc5ee86d.tar.bz2 |
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>
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5155ff2..b97f930 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); |