USB: cdc-acm: clean up throttle handling
authorJohan Hovold <johan@kernel.org>
Thu, 25 Apr 2019 16:05:40 +0000 (18:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 29 Apr 2019 14:14:41 +0000 (16:14 +0200)
Clean up the throttle implementation by dropping the redundant
throttle_req flag which was a remnant from back when USB serial had only
a single read URB, something which was later carried over to cdc-acm.

Also convert the throttled flag to an atomic bit flag.

Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h

index c03aa8550980d4249e299d7c3cff9c5743ddc778..183b41753c98298236ea0690cd119e231d1ae5f3 100644 (file)
@@ -468,7 +468,6 @@ static void acm_read_bulk_callback(struct urb *urb)
 {
        struct acm_rb *rb = urb->context;
        struct acm *acm = rb->instance;
-       unsigned long flags;
        int status = urb->status;
        bool stopped = false;
        bool stalled = false;
@@ -525,15 +524,10 @@ static void acm_read_bulk_callback(struct urb *urb)
                return;
        }
 
-       /* throttle device if requested by tty */
-       spin_lock_irqsave(&acm->read_lock, flags);
-       acm->throttled = acm->throttle_req;
-       if (!acm->throttled) {
-               spin_unlock_irqrestore(&acm->read_lock, flags);
-               acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
-       } else {
-               spin_unlock_irqrestore(&acm->read_lock, flags);
-       }
+       if (test_bit(ACM_THROTTLED, &acm->flags))
+               return;
+
+       acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
 }
 
 /* data interface wrote those outgoing bytes */
@@ -670,10 +664,7 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
        /*
         * Unthrottle device in case the TTY was closed while throttled.
         */
-       spin_lock_irq(&acm->read_lock);
-       acm->throttled = 0;
-       acm->throttle_req = 0;
-       spin_unlock_irq(&acm->read_lock);
+       clear_bit(ACM_THROTTLED, &acm->flags);
 
        retval = acm_submit_read_urbs(acm, GFP_KERNEL);
        if (retval)
@@ -841,27 +832,19 @@ static void acm_tty_throttle(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
 
-       spin_lock_irq(&acm->read_lock);
-       acm->throttle_req = 1;
-       spin_unlock_irq(&acm->read_lock);
+       set_bit(ACM_THROTTLED, &acm->flags);
 }
 
 static void acm_tty_unthrottle(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
-       unsigned int was_throttled;
 
-       spin_lock_irq(&acm->read_lock);
-       was_throttled = acm->throttled;
-       acm->throttled = 0;
-       acm->throttle_req = 0;
-       spin_unlock_irq(&acm->read_lock);
+       clear_bit(ACM_THROTTLED, &acm->flags);
 
        /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */
        smp_mb();
 
-       if (was_throttled)
-               acm_submit_read_urbs(acm, GFP_KERNEL);
+       acm_submit_read_urbs(acm, GFP_KERNEL);
 }
 
 static int acm_tty_break_ctl(struct tty_struct *tty, int state)
index 515aad0847ee84b408e7fceb503081f5d97fc78b..ca1c026382c2e1a98a330cde2043dee308d76aad 100644 (file)
@@ -108,6 +108,7 @@ struct acm {
        unsigned long flags;
 #              define EVENT_TTY_WAKEUP 0
 #              define EVENT_RX_STALL   1
+#              define ACM_THROTTLED    2
        struct usb_cdc_line_coding line;                /* bits, stop, parity */
        struct work_struct work;                        /* work queue entry for line discipline waking up */
        unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
@@ -122,8 +123,6 @@ struct acm {
        unsigned int ctrl_caps;                         /* control capabilities from the class specific header */
        unsigned int susp_count;                        /* number of suspended interfaces */
        unsigned int combined_interfaces:1;             /* control and data collapsed */
-       unsigned int throttled:1;                       /* actually throttled */
-       unsigned int throttle_req:1;                    /* throttle requested */
        u8 bInterval;
        struct usb_anchor delayed;                      /* writes queued for a device about to be woken */
        unsigned long quirks;