From: Zhang Yanmin <yanmin.zh...@intel.com> acm device might be used as ldisc device by n_gsm driver. gsmtty_write and other gsm functions calls acm_tty_write indirectly while they holds spinlocks.
Meanwhile, application might access ACM tty device directly. Here we choose to call usb_autopm_get_interface_upgrade instead of usb_autopm_get_interface_async to make sure above 2 scenarios can work well. Signed-off-by: Zhang Yanmin <yanmin.zh...@intel.com> --- drivers/usb/class/cdc-acm.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5c8f581..6ad85a3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -689,10 +689,15 @@ static int acm_tty_write(struct tty_struct *tty, dev_vdbg(&acm->data->dev, "%s - count %d\n", __func__, count); + stat = usb_autopm_get_interface_upgrade(acm->control); + if (stat) + return stat; + spin_lock_irqsave(&acm->write_lock, flags); wbn = acm_wb_alloc(acm); if (wbn < 0) { spin_unlock_irqrestore(&acm->write_lock, flags); + usb_autopm_put_interface(acm->control); return 0; } wb = &acm->wb[wbn]; @@ -700,6 +705,7 @@ static int acm_tty_write(struct tty_struct *tty, if (!acm->dev) { wb->use = 0; spin_unlock_irqrestore(&acm->write_lock, flags); + usb_autopm_put_interface(acm->control); return -ENODEV; } @@ -708,13 +714,6 @@ static int acm_tty_write(struct tty_struct *tty, memcpy(wb->buf, buf, count); wb->len = count; - stat = usb_autopm_get_interface_async(acm->control); - if (stat) { - wb->use = 0; - spin_unlock_irqrestore(&acm->write_lock, flags); - return stat; - } - if (acm->susp_count) { usb_anchor_urb(wb->urb, &acm->delayed); spin_unlock_irqrestore(&acm->write_lock, flags); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/