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> BUG=chrome-os-partner:3143 TEST=run power_Resume test in tight loops on Alex. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Review URL: http://codereview.chromium.org/6820034 Change-Id: Ic0e9c134b803393c66dbec7d4a66e2b7af5ceae4
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5fb3117..fc74de7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c
@@ -556,7 +556,7 @@ acm = acm_table[tty->index]; if (!acm || !acm->dev) - goto err_out; + goto out; else rv = 0; @@ -572,8 +572,9 @@ 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; @@ -602,18 +603,18 @@ 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);