Skip to content

Commit

Permalink
USB: cdc-acm: clean up throttle handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johan Hovold authored and Greg Kroah-Hartman committed Apr 29, 2019
1 parent 764478f commit 0f02321
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 27 deletions.
33 changes: 8 additions & 25 deletions drivers/usb/class/cdc-acm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions drivers/usb/class/cdc-acm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
Expand All @@ -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;
Expand Down

0 comments on commit 0f02321

Please sign in to comment.