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

Commit 63832515 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman
Browse files

USB: serial: fix assumption that throttle/unthrottle cannot sleep



many serial subdrivers are clearly written as if throttle/unthrottle
cannot sleep. This leads to unneeded atomic submissions. This
patch converts affected drivers in a way to makes very clear that
throttle/unthrottle can sleep. Thus future misdesigns can be avoided
and efficiency and reliability improved.

This removes any such assumption using GFP_KERNEL and spin_lock_irq()

Signed-off-by: default avatarOliver Neukum <oliver@neukum.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b2a5cf1b
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -554,13 +554,12 @@ static void aircable_throttle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct aircable_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);

	spin_lock_irqsave(&priv->rx_lock, flags);
	spin_lock_irq(&priv->rx_lock);
	priv->rx_flags |= THROTTLED;
	spin_unlock_irqrestore(&priv->rx_lock, flags);
	spin_unlock_irq(&priv->rx_lock);
}

/* Based on ftdi_sio.c unthrottle */
@@ -569,14 +568,13 @@ static void aircable_unthrottle(struct tty_struct *tty)
	struct usb_serial_port *port = tty->driver_data;
	struct aircable_private *priv = usb_get_serial_port_data(port);
	int actually_throttled;
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);

	spin_lock_irqsave(&priv->rx_lock, flags);
	spin_lock_irq(&priv->rx_lock);
	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
	priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
	spin_unlock_irqrestore(&priv->rx_lock, flags);
	spin_unlock_irq(&priv->rx_lock);

	if (actually_throttled)
		schedule_work(&priv->rx_work);
+5 −7
Original line number Diff line number Diff line
@@ -1155,13 +1155,12 @@ static void cypress_throttle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct cypress_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);

	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irq(&priv->lock);
	priv->rx_flags = THROTTLED;
	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irq(&priv->lock);
}


@@ -1170,14 +1169,13 @@ static void cypress_unthrottle(struct tty_struct *tty)
	struct usb_serial_port *port = tty->driver_data;
	struct cypress_private *priv = usb_get_serial_port_data(port);
	int actually_throttled, result;
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);

	spin_lock_irqsave(&priv->lock, flags);
	spin_lock_irq(&priv->lock);
	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
	priv->rx_flags = 0;
	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irq(&priv->lock);

	if (!priv->comm_is_ok)
		return;
@@ -1185,7 +1183,7 @@ static void cypress_unthrottle(struct tty_struct *tty)
	if (actually_throttled) {
		port->interrupt_in_urb->dev = port->serial->dev;

		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
		if (result) {
			dev_err(&port->dev, "%s - failed submitting read urb, "
					"error %d\n", __func__, result);
+1 −1
Original line number Diff line number Diff line
@@ -391,7 +391,7 @@ static void empeg_unthrottle(struct tty_struct *tty)
	dbg("%s - port %d", __func__, port->number);

	port->read_urb->dev = port->serial->dev;
	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
	if (result)
		dev_err(&port->dev,
			"%s - failed submitting read urb, error %d\n",
+5 −7
Original line number Diff line number Diff line
@@ -1390,14 +1390,13 @@ static void garmin_throttle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);
	/* set flag, data received will be put into a queue
	   for later processing */
	spin_lock_irqsave(&garmin_data_p->lock, flags);
	spin_lock_irq(&garmin_data_p->lock);
	garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
	spin_unlock_irq(&garmin_data_p->lock);
}


@@ -1405,13 +1404,12 @@ static void garmin_unthrottle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
	unsigned long flags;
	int status;

	dbg("%s - port %d", __func__, port->number);
	spin_lock_irqsave(&garmin_data_p->lock, flags);
	spin_lock_irq(&garmin_data_p->lock);
	garmin_data_p->flags &= ~FLAGS_THROTTLED;
	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
	spin_unlock_irq(&garmin_data_p->lock);

	/* in native mode send queued data to tty, in
	   serial mode nothing needs to be done here */
@@ -1419,7 +1417,7 @@ static void garmin_unthrottle(struct tty_struct *tty)
		garmin_flush_queue(garmin_data_p);

	if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
		status = usb_submit_urb(port->read_urb, GFP_KERNEL);
		if (status)
			dev_err(&port->dev,
				"%s - failed resubmitting read urb, error %d\n",
+1 −1
Original line number Diff line number Diff line
@@ -290,7 +290,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
	/* just restart the receive interrupt URB */
	dbg("keyspan_pda_rx_unthrottle port %d", port->number);
	port->interrupt_in_urb->dev = port->serial->dev;
	if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
	if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
		dbg(" usb_submit_urb(read urb) failed");
	return;
}
Loading