diff options
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e72a657a6177..56419254ef75 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -573,6 +573,8 @@ static void acm_port_destruct(struct tty_port *port) | |||
573 | static void acm_port_shutdown(struct tty_port *port) | 573 | static void acm_port_shutdown(struct tty_port *port) |
574 | { | 574 | { |
575 | struct acm *acm = container_of(port, struct acm, port); | 575 | struct acm *acm = container_of(port, struct acm, port); |
576 | struct urb *urb; | ||
577 | struct acm_wb *wb; | ||
576 | int i; | 578 | int i; |
577 | 579 | ||
578 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 580 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
@@ -581,6 +583,16 @@ static void acm_port_shutdown(struct tty_port *port) | |||
581 | if (!acm->disconnected) { | 583 | if (!acm->disconnected) { |
582 | usb_autopm_get_interface(acm->control); | 584 | usb_autopm_get_interface(acm->control); |
583 | acm_set_control(acm, acm->ctrlout = 0); | 585 | acm_set_control(acm, acm->ctrlout = 0); |
586 | |||
587 | for (;;) { | ||
588 | urb = usb_get_from_anchor(&acm->delayed); | ||
589 | if (!urb) | ||
590 | break; | ||
591 | wb = urb->context; | ||
592 | wb->use = 0; | ||
593 | usb_autopm_put_interface_async(acm->control); | ||
594 | } | ||
595 | |||
584 | usb_kill_urb(acm->ctrlurb); | 596 | usb_kill_urb(acm->ctrlurb); |
585 | for (i = 0; i < ACM_NW; i++) | 597 | for (i = 0; i < ACM_NW; i++) |
586 | usb_kill_urb(acm->wb[i].urb); | 598 | usb_kill_urb(acm->wb[i].urb); |
@@ -648,12 +660,9 @@ static int acm_tty_write(struct tty_struct *tty, | |||
648 | 660 | ||
649 | usb_autopm_get_interface_async(acm->control); | 661 | usb_autopm_get_interface_async(acm->control); |
650 | if (acm->susp_count) { | 662 | if (acm->susp_count) { |
651 | if (!acm->delayed_wb) | 663 | usb_anchor_urb(wb->urb, &acm->delayed); |
652 | acm->delayed_wb = wb; | ||
653 | else | ||
654 | usb_autopm_put_interface_async(acm->control); | ||
655 | spin_unlock_irqrestore(&acm->write_lock, flags); | 664 | spin_unlock_irqrestore(&acm->write_lock, flags); |
656 | return count; /* A white lie */ | 665 | return count; |
657 | } | 666 | } |
658 | usb_mark_last_busy(acm->dev); | 667 | usb_mark_last_busy(acm->dev); |
659 | 668 | ||
@@ -1269,6 +1278,7 @@ made_compressed_probe: | |||
1269 | acm->bInterval = epread->bInterval; | 1278 | acm->bInterval = epread->bInterval; |
1270 | tty_port_init(&acm->port); | 1279 | tty_port_init(&acm->port); |
1271 | acm->port.ops = &acm_port_ops; | 1280 | acm->port.ops = &acm_port_ops; |
1281 | init_usb_anchor(&acm->delayed); | ||
1272 | 1282 | ||
1273 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 1283 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
1274 | if (!buf) { | 1284 | if (!buf) { |
@@ -1539,7 +1549,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1539 | static int acm_resume(struct usb_interface *intf) | 1549 | static int acm_resume(struct usb_interface *intf) |
1540 | { | 1550 | { |
1541 | struct acm *acm = usb_get_intfdata(intf); | 1551 | struct acm *acm = usb_get_intfdata(intf); |
1542 | struct acm_wb *wb; | 1552 | struct urb *urb; |
1543 | int rv = 0; | 1553 | int rv = 0; |
1544 | 1554 | ||
1545 | spin_lock_irq(&acm->read_lock); | 1555 | spin_lock_irq(&acm->read_lock); |
@@ -1551,10 +1561,12 @@ static int acm_resume(struct usb_interface *intf) | |||
1551 | if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { | 1561 | if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { |
1552 | rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC); | 1562 | rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC); |
1553 | 1563 | ||
1554 | if (acm->delayed_wb) { | 1564 | for (;;) { |
1555 | wb = acm->delayed_wb; | 1565 | urb = usb_get_from_anchor(&acm->delayed); |
1556 | acm->delayed_wb = NULL; | 1566 | if (!urb) |
1557 | acm_start_wb(acm, wb); | 1567 | break; |
1568 | |||
1569 | acm_start_wb(acm, urb->context); | ||
1558 | } | 1570 | } |
1559 | 1571 | ||
1560 | /* | 1572 | /* |