aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index ec666eb4b7b4..183b41753c98 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -468,14 +468,13 @@ static void acm_read_bulk_callback(struct urb *urb)
468{ 468{
469 struct acm_rb *rb = urb->context; 469 struct acm_rb *rb = urb->context;
470 struct acm *acm = rb->instance; 470 struct acm *acm = rb->instance;
471 unsigned long flags;
472 int status = urb->status; 471 int status = urb->status;
472 bool stopped = false;
473 bool stalled = false;
473 474
474 dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", 475 dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n",
475 rb->index, urb->actual_length, status); 476 rb->index, urb->actual_length, status);
476 477
477 set_bit(rb->index, &acm->read_urbs_free);
478
479 if (!acm->dev) { 478 if (!acm->dev) {
480 dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); 479 dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
481 return; 480 return;
@@ -488,15 +487,16 @@ static void acm_read_bulk_callback(struct urb *urb)
488 break; 487 break;
489 case -EPIPE: 488 case -EPIPE:
490 set_bit(EVENT_RX_STALL, &acm->flags); 489 set_bit(EVENT_RX_STALL, &acm->flags);
491 schedule_work(&acm->work); 490 stalled = true;
492 return; 491 break;
493 case -ENOENT: 492 case -ENOENT:
494 case -ECONNRESET: 493 case -ECONNRESET:
495 case -ESHUTDOWN: 494 case -ESHUTDOWN:
496 dev_dbg(&acm->data->dev, 495 dev_dbg(&acm->data->dev,
497 "%s - urb shutting down with status: %d\n", 496 "%s - urb shutting down with status: %d\n",
498 __func__, status); 497 __func__, status);
499 return; 498 stopped = true;
499 break;
500 default: 500 default:
501 dev_dbg(&acm->data->dev, 501 dev_dbg(&acm->data->dev,
502 "%s - nonzero urb status received: %d\n", 502 "%s - nonzero urb status received: %d\n",
@@ -505,20 +505,29 @@ static void acm_read_bulk_callback(struct urb *urb)
505 } 505 }
506 506
507 /* 507 /*
508 * Unthrottle may run on another CPU which needs to see events 508 * Make sure URB processing is done before marking as free to avoid
509 * in the same order. Submission has an implict barrier 509 * racing with unthrottle() on another CPU. Matches the barriers
510 * implied by the test_and_clear_bit() in acm_submit_read_urb().
510 */ 511 */
511 smp_mb__before_atomic(); 512 smp_mb__before_atomic();
513 set_bit(rb->index, &acm->read_urbs_free);
514 /*
515 * Make sure URB is marked as free before checking the throttled flag
516 * to avoid racing with unthrottle() on another CPU. Matches the
517 * smp_mb() in unthrottle().
518 */
519 smp_mb__after_atomic();
512 520
513 /* throttle device if requested by tty */ 521 if (stopped || stalled) {
514 spin_lock_irqsave(&acm->read_lock, flags); 522 if (stalled)
515 acm->throttled = acm->throttle_req; 523 schedule_work(&acm->work);
516 if (!acm->throttled) { 524 return;
517 spin_unlock_irqrestore(&acm->read_lock, flags);
518 acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
519 } else {
520 spin_unlock_irqrestore(&acm->read_lock, flags);
521 } 525 }
526
527 if (test_bit(ACM_THROTTLED, &acm->flags))
528 return;
529
530 acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
522} 531}
523 532
524/* data interface wrote those outgoing bytes */ 533/* data interface wrote those outgoing bytes */
@@ -655,10 +664,7 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
655 /* 664 /*
656 * Unthrottle device in case the TTY was closed while throttled. 665 * Unthrottle device in case the TTY was closed while throttled.
657 */ 666 */
658 spin_lock_irq(&acm->read_lock); 667 clear_bit(ACM_THROTTLED, &acm->flags);
659 acm->throttled = 0;
660 acm->throttle_req = 0;
661 spin_unlock_irq(&acm->read_lock);
662 668
663 retval = acm_submit_read_urbs(acm, GFP_KERNEL); 669 retval = acm_submit_read_urbs(acm, GFP_KERNEL);
664 if (retval) 670 if (retval)
@@ -826,24 +832,19 @@ static void acm_tty_throttle(struct tty_struct *tty)
826{ 832{
827 struct acm *acm = tty->driver_data; 833 struct acm *acm = tty->driver_data;
828 834
829 spin_lock_irq(&acm->read_lock); 835 set_bit(ACM_THROTTLED, &acm->flags);
830 acm->throttle_req = 1;
831 spin_unlock_irq(&acm->read_lock);
832} 836}
833 837
834static void acm_tty_unthrottle(struct tty_struct *tty) 838static void acm_tty_unthrottle(struct tty_struct *tty)
835{ 839{
836 struct acm *acm = tty->driver_data; 840 struct acm *acm = tty->driver_data;
837 unsigned int was_throttled;
838 841
839 spin_lock_irq(&acm->read_lock); 842 clear_bit(ACM_THROTTLED, &acm->flags);
840 was_throttled = acm->throttled; 843
841 acm->throttled = 0; 844 /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */
842 acm->throttle_req = 0; 845 smp_mb();
843 spin_unlock_irq(&acm->read_lock);
844 846
845 if (was_throttled) 847 acm_submit_read_urbs(acm, GFP_KERNEL);
846 acm_submit_read_urbs(acm, GFP_KERNEL);
847} 848}
848 849
849static int acm_tty_break_ctl(struct tty_struct *tty, int state) 850static int acm_tty_break_ctl(struct tty_struct *tty, int state)