diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/usb/class/cdc-acm.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 557 |
1 files changed, 261 insertions, 296 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 2d92cce260d..a06f2cdc610 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -58,62 +58,12 @@ static struct usb_driver acm_driver; | |||
58 | static struct tty_driver *acm_tty_driver; | 58 | static struct tty_driver *acm_tty_driver; |
59 | static struct acm *acm_table[ACM_TTY_MINORS]; | 59 | static struct acm *acm_table[ACM_TTY_MINORS]; |
60 | 60 | ||
61 | static DEFINE_MUTEX(acm_table_lock); | 61 | static DEFINE_MUTEX(open_mutex); |
62 | 62 | ||
63 | /* | 63 | #define ACM_READY(acm) (acm && acm->dev && acm->port.count) |
64 | * acm_table accessors | ||
65 | */ | ||
66 | |||
67 | /* | ||
68 | * Look up an ACM structure by index. If found and not disconnected, increment | ||
69 | * its refcount and return it with its mutex held. | ||
70 | */ | ||
71 | static struct acm *acm_get_by_index(unsigned index) | ||
72 | { | ||
73 | struct acm *acm; | ||
74 | |||
75 | mutex_lock(&acm_table_lock); | ||
76 | acm = acm_table[index]; | ||
77 | if (acm) { | ||
78 | mutex_lock(&acm->mutex); | ||
79 | if (acm->disconnected) { | ||
80 | mutex_unlock(&acm->mutex); | ||
81 | acm = NULL; | ||
82 | } else { | ||
83 | tty_port_get(&acm->port); | ||
84 | mutex_unlock(&acm->mutex); | ||
85 | } | ||
86 | } | ||
87 | mutex_unlock(&acm_table_lock); | ||
88 | return acm; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Try to find an available minor number and if found, associate it with 'acm'. | ||
93 | */ | ||
94 | static int acm_alloc_minor(struct acm *acm) | ||
95 | { | ||
96 | int minor; | ||
97 | |||
98 | mutex_lock(&acm_table_lock); | ||
99 | for (minor = 0; minor < ACM_TTY_MINORS; minor++) { | ||
100 | if (!acm_table[minor]) { | ||
101 | acm_table[minor] = acm; | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | mutex_unlock(&acm_table_lock); | ||
106 | |||
107 | return minor; | ||
108 | } | ||
109 | 64 | ||
110 | /* Release the minor number associated with 'acm'. */ | 65 | static const struct tty_port_operations acm_port_ops = { |
111 | static void acm_release_minor(struct acm *acm) | 66 | }; |
112 | { | ||
113 | mutex_lock(&acm_table_lock); | ||
114 | acm_table[acm->minor] = NULL; | ||
115 | mutex_unlock(&acm_table_lock); | ||
116 | } | ||
117 | 67 | ||
118 | /* | 68 | /* |
119 | * Functions for ACM control messages. | 69 | * Functions for ACM control messages. |
@@ -205,7 +155,6 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) | |||
205 | wb->urb->transfer_dma = wb->dmah; | 155 | wb->urb->transfer_dma = wb->dmah; |
206 | wb->urb->transfer_buffer_length = wb->len; | 156 | wb->urb->transfer_buffer_length = wb->len; |
207 | wb->urb->dev = acm->dev; | 157 | wb->urb->dev = acm->dev; |
208 | |||
209 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); | 158 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); |
210 | if (rc < 0) { | 159 | if (rc < 0) { |
211 | dev_err(&acm->data->dev, | 160 | dev_err(&acm->data->dev, |
@@ -221,6 +170,9 @@ static int acm_write_start(struct acm *acm, int wbn) | |||
221 | unsigned long flags; | 170 | unsigned long flags; |
222 | struct acm_wb *wb = &acm->wb[wbn]; | 171 | struct acm_wb *wb = &acm->wb[wbn]; |
223 | int rc; | 172 | int rc; |
173 | #ifdef CONFIG_PM | ||
174 | struct urb *res; | ||
175 | #endif | ||
224 | 176 | ||
225 | spin_lock_irqsave(&acm->write_lock, flags); | 177 | spin_lock_irqsave(&acm->write_lock, flags); |
226 | if (!acm->dev) { | 178 | if (!acm->dev) { |
@@ -233,15 +185,33 @@ static int acm_write_start(struct acm *acm, int wbn) | |||
233 | acm->susp_count); | 185 | acm->susp_count); |
234 | usb_autopm_get_interface_async(acm->control); | 186 | usb_autopm_get_interface_async(acm->control); |
235 | if (acm->susp_count) { | 187 | if (acm->susp_count) { |
188 | #ifdef CONFIG_PM | ||
189 | acm->transmitting++; | ||
190 | wb->urb->transfer_buffer = wb->buf; | ||
191 | wb->urb->transfer_dma = wb->dmah; | ||
192 | wb->urb->transfer_buffer_length = wb->len; | ||
193 | wb->urb->dev = acm->dev; | ||
194 | usb_anchor_urb(wb->urb, &acm->deferred); | ||
195 | #else | ||
236 | if (!acm->delayed_wb) | 196 | if (!acm->delayed_wb) |
237 | acm->delayed_wb = wb; | 197 | acm->delayed_wb = wb; |
238 | else | 198 | else |
239 | usb_autopm_put_interface_async(acm->control); | 199 | usb_autopm_put_interface_async(acm->control); |
200 | #endif | ||
240 | spin_unlock_irqrestore(&acm->write_lock, flags); | 201 | spin_unlock_irqrestore(&acm->write_lock, flags); |
241 | return 0; /* A white lie */ | 202 | return 0; /* A white lie */ |
242 | } | 203 | } |
243 | usb_mark_last_busy(acm->dev); | 204 | usb_mark_last_busy(acm->dev); |
244 | 205 | #ifdef CONFIG_PM | |
206 | while ((res = usb_get_from_anchor(&acm->deferred))) { | ||
207 | rc = usb_submit_urb(res, GFP_ATOMIC); | ||
208 | if (rc < 0) { | ||
209 | dbg("usb_submit_urb(pending request) failed: %d", rc); | ||
210 | usb_unanchor_urb(res); | ||
211 | acm_write_done(acm, res->context); | ||
212 | } | ||
213 | } | ||
214 | #endif | ||
245 | rc = acm_start_wb(acm, wb); | 215 | rc = acm_start_wb(acm, wb); |
246 | spin_unlock_irqrestore(&acm->write_lock, flags); | 216 | spin_unlock_irqrestore(&acm->write_lock, flags); |
247 | 217 | ||
@@ -317,6 +287,9 @@ static void acm_ctrl_irq(struct urb *urb) | |||
317 | goto exit; | 287 | goto exit; |
318 | } | 288 | } |
319 | 289 | ||
290 | if (!ACM_READY(acm)) | ||
291 | goto exit; | ||
292 | |||
320 | usb_mark_last_busy(acm->dev); | 293 | usb_mark_last_busy(acm->dev); |
321 | 294 | ||
322 | data = (unsigned char *)(dr + 1); | 295 | data = (unsigned char *)(dr + 1); |
@@ -476,7 +449,8 @@ static void acm_write_bulk(struct urb *urb) | |||
476 | spin_lock_irqsave(&acm->write_lock, flags); | 449 | spin_lock_irqsave(&acm->write_lock, flags); |
477 | acm_write_done(acm, wb); | 450 | acm_write_done(acm, wb); |
478 | spin_unlock_irqrestore(&acm->write_lock, flags); | 451 | spin_unlock_irqrestore(&acm->write_lock, flags); |
479 | schedule_work(&acm->work); | 452 | if (ACM_READY(acm)) |
453 | schedule_work(&acm->work); | ||
480 | } | 454 | } |
481 | 455 | ||
482 | static void acm_softint(struct work_struct *work) | 456 | static void acm_softint(struct work_struct *work) |
@@ -486,6 +460,8 @@ static void acm_softint(struct work_struct *work) | |||
486 | 460 | ||
487 | dev_vdbg(&acm->data->dev, "%s\n", __func__); | 461 | dev_vdbg(&acm->data->dev, "%s\n", __func__); |
488 | 462 | ||
463 | if (!ACM_READY(acm)) | ||
464 | return; | ||
489 | tty = tty_port_tty_get(&acm->port); | 465 | tty = tty_port_tty_get(&acm->port); |
490 | if (!tty) | 466 | if (!tty) |
491 | return; | 467 | return; |
@@ -497,125 +473,93 @@ static void acm_softint(struct work_struct *work) | |||
497 | * TTY handlers | 473 | * TTY handlers |
498 | */ | 474 | */ |
499 | 475 | ||
500 | static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty) | 476 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
501 | { | 477 | { |
502 | struct acm *acm; | 478 | struct acm *acm; |
503 | int retval; | 479 | int rv = -ENODEV; |
504 | |||
505 | dev_dbg(tty->dev, "%s\n", __func__); | ||
506 | |||
507 | acm = acm_get_by_index(tty->index); | ||
508 | if (!acm) | ||
509 | return -ENODEV; | ||
510 | |||
511 | retval = tty_standard_install(driver, tty); | ||
512 | if (retval) | ||
513 | goto error_init_termios; | ||
514 | |||
515 | tty->driver_data = acm; | ||
516 | |||
517 | return 0; | ||
518 | 480 | ||
519 | error_init_termios: | 481 | mutex_lock(&open_mutex); |
520 | tty_port_put(&acm->port); | ||
521 | return retval; | ||
522 | } | ||
523 | 482 | ||
524 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) | 483 | acm = acm_table[tty->index]; |
525 | { | 484 | if (!acm || !acm->dev) |
526 | struct acm *acm = tty->driver_data; | 485 | goto out; |
486 | else | ||
487 | rv = 0; | ||
527 | 488 | ||
528 | dev_dbg(tty->dev, "%s\n", __func__); | 489 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
529 | 490 | ||
530 | return tty_port_open(&acm->port, tty, filp); | 491 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); |
531 | } | ||
532 | 492 | ||
533 | static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) | 493 | tty->driver_data = acm; |
534 | { | 494 | tty_port_tty_set(&acm->port, tty); |
535 | struct acm *acm = container_of(port, struct acm, port); | ||
536 | int retval = -ENODEV; | ||
537 | 495 | ||
538 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 496 | if (usb_autopm_get_interface(acm->control) < 0) |
497 | goto early_bail; | ||
498 | else | ||
499 | acm->control->needs_remote_wakeup = 0; | ||
539 | 500 | ||
540 | mutex_lock(&acm->mutex); | 501 | mutex_lock(&acm->mutex); |
541 | if (acm->disconnected) | 502 | if (acm->port.count++) { |
542 | goto disconnected; | 503 | mutex_unlock(&acm->mutex); |
543 | 504 | usb_autopm_put_interface(acm->control); | |
544 | retval = usb_autopm_get_interface(acm->control); | 505 | goto out; |
545 | if (retval) | 506 | } |
546 | goto error_get_interface; | ||
547 | |||
548 | /* | ||
549 | * FIXME: Why do we need this? Allocating 64K of physically contiguous | ||
550 | * memory is really nasty... | ||
551 | */ | ||
552 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); | ||
553 | acm->control->needs_remote_wakeup = 1; | ||
554 | 507 | ||
555 | acm->ctrlurb->dev = acm->dev; | 508 | acm->ctrlurb->dev = acm->dev; |
556 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { | 509 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { |
557 | dev_err(&acm->control->dev, | 510 | dev_err(&acm->control->dev, |
558 | "%s - usb_submit_urb(ctrl irq) failed\n", __func__); | 511 | "%s - usb_submit_urb(ctrl irq) failed\n", __func__); |
559 | goto error_submit_urb; | 512 | goto bail_out; |
560 | } | 513 | } |
561 | 514 | ||
562 | acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; | 515 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && |
563 | if (acm_set_control(acm, acm->ctrlout) < 0 && | ||
564 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) | 516 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) |
565 | goto error_set_control; | 517 | goto bail_out; |
566 | 518 | ||
567 | usb_autopm_put_interface(acm->control); | 519 | usb_autopm_put_interface(acm->control); |
568 | 520 | ||
569 | /* | ||
570 | * Unthrottle device in case the TTY was closed while throttled. | ||
571 | */ | ||
572 | spin_lock_irq(&acm->read_lock); | ||
573 | acm->throttled = 0; | ||
574 | acm->throttle_req = 0; | ||
575 | spin_unlock_irq(&acm->read_lock); | ||
576 | |||
577 | if (acm_submit_read_urbs(acm, GFP_KERNEL)) | 521 | if (acm_submit_read_urbs(acm, GFP_KERNEL)) |
578 | goto error_submit_read_urbs; | 522 | goto bail_out; |
579 | 523 | ||
580 | mutex_unlock(&acm->mutex); | 524 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
525 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | ||
581 | 526 | ||
582 | return 0; | 527 | mutex_unlock(&acm->mutex); |
528 | out: | ||
529 | mutex_unlock(&open_mutex); | ||
530 | return rv; | ||
583 | 531 | ||
584 | error_submit_read_urbs: | 532 | bail_out: |
585 | acm->ctrlout = 0; | 533 | acm->port.count--; |
586 | acm_set_control(acm, acm->ctrlout); | ||
587 | error_set_control: | ||
588 | usb_kill_urb(acm->ctrlurb); | ||
589 | error_submit_urb: | ||
590 | usb_autopm_put_interface(acm->control); | ||
591 | error_get_interface: | ||
592 | disconnected: | ||
593 | mutex_unlock(&acm->mutex); | 534 | mutex_unlock(&acm->mutex); |
594 | return retval; | 535 | usb_autopm_put_interface(acm->control); |
536 | early_bail: | ||
537 | mutex_unlock(&open_mutex); | ||
538 | tty_port_tty_set(&acm->port, NULL); | ||
539 | return -EIO; | ||
595 | } | 540 | } |
596 | 541 | ||
597 | static void acm_port_destruct(struct tty_port *port) | 542 | static void acm_tty_unregister(struct acm *acm) |
598 | { | 543 | { |
599 | struct acm *acm = container_of(port, struct acm, port); | 544 | int i; |
600 | |||
601 | dev_dbg(&acm->control->dev, "%s\n", __func__); | ||
602 | 545 | ||
603 | tty_unregister_device(acm_tty_driver, acm->minor); | 546 | tty_unregister_device(acm_tty_driver, acm->minor); |
604 | acm_release_minor(acm); | ||
605 | usb_put_intf(acm->control); | 547 | usb_put_intf(acm->control); |
548 | acm_table[acm->minor] = NULL; | ||
549 | usb_free_urb(acm->ctrlurb); | ||
550 | for (i = 0; i < ACM_NW; i++) | ||
551 | usb_free_urb(acm->wb[i].urb); | ||
552 | for (i = 0; i < acm->rx_buflimit; i++) | ||
553 | usb_free_urb(acm->read_urbs[i]); | ||
606 | kfree(acm->country_codes); | 554 | kfree(acm->country_codes); |
607 | kfree(acm); | 555 | kfree(acm); |
608 | } | 556 | } |
609 | 557 | ||
610 | static void acm_port_shutdown(struct tty_port *port) | 558 | static void acm_port_down(struct acm *acm) |
611 | { | 559 | { |
612 | struct acm *acm = container_of(port, struct acm, port); | ||
613 | int i; | 560 | int i; |
614 | 561 | ||
615 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 562 | if (acm->dev) { |
616 | |||
617 | mutex_lock(&acm->mutex); | ||
618 | if (!acm->disconnected) { | ||
619 | usb_autopm_get_interface(acm->control); | 563 | usb_autopm_get_interface(acm->control); |
620 | acm_set_control(acm, acm->ctrlout = 0); | 564 | acm_set_control(acm, acm->ctrlout = 0); |
621 | usb_kill_urb(acm->ctrlurb); | 565 | usb_kill_urb(acm->ctrlurb); |
@@ -626,28 +570,48 @@ static void acm_port_shutdown(struct tty_port *port) | |||
626 | acm->control->needs_remote_wakeup = 0; | 570 | acm->control->needs_remote_wakeup = 0; |
627 | usb_autopm_put_interface(acm->control); | 571 | usb_autopm_put_interface(acm->control); |
628 | } | 572 | } |
629 | mutex_unlock(&acm->mutex); | ||
630 | } | ||
631 | |||
632 | static void acm_tty_cleanup(struct tty_struct *tty) | ||
633 | { | ||
634 | struct acm *acm = tty->driver_data; | ||
635 | dev_dbg(&acm->control->dev, "%s\n", __func__); | ||
636 | tty_port_put(&acm->port); | ||
637 | } | 573 | } |
638 | 574 | ||
639 | static void acm_tty_hangup(struct tty_struct *tty) | 575 | static void acm_tty_hangup(struct tty_struct *tty) |
640 | { | 576 | { |
641 | struct acm *acm = tty->driver_data; | 577 | struct acm *acm; |
642 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 578 | |
579 | mutex_lock(&open_mutex); | ||
580 | acm = tty->driver_data; | ||
581 | |||
582 | if (!acm) | ||
583 | goto out; | ||
584 | |||
643 | tty_port_hangup(&acm->port); | 585 | tty_port_hangup(&acm->port); |
586 | acm_port_down(acm); | ||
587 | |||
588 | out: | ||
589 | mutex_unlock(&open_mutex); | ||
644 | } | 590 | } |
645 | 591 | ||
646 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 592 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
647 | { | 593 | { |
648 | struct acm *acm = tty->driver_data; | 594 | struct acm *acm = tty->driver_data; |
649 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 595 | |
650 | tty_port_close(&acm->port, tty, filp); | 596 | /* Perform the closing process and see if we need to do the hardware |
597 | shutdown */ | ||
598 | if (!acm) | ||
599 | return; | ||
600 | |||
601 | mutex_lock(&open_mutex); | ||
602 | if (tty_port_close_start(&acm->port, tty, filp) == 0) { | ||
603 | if (!acm->dev) { | ||
604 | tty_port_tty_set(&acm->port, NULL); | ||
605 | acm_tty_unregister(acm); | ||
606 | tty->driver_data = NULL; | ||
607 | } | ||
608 | mutex_unlock(&open_mutex); | ||
609 | return; | ||
610 | } | ||
611 | acm_port_down(acm); | ||
612 | tty_port_close_end(&acm->port, tty); | ||
613 | tty_port_tty_set(&acm->port, NULL); | ||
614 | mutex_unlock(&open_mutex); | ||
651 | } | 615 | } |
652 | 616 | ||
653 | static int acm_tty_write(struct tty_struct *tty, | 617 | static int acm_tty_write(struct tty_struct *tty, |
@@ -659,6 +623,8 @@ static int acm_tty_write(struct tty_struct *tty, | |||
659 | int wbn; | 623 | int wbn; |
660 | struct acm_wb *wb; | 624 | struct acm_wb *wb; |
661 | 625 | ||
626 | if (!ACM_READY(acm)) | ||
627 | return -EINVAL; | ||
662 | if (!count) | 628 | if (!count) |
663 | return 0; | 629 | return 0; |
664 | 630 | ||
@@ -687,6 +653,8 @@ static int acm_tty_write(struct tty_struct *tty, | |||
687 | static int acm_tty_write_room(struct tty_struct *tty) | 653 | static int acm_tty_write_room(struct tty_struct *tty) |
688 | { | 654 | { |
689 | struct acm *acm = tty->driver_data; | 655 | struct acm *acm = tty->driver_data; |
656 | if (!ACM_READY(acm)) | ||
657 | return -EINVAL; | ||
690 | /* | 658 | /* |
691 | * Do not let the line discipline to know that we have a reserve, | 659 | * Do not let the line discipline to know that we have a reserve, |
692 | * or it might get too enthusiastic. | 660 | * or it might get too enthusiastic. |
@@ -697,11 +665,7 @@ static int acm_tty_write_room(struct tty_struct *tty) | |||
697 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) | 665 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) |
698 | { | 666 | { |
699 | struct acm *acm = tty->driver_data; | 667 | struct acm *acm = tty->driver_data; |
700 | /* | 668 | if (!ACM_READY(acm)) |
701 | * if the device was unplugged then any remaining characters fell out | ||
702 | * of the connector ;) | ||
703 | */ | ||
704 | if (acm->disconnected) | ||
705 | return 0; | 669 | return 0; |
706 | /* | 670 | /* |
707 | * This is inaccurate (overcounts), but it works. | 671 | * This is inaccurate (overcounts), but it works. |
@@ -713,6 +677,9 @@ static void acm_tty_throttle(struct tty_struct *tty) | |||
713 | { | 677 | { |
714 | struct acm *acm = tty->driver_data; | 678 | struct acm *acm = tty->driver_data; |
715 | 679 | ||
680 | if (!ACM_READY(acm)) | ||
681 | return; | ||
682 | |||
716 | spin_lock_irq(&acm->read_lock); | 683 | spin_lock_irq(&acm->read_lock); |
717 | acm->throttle_req = 1; | 684 | acm->throttle_req = 1; |
718 | spin_unlock_irq(&acm->read_lock); | 685 | spin_unlock_irq(&acm->read_lock); |
@@ -723,6 +690,9 @@ static void acm_tty_unthrottle(struct tty_struct *tty) | |||
723 | struct acm *acm = tty->driver_data; | 690 | struct acm *acm = tty->driver_data; |
724 | unsigned int was_throttled; | 691 | unsigned int was_throttled; |
725 | 692 | ||
693 | if (!ACM_READY(acm)) | ||
694 | return; | ||
695 | |||
726 | spin_lock_irq(&acm->read_lock); | 696 | spin_lock_irq(&acm->read_lock); |
727 | was_throttled = acm->throttled; | 697 | was_throttled = acm->throttled; |
728 | acm->throttled = 0; | 698 | acm->throttled = 0; |
@@ -737,7 +707,8 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state) | |||
737 | { | 707 | { |
738 | struct acm *acm = tty->driver_data; | 708 | struct acm *acm = tty->driver_data; |
739 | int retval; | 709 | int retval; |
740 | 710 | if (!ACM_READY(acm)) | |
711 | return -EINVAL; | ||
741 | retval = acm_send_break(acm, state ? 0xffff : 0); | 712 | retval = acm_send_break(acm, state ? 0xffff : 0); |
742 | if (retval < 0) | 713 | if (retval < 0) |
743 | dev_dbg(&acm->control->dev, "%s - send break failed\n", | 714 | dev_dbg(&acm->control->dev, "%s - send break failed\n", |
@@ -749,6 +720,9 @@ static int acm_tty_tiocmget(struct tty_struct *tty) | |||
749 | { | 720 | { |
750 | struct acm *acm = tty->driver_data; | 721 | struct acm *acm = tty->driver_data; |
751 | 722 | ||
723 | if (!ACM_READY(acm)) | ||
724 | return -EINVAL; | ||
725 | |||
752 | return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | | 726 | return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | |
753 | (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | | 727 | (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | |
754 | (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | | 728 | (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | |
@@ -763,6 +737,9 @@ static int acm_tty_tiocmset(struct tty_struct *tty, | |||
763 | struct acm *acm = tty->driver_data; | 737 | struct acm *acm = tty->driver_data; |
764 | unsigned int newctrl; | 738 | unsigned int newctrl; |
765 | 739 | ||
740 | if (!ACM_READY(acm)) | ||
741 | return -EINVAL; | ||
742 | |||
766 | newctrl = acm->ctrlout; | 743 | newctrl = acm->ctrlout; |
767 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | | 744 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | |
768 | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); | 745 | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); |
@@ -776,75 +753,15 @@ static int acm_tty_tiocmset(struct tty_struct *tty, | |||
776 | return acm_set_control(acm, acm->ctrlout = newctrl); | 753 | return acm_set_control(acm, acm->ctrlout = newctrl); |
777 | } | 754 | } |
778 | 755 | ||
779 | static int get_serial_info(struct acm *acm, struct serial_struct __user *info) | ||
780 | { | ||
781 | struct serial_struct tmp; | ||
782 | |||
783 | if (!info) | ||
784 | return -EINVAL; | ||
785 | |||
786 | memset(&tmp, 0, sizeof(tmp)); | ||
787 | tmp.flags = ASYNC_LOW_LATENCY; | ||
788 | tmp.xmit_fifo_size = acm->writesize; | ||
789 | tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); | ||
790 | tmp.close_delay = acm->port.close_delay / 10; | ||
791 | tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? | ||
792 | ASYNC_CLOSING_WAIT_NONE : | ||
793 | acm->port.closing_wait / 10; | ||
794 | |||
795 | if (copy_to_user(info, &tmp, sizeof(tmp))) | ||
796 | return -EFAULT; | ||
797 | else | ||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static int set_serial_info(struct acm *acm, | ||
802 | struct serial_struct __user *newinfo) | ||
803 | { | ||
804 | struct serial_struct new_serial; | ||
805 | unsigned int closing_wait, close_delay; | ||
806 | int retval = 0; | ||
807 | |||
808 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | ||
809 | return -EFAULT; | ||
810 | |||
811 | close_delay = new_serial.close_delay * 10; | ||
812 | closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? | ||
813 | ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; | ||
814 | |||
815 | mutex_lock(&acm->port.mutex); | ||
816 | |||
817 | if (!capable(CAP_SYS_ADMIN)) { | ||
818 | if ((close_delay != acm->port.close_delay) || | ||
819 | (closing_wait != acm->port.closing_wait)) | ||
820 | retval = -EPERM; | ||
821 | else | ||
822 | retval = -EOPNOTSUPP; | ||
823 | } else { | ||
824 | acm->port.close_delay = close_delay; | ||
825 | acm->port.closing_wait = closing_wait; | ||
826 | } | ||
827 | |||
828 | mutex_unlock(&acm->port.mutex); | ||
829 | return retval; | ||
830 | } | ||
831 | |||
832 | static int acm_tty_ioctl(struct tty_struct *tty, | 756 | static int acm_tty_ioctl(struct tty_struct *tty, |
833 | unsigned int cmd, unsigned long arg) | 757 | unsigned int cmd, unsigned long arg) |
834 | { | 758 | { |
835 | struct acm *acm = tty->driver_data; | 759 | struct acm *acm = tty->driver_data; |
836 | int rv = -ENOIOCTLCMD; | ||
837 | 760 | ||
838 | switch (cmd) { | 761 | if (!ACM_READY(acm)) |
839 | case TIOCGSERIAL: /* gets serial port data */ | 762 | return -EINVAL; |
840 | rv = get_serial_info(acm, (struct serial_struct __user *) arg); | ||
841 | break; | ||
842 | case TIOCSSERIAL: | ||
843 | rv = set_serial_info(acm, (struct serial_struct __user *) arg); | ||
844 | break; | ||
845 | } | ||
846 | 763 | ||
847 | return rv; | 764 | return -ENOIOCTLCMD; |
848 | } | 765 | } |
849 | 766 | ||
850 | static const __u32 acm_tty_speed[] = { | 767 | static const __u32 acm_tty_speed[] = { |
@@ -855,34 +772,27 @@ static const __u32 acm_tty_speed[] = { | |||
855 | 2500000, 3000000, 3500000, 4000000 | 772 | 2500000, 3000000, 3500000, 4000000 |
856 | }; | 773 | }; |
857 | 774 | ||
775 | static const __u8 acm_tty_size[] = { | ||
776 | 5, 6, 7, 8 | ||
777 | }; | ||
778 | |||
858 | static void acm_tty_set_termios(struct tty_struct *tty, | 779 | static void acm_tty_set_termios(struct tty_struct *tty, |
859 | struct ktermios *termios_old) | 780 | struct ktermios *termios_old) |
860 | { | 781 | { |
861 | struct acm *acm = tty->driver_data; | 782 | struct acm *acm = tty->driver_data; |
862 | struct ktermios *termios = &tty->termios; | 783 | struct ktermios *termios = tty->termios; |
863 | struct usb_cdc_line_coding newline; | 784 | struct usb_cdc_line_coding newline; |
864 | int newctrl = acm->ctrlout; | 785 | int newctrl = acm->ctrlout; |
865 | 786 | ||
787 | if (!ACM_READY(acm)) | ||
788 | return; | ||
789 | |||
866 | newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); | 790 | newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); |
867 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; | 791 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; |
868 | newline.bParityType = termios->c_cflag & PARENB ? | 792 | newline.bParityType = termios->c_cflag & PARENB ? |
869 | (termios->c_cflag & PARODD ? 1 : 2) + | 793 | (termios->c_cflag & PARODD ? 1 : 2) + |
870 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; | 794 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; |
871 | switch (termios->c_cflag & CSIZE) { | 795 | newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; |
872 | case CS5: | ||
873 | newline.bDataBits = 5; | ||
874 | break; | ||
875 | case CS6: | ||
876 | newline.bDataBits = 6; | ||
877 | break; | ||
878 | case CS7: | ||
879 | newline.bDataBits = 7; | ||
880 | break; | ||
881 | case CS8: | ||
882 | default: | ||
883 | newline.bDataBits = 8; | ||
884 | break; | ||
885 | } | ||
886 | /* FIXME: Needs to clear unsupported bits in the termios */ | 796 | /* FIXME: Needs to clear unsupported bits in the termios */ |
887 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); | 797 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); |
888 | 798 | ||
@@ -906,12 +816,6 @@ static void acm_tty_set_termios(struct tty_struct *tty, | |||
906 | } | 816 | } |
907 | } | 817 | } |
908 | 818 | ||
909 | static const struct tty_port_operations acm_port_ops = { | ||
910 | .shutdown = acm_port_shutdown, | ||
911 | .activate = acm_port_activate, | ||
912 | .destruct = acm_port_destruct, | ||
913 | }; | ||
914 | |||
915 | /* | 819 | /* |
916 | * USB probe and disconnect routines. | 820 | * USB probe and disconnect routines. |
917 | */ | 821 | */ |
@@ -989,8 +893,12 @@ static int acm_probe(struct usb_interface *intf, | |||
989 | quirks = (unsigned long)id->driver_info; | 893 | quirks = (unsigned long)id->driver_info; |
990 | num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; | 894 | num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; |
991 | 895 | ||
896 | /* not a real CDC ACM device */ | ||
897 | if (quirks & NOT_REAL_ACM) | ||
898 | return -ENODEV; | ||
899 | |||
992 | /* handle quirks deadly to normal probing*/ | 900 | /* handle quirks deadly to normal probing*/ |
993 | if (quirks == NO_UNION_NORMAL) { | 901 | if (quirks & NO_UNION_NORMAL) { |
994 | data_interface = usb_ifnum_to_if(usb_dev, 1); | 902 | data_interface = usb_ifnum_to_if(usb_dev, 1); |
995 | control_interface = usb_ifnum_to_if(usb_dev, 0); | 903 | control_interface = usb_ifnum_to_if(usb_dev, 0); |
996 | goto skip_normal_probe; | 904 | goto skip_normal_probe; |
@@ -1043,7 +951,7 @@ static int acm_probe(struct usb_interface *intf, | |||
1043 | case USB_CDC_CALL_MANAGEMENT_TYPE: | 951 | case USB_CDC_CALL_MANAGEMENT_TYPE: |
1044 | call_management_function = buffer[3]; | 952 | call_management_function = buffer[3]; |
1045 | call_interface_num = buffer[4]; | 953 | call_interface_num = buffer[4]; |
1046 | if ((quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) | 954 | if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) |
1047 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); | 955 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); |
1048 | break; | 956 | break; |
1049 | default: | 957 | default: |
@@ -1151,8 +1059,7 @@ skip_normal_probe: | |||
1151 | } | 1059 | } |
1152 | 1060 | ||
1153 | 1061 | ||
1154 | if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || | 1062 | if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) |
1155 | control_interface->cur_altsetting->desc.bNumEndpoints == 0) | ||
1156 | return -EINVAL; | 1063 | return -EINVAL; |
1157 | 1064 | ||
1158 | epctrl = &control_interface->cur_altsetting->endpoint[0].desc; | 1065 | epctrl = &control_interface->cur_altsetting->endpoint[0].desc; |
@@ -1172,6 +1079,12 @@ skip_normal_probe: | |||
1172 | } | 1079 | } |
1173 | made_compressed_probe: | 1080 | made_compressed_probe: |
1174 | dev_dbg(&intf->dev, "interfaces are valid\n"); | 1081 | dev_dbg(&intf->dev, "interfaces are valid\n"); |
1082 | for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); | ||
1083 | |||
1084 | if (minor == ACM_TTY_MINORS) { | ||
1085 | dev_err(&intf->dev, "no more free acm devices\n"); | ||
1086 | return -ENODEV; | ||
1087 | } | ||
1175 | 1088 | ||
1176 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); | 1089 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); |
1177 | if (acm == NULL) { | 1090 | if (acm == NULL) { |
@@ -1179,18 +1092,11 @@ made_compressed_probe: | |||
1179 | goto alloc_fail; | 1092 | goto alloc_fail; |
1180 | } | 1093 | } |
1181 | 1094 | ||
1182 | minor = acm_alloc_minor(acm); | 1095 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); |
1183 | if (minor == ACM_TTY_MINORS) { | 1096 | readsize = le16_to_cpu(epread->wMaxPacketSize) * |
1184 | dev_err(&intf->dev, "no more free acm devices\n"); | ||
1185 | kfree(acm); | ||
1186 | return -ENODEV; | ||
1187 | } | ||
1188 | |||
1189 | ctrlsize = usb_endpoint_maxp(epctrl); | ||
1190 | readsize = usb_endpoint_maxp(epread) * | ||
1191 | (quirks == SINGLE_RX_URB ? 1 : 2); | 1097 | (quirks == SINGLE_RX_URB ? 1 : 2); |
1192 | acm->combined_interfaces = combined_interfaces; | 1098 | acm->combined_interfaces = combined_interfaces; |
1193 | acm->writesize = usb_endpoint_maxp(epwrite) * 20; | 1099 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; |
1194 | acm->control = control_interface; | 1100 | acm->control = control_interface; |
1195 | acm->data = data_interface; | 1101 | acm->data = data_interface; |
1196 | acm->minor = minor; | 1102 | acm->minor = minor; |
@@ -1202,6 +1108,7 @@ made_compressed_probe: | |||
1202 | acm->readsize = readsize; | 1108 | acm->readsize = readsize; |
1203 | acm->rx_buflimit = num_rx_buf; | 1109 | acm->rx_buflimit = num_rx_buf; |
1204 | INIT_WORK(&acm->work, acm_softint); | 1110 | INIT_WORK(&acm->work, acm_softint); |
1111 | init_usb_anchor(&acm->deferred); | ||
1205 | spin_lock_init(&acm->write_lock); | 1112 | spin_lock_init(&acm->write_lock); |
1206 | spin_lock_init(&acm->read_lock); | 1113 | spin_lock_init(&acm->read_lock); |
1207 | mutex_init(&acm->mutex); | 1114 | mutex_init(&acm->mutex); |
@@ -1209,6 +1116,8 @@ made_compressed_probe: | |||
1209 | acm->is_int_ep = usb_endpoint_xfer_int(epread); | 1116 | acm->is_int_ep = usb_endpoint_xfer_int(epread); |
1210 | if (acm->is_int_ep) | 1117 | if (acm->is_int_ep) |
1211 | acm->bInterval = epread->bInterval; | 1118 | acm->bInterval = epread->bInterval; |
1119 | if (quirks & NO_HANGUP_IN_RESET_RESUME) | ||
1120 | acm->no_hangup_in_reset_resume = 1; | ||
1212 | tty_port_init(&acm->port); | 1121 | tty_port_init(&acm->port); |
1213 | acm->port.ops = &acm_port_ops; | 1122 | acm->port.ops = &acm_port_ops; |
1214 | 1123 | ||
@@ -1281,7 +1190,7 @@ made_compressed_probe: | |||
1281 | 1190 | ||
1282 | if (usb_endpoint_xfer_int(epwrite)) | 1191 | if (usb_endpoint_xfer_int(epwrite)) |
1283 | usb_fill_int_urb(snd->urb, usb_dev, | 1192 | usb_fill_int_urb(snd->urb, usb_dev, |
1284 | usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), | 1193 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
1285 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); | 1194 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); |
1286 | else | 1195 | else |
1287 | usb_fill_bulk_urb(snd->urb, usb_dev, | 1196 | usb_fill_bulk_urb(snd->urb, usb_dev, |
@@ -1346,8 +1255,9 @@ skip_countries: | |||
1346 | usb_set_intfdata(data_interface, acm); | 1255 | usb_set_intfdata(data_interface, acm); |
1347 | 1256 | ||
1348 | usb_get_intf(control_interface); | 1257 | usb_get_intf(control_interface); |
1349 | tty_port_register_device(&acm->port, acm_tty_driver, minor, | 1258 | tty_register_device(acm_tty_driver, minor, &control_interface->dev); |
1350 | &control_interface->dev); | 1259 | |
1260 | acm_table[minor] = acm; | ||
1351 | 1261 | ||
1352 | return 0; | 1262 | return 0; |
1353 | alloc_fail7: | 1263 | alloc_fail7: |
@@ -1363,7 +1273,6 @@ alloc_fail5: | |||
1363 | alloc_fail4: | 1273 | alloc_fail4: |
1364 | usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1274 | usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
1365 | alloc_fail2: | 1275 | alloc_fail2: |
1366 | acm_release_minor(acm); | ||
1367 | kfree(acm); | 1276 | kfree(acm); |
1368 | alloc_fail: | 1277 | alloc_fail: |
1369 | return -ENOMEM; | 1278 | return -ENOMEM; |
@@ -1373,6 +1282,11 @@ static void stop_data_traffic(struct acm *acm) | |||
1373 | { | 1282 | { |
1374 | int i; | 1283 | int i; |
1375 | 1284 | ||
1285 | if (!acm) { | ||
1286 | pr_err("%s: !acm\n", __func__); | ||
1287 | return; | ||
1288 | } | ||
1289 | |||
1376 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 1290 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
1377 | 1291 | ||
1378 | usb_kill_urb(acm->ctrlurb); | 1292 | usb_kill_urb(acm->ctrlurb); |
@@ -1389,16 +1303,12 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1389 | struct acm *acm = usb_get_intfdata(intf); | 1303 | struct acm *acm = usb_get_intfdata(intf); |
1390 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 1304 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
1391 | struct tty_struct *tty; | 1305 | struct tty_struct *tty; |
1392 | int i; | ||
1393 | |||
1394 | dev_dbg(&intf->dev, "%s\n", __func__); | ||
1395 | 1306 | ||
1396 | /* sibling interface is already cleaning up */ | 1307 | /* sibling interface is already cleaning up */ |
1397 | if (!acm) | 1308 | if (!acm) |
1398 | return; | 1309 | return; |
1399 | 1310 | ||
1400 | mutex_lock(&acm->mutex); | 1311 | mutex_lock(&open_mutex); |
1401 | acm->disconnected = true; | ||
1402 | if (acm->country_codes) { | 1312 | if (acm->country_codes) { |
1403 | device_remove_file(&acm->control->dev, | 1313 | device_remove_file(&acm->control->dev, |
1404 | &dev_attr_wCountryCodes); | 1314 | &dev_attr_wCountryCodes); |
@@ -1406,32 +1316,34 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1406 | &dev_attr_iCountryCodeRelDate); | 1316 | &dev_attr_iCountryCodeRelDate); |
1407 | } | 1317 | } |
1408 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); | 1318 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); |
1319 | acm->dev = NULL; | ||
1409 | usb_set_intfdata(acm->control, NULL); | 1320 | usb_set_intfdata(acm->control, NULL); |
1410 | usb_set_intfdata(acm->data, NULL); | 1321 | usb_set_intfdata(acm->data, NULL); |
1411 | mutex_unlock(&acm->mutex); | ||
1412 | |||
1413 | tty = tty_port_tty_get(&acm->port); | ||
1414 | if (tty) { | ||
1415 | tty_vhangup(tty); | ||
1416 | tty_kref_put(tty); | ||
1417 | } | ||
1418 | 1322 | ||
1419 | stop_data_traffic(acm); | 1323 | stop_data_traffic(acm); |
1420 | 1324 | ||
1421 | usb_free_urb(acm->ctrlurb); | 1325 | usb_kill_anchored_urbs(&acm->deferred); |
1422 | for (i = 0; i < ACM_NW; i++) | ||
1423 | usb_free_urb(acm->wb[i].urb); | ||
1424 | for (i = 0; i < acm->rx_buflimit; i++) | ||
1425 | usb_free_urb(acm->read_urbs[i]); | ||
1426 | acm_write_buffers_free(acm); | 1326 | acm_write_buffers_free(acm); |
1427 | usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1327 | usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, |
1328 | acm->ctrl_dma); | ||
1428 | acm_read_buffers_free(acm); | 1329 | acm_read_buffers_free(acm); |
1429 | 1330 | ||
1430 | if (!acm->combined_interfaces) | 1331 | if (!acm->combined_interfaces) |
1431 | usb_driver_release_interface(&acm_driver, intf == acm->control ? | 1332 | usb_driver_release_interface(&acm_driver, intf == acm->control ? |
1432 | acm->data : acm->control); | 1333 | acm->data : acm->control); |
1433 | 1334 | ||
1434 | tty_port_put(&acm->port); | 1335 | if (acm->port.count == 0) { |
1336 | acm_tty_unregister(acm); | ||
1337 | mutex_unlock(&open_mutex); | ||
1338 | return; | ||
1339 | } | ||
1340 | |||
1341 | mutex_unlock(&open_mutex); | ||
1342 | tty = tty_port_tty_get(&acm->port); | ||
1343 | if (tty) { | ||
1344 | tty_hangup(tty); | ||
1345 | tty_kref_put(tty); | ||
1346 | } | ||
1435 | } | 1347 | } |
1436 | 1348 | ||
1437 | #ifdef CONFIG_PM | 1349 | #ifdef CONFIG_PM |
@@ -1440,7 +1352,12 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1440 | struct acm *acm = usb_get_intfdata(intf); | 1352 | struct acm *acm = usb_get_intfdata(intf); |
1441 | int cnt; | 1353 | int cnt; |
1442 | 1354 | ||
1443 | if (PMSG_IS_AUTO(message)) { | 1355 | if (!acm) { |
1356 | pr_err("%s: !acm\n", __func__); | ||
1357 | return -ENODEV; | ||
1358 | } | ||
1359 | |||
1360 | if (message.event & PM_EVENT_AUTO) { | ||
1444 | int b; | 1361 | int b; |
1445 | 1362 | ||
1446 | spin_lock_irq(&acm->write_lock); | 1363 | spin_lock_irq(&acm->write_lock); |
@@ -1458,32 +1375,66 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1458 | 1375 | ||
1459 | if (cnt) | 1376 | if (cnt) |
1460 | return 0; | 1377 | return 0; |
1378 | /* | ||
1379 | we treat opened interfaces differently, | ||
1380 | we must guard against open | ||
1381 | */ | ||
1382 | mutex_lock(&acm->mutex); | ||
1461 | 1383 | ||
1462 | if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) | 1384 | if (acm->port.count) |
1463 | stop_data_traffic(acm); | 1385 | stop_data_traffic(acm); |
1464 | 1386 | ||
1387 | mutex_unlock(&acm->mutex); | ||
1465 | return 0; | 1388 | return 0; |
1466 | } | 1389 | } |
1467 | 1390 | ||
1468 | static int acm_resume(struct usb_interface *intf) | 1391 | static int acm_resume(struct usb_interface *intf) |
1469 | { | 1392 | { |
1470 | struct acm *acm = usb_get_intfdata(intf); | 1393 | struct acm *acm = usb_get_intfdata(intf); |
1471 | struct acm_wb *wb; | ||
1472 | int rv = 0; | 1394 | int rv = 0; |
1473 | int cnt; | 1395 | int cnt; |
1396 | #ifdef CONFIG_PM | ||
1397 | struct urb *res; | ||
1398 | #else | ||
1399 | struct acm_wb *wb; | ||
1400 | #endif | ||
1401 | |||
1402 | if (!acm) { | ||
1403 | pr_err("%s: !acm\n", __func__); | ||
1404 | return -ENODEV; | ||
1405 | } | ||
1474 | 1406 | ||
1475 | spin_lock_irq(&acm->read_lock); | 1407 | spin_lock_irq(&acm->read_lock); |
1476 | acm->susp_count -= 1; | 1408 | if (acm->susp_count > 0) { |
1477 | cnt = acm->susp_count; | 1409 | acm->susp_count -= 1; |
1410 | cnt = acm->susp_count; | ||
1411 | } else { | ||
1412 | spin_unlock_irq(&acm->read_lock); | ||
1413 | return 0; | ||
1414 | } | ||
1478 | spin_unlock_irq(&acm->read_lock); | 1415 | spin_unlock_irq(&acm->read_lock); |
1479 | 1416 | ||
1480 | if (cnt) | 1417 | if (cnt) |
1481 | return 0; | 1418 | return 0; |
1482 | 1419 | ||
1483 | if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { | ||
1484 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); | ||
1485 | 1420 | ||
1421 | mutex_lock(&acm->mutex); | ||
1422 | |||
1423 | if (acm->port.count) { | ||
1424 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); | ||
1486 | spin_lock_irq(&acm->write_lock); | 1425 | spin_lock_irq(&acm->write_lock); |
1426 | #ifdef CONFIG_PM | ||
1427 | while ((res = usb_get_from_anchor(&acm->deferred))) { | ||
1428 | rv = usb_submit_urb(res, GFP_ATOMIC); | ||
1429 | if (rv < 0) { | ||
1430 | dbg("usb_submit_urb(pending request)" | ||
1431 | " failed: %d", rv); | ||
1432 | usb_unanchor_urb(res); | ||
1433 | acm_write_done(acm, res->context); | ||
1434 | } | ||
1435 | } | ||
1436 | spin_unlock_irq(&acm->write_lock); | ||
1437 | #else | ||
1487 | if (acm->delayed_wb) { | 1438 | if (acm->delayed_wb) { |
1488 | wb = acm->delayed_wb; | 1439 | wb = acm->delayed_wb; |
1489 | acm->delayed_wb = NULL; | 1440 | acm->delayed_wb = NULL; |
@@ -1492,6 +1443,7 @@ static int acm_resume(struct usb_interface *intf) | |||
1492 | } else { | 1443 | } else { |
1493 | spin_unlock_irq(&acm->write_lock); | 1444 | spin_unlock_irq(&acm->write_lock); |
1494 | } | 1445 | } |
1446 | #endif | ||
1495 | 1447 | ||
1496 | /* | 1448 | /* |
1497 | * delayed error checking because we must | 1449 | * delayed error checking because we must |
@@ -1504,6 +1456,7 @@ static int acm_resume(struct usb_interface *intf) | |||
1504 | } | 1456 | } |
1505 | 1457 | ||
1506 | err_out: | 1458 | err_out: |
1459 | mutex_unlock(&acm->mutex); | ||
1507 | return rv; | 1460 | return rv; |
1508 | } | 1461 | } |
1509 | 1462 | ||
@@ -1512,14 +1465,21 @@ static int acm_reset_resume(struct usb_interface *intf) | |||
1512 | struct acm *acm = usb_get_intfdata(intf); | 1465 | struct acm *acm = usb_get_intfdata(intf); |
1513 | struct tty_struct *tty; | 1466 | struct tty_struct *tty; |
1514 | 1467 | ||
1515 | if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { | 1468 | if (!acm) { |
1469 | pr_err("%s: !acm\n", __func__); | ||
1470 | return -ENODEV; | ||
1471 | } | ||
1472 | |||
1473 | mutex_lock(&acm->mutex); | ||
1474 | if (acm->port.count) { | ||
1516 | tty = tty_port_tty_get(&acm->port); | 1475 | tty = tty_port_tty_get(&acm->port); |
1517 | if (tty) { | 1476 | if (tty) { |
1518 | tty_hangup(tty); | 1477 | if (!acm->no_hangup_in_reset_resume) |
1478 | tty_hangup(tty); | ||
1519 | tty_kref_put(tty); | 1479 | tty_kref_put(tty); |
1520 | } | 1480 | } |
1521 | } | 1481 | } |
1522 | 1482 | mutex_unlock(&acm->mutex); | |
1523 | return acm_resume(intf); | 1483 | return acm_resume(intf); |
1524 | } | 1484 | } |
1525 | 1485 | ||
@@ -1599,18 +1559,15 @@ static const struct usb_device_id acm_ids[] = { | |||
1599 | Maybe we should define a new | 1559 | Maybe we should define a new |
1600 | quirk for this. */ | 1560 | quirk for this. */ |
1601 | }, | 1561 | }, |
1602 | { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ | ||
1603 | .driver_info = NO_UNION_NORMAL, | ||
1604 | }, | ||
1605 | { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ | ||
1606 | .driver_info = NO_UNION_NORMAL, | ||
1607 | }, | ||
1608 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1562 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1609 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1563 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1610 | }, | 1564 | }, |
1611 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ | 1565 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ |
1612 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1566 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1613 | }, | 1567 | }, |
1568 | { USB_DEVICE(0x1519, 0x0020), | ||
1569 | .driver_info = NO_UNION_NORMAL | NO_HANGUP_IN_RESET_RESUME, /* has no union descriptor */ | ||
1570 | }, | ||
1614 | 1571 | ||
1615 | /* Nokia S60 phones expose two ACM channels. The first is | 1572 | /* Nokia S60 phones expose two ACM channels. The first is |
1616 | * a modem and is picked up by the standard AT-command | 1573 | * a modem and is picked up by the standard AT-command |
@@ -1691,6 +1648,16 @@ static const struct usb_device_id acm_ids[] = { | |||
1691 | .driver_info = NO_DATA_INTERFACE, | 1648 | .driver_info = NO_DATA_INTERFACE, |
1692 | }, | 1649 | }, |
1693 | 1650 | ||
1651 | /* Exclude XMM6260 boot rom (not running modem software yet) */ | ||
1652 | { USB_DEVICE(0x058b, 0x0041), | ||
1653 | .driver_info = NOT_REAL_ACM, | ||
1654 | }, | ||
1655 | |||
1656 | /* Icera 450 */ | ||
1657 | { USB_DEVICE(0x1983, 0x0321), | ||
1658 | .driver_info = NO_HANGUP_IN_RESET_RESUME, | ||
1659 | }, | ||
1660 | |||
1694 | /* control interfaces without any protocol set */ | 1661 | /* control interfaces without any protocol set */ |
1695 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1662 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1696 | USB_CDC_PROTO_NONE) }, | 1663 | USB_CDC_PROTO_NONE) }, |
@@ -1727,7 +1694,6 @@ static struct usb_driver acm_driver = { | |||
1727 | #ifdef CONFIG_PM | 1694 | #ifdef CONFIG_PM |
1728 | .supports_autosuspend = 1, | 1695 | .supports_autosuspend = 1, |
1729 | #endif | 1696 | #endif |
1730 | .disable_hub_initiated_lpm = 1, | ||
1731 | }; | 1697 | }; |
1732 | 1698 | ||
1733 | /* | 1699 | /* |
@@ -1735,10 +1701,8 @@ static struct usb_driver acm_driver = { | |||
1735 | */ | 1701 | */ |
1736 | 1702 | ||
1737 | static const struct tty_operations acm_ops = { | 1703 | static const struct tty_operations acm_ops = { |
1738 | .install = acm_tty_install, | ||
1739 | .open = acm_tty_open, | 1704 | .open = acm_tty_open, |
1740 | .close = acm_tty_close, | 1705 | .close = acm_tty_close, |
1741 | .cleanup = acm_tty_cleanup, | ||
1742 | .hangup = acm_tty_hangup, | 1706 | .hangup = acm_tty_hangup, |
1743 | .write = acm_tty_write, | 1707 | .write = acm_tty_write, |
1744 | .write_room = acm_tty_write_room, | 1708 | .write_room = acm_tty_write_room, |
@@ -1762,6 +1726,7 @@ static int __init acm_init(void) | |||
1762 | acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS); | 1726 | acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS); |
1763 | if (!acm_tty_driver) | 1727 | if (!acm_tty_driver) |
1764 | return -ENOMEM; | 1728 | return -ENOMEM; |
1729 | acm_tty_driver->owner = THIS_MODULE, | ||
1765 | acm_tty_driver->driver_name = "acm", | 1730 | acm_tty_driver->driver_name = "acm", |
1766 | acm_tty_driver->name = "ttyACM", | 1731 | acm_tty_driver->name = "ttyACM", |
1767 | acm_tty_driver->major = ACM_TTY_MAJOR, | 1732 | acm_tty_driver->major = ACM_TTY_MAJOR, |