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: Johan Hovold <johan@kernel.org>
Acked-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Johan Hovold 2019-04-25 18:05:40 +02:00 committed by Greg Kroah-Hartman
parent 764478f411
commit 0f02321e4b
2 changed files with 9 additions and 27 deletions

View File

@ -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;
@ -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 */
@ -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)
@ -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)

View File

@ -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) */
@ -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;