USB: serial: clean up throttle handling
authorJohan Hovold <johan@kernel.org>
Thu, 25 Apr 2019 16:05:37 +0000 (18:05 +0200)
committerJohan Hovold <johan@kernel.org>
Tue, 30 Apr 2019 08:23:29 +0000 (10:23 +0200)
Clean up the throttle implementation by dropping the redundant
throttle_req flag which was a remnant from back when there was only a
single read URB.

Also convert the throttled flag to an atomic bit flag.

Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/generic.c
include/linux/usb/serial.h

index 0fff496..67cef3e 100644 (file)
@@ -106,12 +106,8 @@ void usb_serial_generic_deregister(void)
 int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        int result = 0;
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
-       port->throttled = 0;
-       port->throttle_req = 0;
-       spin_unlock_irqrestore(&port->lock, flags);
+       clear_bit(USB_SERIAL_THROTTLED, &port->flags);
 
        if (port->bulk_in_size)
                result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
@@ -375,7 +371,6 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
        unsigned char *data = urb->transfer_buffer;
-       unsigned long flags;
        bool stopped = false;
        int status = urb->status;
        int i;
@@ -429,15 +424,10 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
        if (stopped)
                return;
 
-       /* Throttle the device if requested by tty */
-       spin_lock_irqsave(&port->lock, flags);
-       port->throttled = port->throttle_req;
-       if (!port->throttled) {
-               spin_unlock_irqrestore(&port->lock, flags);
-               usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
-       } else {
-               spin_unlock_irqrestore(&port->lock, flags);
-       }
+       if (test_bit(USB_SERIAL_THROTTLED, &port->flags))
+               return;
+
+       usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
@@ -485,23 +475,16 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 void usb_serial_generic_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       unsigned long flags;
 
-       spin_lock_irqsave(&port->lock, flags);
-       port->throttle_req = 1;
-       spin_unlock_irqrestore(&port->lock, flags);
+       set_bit(USB_SERIAL_THROTTLED, &port->flags);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_throttle);
 
 void usb_serial_generic_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       int was_throttled;
 
-       spin_lock_irq(&port->lock);
-       was_throttled = port->throttled;
-       port->throttled = port->throttle_req = 0;
-       spin_unlock_irq(&port->lock);
+       clear_bit(USB_SERIAL_THROTTLED, &port->flags);
 
        /*
         * Matches the smp_mb__after_atomic() in
@@ -509,8 +492,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
         */
        smp_mb();
 
-       if (was_throttled)
-               usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
+       usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
 
index 1c19f77..d8bdab8 100644 (file)
@@ -28,6 +28,7 @@
 
 /* USB serial flags */
 #define USB_SERIAL_WRITE_BUSY  0
+#define USB_SERIAL_THROTTLED   1
 
 /**
  * usb_serial_port: structure for the specific ports of a device.
@@ -67,8 +68,6 @@
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
  * @work: work queue entry for the line discipline waking up.
- * @throttled: nonzero if the read urb is inactive to throttle the device
- * @throttle_req: nonzero if the tty wants to throttle us
  * @dev: pointer to the serial device
  *
  * This structure is used by the usb-serial core and drivers for the specific
@@ -115,8 +114,6 @@ struct usb_serial_port {
        unsigned long           flags;
        wait_queue_head_t       write_wait;
        struct work_struct      work;
-       char                    throttled;
-       char                    throttle_req;
        unsigned long           sysrq; /* sysrq timeout */
        struct device           dev;
 };