Commit 0f02321e authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

USB: cdc-acm: clean up throttle handling

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: default avatarJohan Hovold <johan@kernel.org>
Acked-by: default avatarOliver Neukum <oneukum@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 764478f4
...@@ -468,7 +468,6 @@ static void acm_read_bulk_callback(struct urb *urb) ...@@ -468,7 +468,6 @@ static void acm_read_bulk_callback(struct urb *urb)
{ {
struct acm_rb *rb = urb->context; struct acm_rb *rb = urb->context;
struct acm *acm = rb->instance; struct acm *acm = rb->instance;
unsigned long flags;
int status = urb->status; int status = urb->status;
bool stopped = false; bool stopped = false;
bool stalled = false; bool stalled = false;
...@@ -525,15 +524,10 @@ static void acm_read_bulk_callback(struct urb *urb) ...@@ -525,15 +524,10 @@ static void acm_read_bulk_callback(struct urb *urb)
return; return;
} }
/* throttle device if requested by tty */ if (test_bit(ACM_THROTTLED, &acm->flags))
spin_lock_irqsave(&acm->read_lock, flags); return;
acm->throttled = acm->throttle_req;
if (!acm->throttled) {
spin_unlock_irqrestore(&acm->read_lock, flags);
acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
} else {
spin_unlock_irqrestore(&acm->read_lock, flags);
}
} }
/* data interface wrote those outgoing bytes */ /* data interface wrote those outgoing bytes */
...@@ -670,10 +664,7 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) ...@@ -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. * Unthrottle device in case the TTY was closed while throttled.
*/ */
spin_lock_irq(&acm->read_lock); clear_bit(ACM_THROTTLED, &acm->flags);
acm->throttled = 0;
acm->throttle_req = 0;
spin_unlock_irq(&acm->read_lock);
retval = acm_submit_read_urbs(acm, GFP_KERNEL); retval = acm_submit_read_urbs(acm, GFP_KERNEL);
if (retval) if (retval)
...@@ -841,26 +832,18 @@ static void acm_tty_throttle(struct tty_struct *tty) ...@@ -841,26 +832,18 @@ static void acm_tty_throttle(struct tty_struct *tty)
{ {
struct acm *acm = tty->driver_data; struct acm *acm = tty->driver_data;
spin_lock_irq(&acm->read_lock); set_bit(ACM_THROTTLED, &acm->flags);
acm->throttle_req = 1;
spin_unlock_irq(&acm->read_lock);
} }
static void acm_tty_unthrottle(struct tty_struct *tty) static void acm_tty_unthrottle(struct tty_struct *tty)
{ {
struct acm *acm = tty->driver_data; struct acm *acm = tty->driver_data;
unsigned int was_throttled;
spin_lock_irq(&acm->read_lock); clear_bit(ACM_THROTTLED, &acm->flags);
was_throttled = acm->throttled;
acm->throttled = 0;
acm->throttle_req = 0;
spin_unlock_irq(&acm->read_lock);
/* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */ /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */
smp_mb(); smp_mb();
if (was_throttled)
acm_submit_read_urbs(acm, GFP_KERNEL); acm_submit_read_urbs(acm, GFP_KERNEL);
} }
......
...@@ -108,6 +108,7 @@ struct acm { ...@@ -108,6 +108,7 @@ struct acm {
unsigned long flags; unsigned long flags;
# define EVENT_TTY_WAKEUP 0 # define EVENT_TTY_WAKEUP 0
# define EVENT_RX_STALL 1 # define EVENT_RX_STALL 1
# define ACM_THROTTLED 2
struct usb_cdc_line_coding line; /* bits, stop, parity */ struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */ struct work_struct work; /* work queue entry for line discipline waking up */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
...@@ -122,8 +123,6 @@ struct acm { ...@@ -122,8 +123,6 @@ struct acm {
unsigned int ctrl_caps; /* control capabilities from the class specific header */ unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */ unsigned int susp_count; /* number of suspended interfaces */
unsigned int combined_interfaces:1; /* control and data collapsed */ unsigned int combined_interfaces:1; /* control and data collapsed */
unsigned int throttled:1; /* actually throttled */
unsigned int throttle_req:1; /* throttle requested */
u8 bInterval; u8 bInterval;
struct usb_anchor delayed; /* writes queued for a device about to be woken */ struct usb_anchor delayed; /* writes queued for a device about to be woken */
unsigned long quirks; unsigned long quirks;
......
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