Commit a8d78d9f authored by Johan Hovold's avatar Johan Hovold
Browse files

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
Loading
Loading
Loading
Loading
+8 −26
Original line number Diff line number Diff line
@@ -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);
	if (test_bit(USB_SERIAL_THROTTLED, &port->flags))
		return;

	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);

@@ -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,7 +492,6 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
	 */
	smp_mb();

	if (was_throttled)
	usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
+1 −4
Original line number Diff line number Diff line
@@ -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;
};