Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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

	acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
	} else {
		spin_unlock_irqrestore(&acm->read_lock, flags);
	}
}

/* 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,26 +832,18 @@ 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);
}

+1 −2
Original line number Diff line number Diff line
@@ -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;