Messages in this thread Patch in this message | | | Date | Tue, 26 May 2015 10:20:22 +0800 | From | "Zhang, Yanmin" <> | Subject | [PATCH 2/3] cdc-acm: call usb_autopm_get_interface_upgrade in, acm_tty_write |
| |
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.zhang@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
| |