aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-08 13:03:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-08 13:03:52 -0400
commit132d68d37d33f1d0b9c1f507c8b4d64c27ecec8a (patch)
treeb3c05972e5579e1574873fe745fb1358c62a269c /drivers/usb/class/cdc-acm.c
parent80f232121b69cc69a31ccb2b38c1665d770b0710 (diff)
parent3515468a87a47781f6af818773650513ff14656a (diff)
Merge tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH: "Here is the big set of USB and PHY driver patches for 5.2-rc1 There is the usual set of: - USB gadget updates - PHY driver updates and additions - USB serial driver updates and fixes - typec updates and new chips supported - mtu3 driver updates - xhci driver updates - other tiny driver updates Nothing really interesting, just constant forward progress. All of these have been in linux-next for a while with no reported issues. The usb-gadget and usb-serial trees were merged a bit "late", but both of them had been in linux-next before they got merged here last Friday" * tag 'usb-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (206 commits) USB: serial: f81232: implement break control USB: serial: f81232: add high baud rate support USB: serial: f81232: clear overrun flag USB: serial: f81232: fix interrupt worker not stop usb: dwc3: Rename DWC3_DCTL_LPM_ERRATA usb: dwc3: Fix default lpm_nyet_threshold value usb: dwc3: debug: Print GET_STATUS(device) tracepoint usb: dwc3: Do core validation early on probe usb: dwc3: gadget: Set lpm_capable usb: gadget: atmel: tie wake lock to running clock usb: gadget: atmel: support USB suspend usb: gadget: atmel_usba_udc: simplify setting of interrupt-enabled mask dwc2: gadget: Fix completed transfer size calculation in DDMA usb: dwc2: Set lpm mode parameters depend on HW configuration usb: dwc2: Fix channel disable flow usb: dwc2: Set actual frame number for completed ISOC transfer usb: gadget: do not use __constant_cpu_to_le16 usb: dwc2: gadget: Increase descriptors count for ISOC's usb: introduce usb_ep_type_string() function usb: dwc3: move synchronize_irq() out of the spinlock protected block ...
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)