Commit a8d78d9f authored by Johan Hovold's avatar Johan Hovold

USB: serial: clean up throttle handling

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: default avatarJohan Hovold <johan@kernel.org>
parent 3f5edd58
...@@ -106,12 +106,8 @@ void usb_serial_generic_deregister(void) ...@@ -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 usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port)
{ {
int result = 0; int result = 0;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags); clear_bit(USB_SERIAL_THROTTLED, &port->flags);
port->throttled = 0;
port->throttle_req = 0;
spin_unlock_irqrestore(&port->lock, flags);
if (port->bulk_in_size) if (port->bulk_in_size)
result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
...@@ -375,7 +371,6 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) ...@@ -375,7 +371,6 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer; unsigned char *data = urb->transfer_buffer;
unsigned long flags;
bool stopped = false; bool stopped = false;
int status = urb->status; int status = urb->status;
int i; int i;
...@@ -429,15 +424,10 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) ...@@ -429,15 +424,10 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
if (stopped) if (stopped)
return; return;
/* Throttle the device if requested by tty */ if (test_bit(USB_SERIAL_THROTTLED, &port->flags))
spin_lock_irqsave(&port->lock, flags); return;
port->throttled = port->throttle_req;
if (!port->throttled) { usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
spin_unlock_irqrestore(&port->lock, flags);
usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC);
} else {
spin_unlock_irqrestore(&port->lock, flags);
}
} }
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
...@@ -485,23 +475,16 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); ...@@ -485,23 +475,16 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
void usb_serial_generic_throttle(struct tty_struct *tty) void usb_serial_generic_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags); set_bit(USB_SERIAL_THROTTLED, &port->flags);
port->throttle_req = 1;
spin_unlock_irqrestore(&port->lock, flags);
} }
EXPORT_SYMBOL_GPL(usb_serial_generic_throttle); EXPORT_SYMBOL_GPL(usb_serial_generic_throttle);
void usb_serial_generic_unthrottle(struct tty_struct *tty) void usb_serial_generic_unthrottle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
int was_throttled;
spin_lock_irq(&port->lock); clear_bit(USB_SERIAL_THROTTLED, &port->flags);
was_throttled = port->throttled;
port->throttled = port->throttle_req = 0;
spin_unlock_irq(&port->lock);
/* /*
* Matches the smp_mb__after_atomic() in * Matches the smp_mb__after_atomic() in
...@@ -509,8 +492,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) ...@@ -509,8 +492,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
*/ */
smp_mb(); 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); EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
/* USB serial flags */ /* USB serial flags */
#define USB_SERIAL_WRITE_BUSY 0 #define USB_SERIAL_WRITE_BUSY 0
#define USB_SERIAL_THROTTLED 1
/** /**
* usb_serial_port: structure for the specific ports of a device. * usb_serial_port: structure for the specific ports of a device.
...@@ -67,8 +68,6 @@ ...@@ -67,8 +68,6 @@
* @flags: usb serial port flags * @flags: usb serial port flags
* @write_wait: a wait_queue_head_t used by the port. * @write_wait: a wait_queue_head_t used by the port.
* @work: work queue entry for the line discipline waking up. * @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 * @dev: pointer to the serial device
* *
* This structure is used by the usb-serial core and drivers for the specific * This structure is used by the usb-serial core and drivers for the specific
...@@ -115,8 +114,6 @@ struct usb_serial_port { ...@@ -115,8 +114,6 @@ struct usb_serial_port {
unsigned long flags; unsigned long flags;
wait_queue_head_t write_wait; wait_queue_head_t write_wait;
struct work_struct work; struct work_struct work;
char throttled;
char throttle_req;
unsigned long sysrq; /* sysrq timeout */ unsigned long sysrq; /* sysrq timeout */
struct device dev; struct device dev;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment