aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2010-02-03 11:10:22 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:54:54 -0500
commit2b626dc134d38d0001b98acf8c7293b6bc5ee86d (patch)
tree7ebdb76b970f985c210d78dbd25f71ea9d957250 /drivers/usb/class/cdc-acm.c
parentd7e18a9f2c506467ec7a9c066da45a0f60c6f5a6 (diff)
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/cdc-acm.c')
-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)
553 553
554 acm = acm_table[tty->index]; 554 acm = acm_table[tty->index];
555 if (!acm || !acm->dev) 555 if (!acm || !acm->dev)
556 goto err_out; 556 goto out;
557 else 557 else
558 rv = 0; 558 rv = 0;
559 559
@@ -569,8 +569,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
569 569
570 mutex_lock(&acm->mutex); 570 mutex_lock(&acm->mutex);
571 if (acm->port.count++) { 571 if (acm->port.count++) {
572 mutex_unlock(&acm->mutex);
572 usb_autopm_put_interface(acm->control); 573 usb_autopm_put_interface(acm->control);
573 goto done; 574 goto out;
574 } 575 }
575 576
576 acm->ctrlurb->dev = acm->dev; 577 acm->ctrlurb->dev = acm->dev;
@@ -599,18 +600,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
599 set_bit(ASYNCB_INITIALIZED, &acm->port.flags); 600 set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
600 rv = tty_port_block_til_ready(&acm->port, tty, filp); 601 rv = tty_port_block_til_ready(&acm->port, tty, filp);
601 tasklet_schedule(&acm->urb_task); 602 tasklet_schedule(&acm->urb_task);
602done: 603
603 mutex_unlock(&acm->mutex); 604 mutex_unlock(&acm->mutex);
604err_out: 605out:
605 mutex_unlock(&open_mutex); 606 mutex_unlock(&open_mutex);
606 return rv; 607 return rv;
607 608
608full_bailout: 609full_bailout:
609 usb_kill_urb(acm->ctrlurb); 610 usb_kill_urb(acm->ctrlurb);
610bail_out: 611bail_out:
611 usb_autopm_put_interface(acm->control);
612 acm->port.count--; 612 acm->port.count--;
613 mutex_unlock(&acm->mutex); 613 mutex_unlock(&acm->mutex);
614 usb_autopm_put_interface(acm->control);
614early_bail: 615early_bail:
615 mutex_unlock(&open_mutex); 616 mutex_unlock(&open_mutex);
616 tty_port_tty_set(&acm->port, NULL); 617 tty_port_tty_set(&acm->port, NULL);