USB: serial: keyspan_pda: fix write deadlock

The write() callback can be called in interrupt context (e.g. when used
as a console) so interrupts must be disabled while holding the port lock
to prevent a possible deadlock.

Fixes: e81ee637e4 ("usb-serial: possible irq lock inversion (PPP vs. usb/serial)")
Fixes: 507ca9bc04 ("[PATCH] USB: add ability for usb-serial drivers to determine if their write urb is currently being used.")
Cc: stable <stable@vger.kernel.org>     # 2.6.19
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
Johan Hovold 2020-10-25 18:45:48 +01:00
parent 696c541c8c
commit 7353cad7ee

View file

@ -443,6 +443,7 @@ static int keyspan_pda_write(struct tty_struct *tty,
int request_unthrottle = 0; int request_unthrottle = 0;
int rc = 0; int rc = 0;
struct keyspan_pda_private *priv; struct keyspan_pda_private *priv;
unsigned long flags;
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
/* guess how much room is left in the device's ring buffer, and if we /* guess how much room is left in the device's ring buffer, and if we
@ -462,13 +463,13 @@ static int keyspan_pda_write(struct tty_struct *tty,
the TX urb is in-flight (wait until it completes) the TX urb is in-flight (wait until it completes)
the device is full (wait until it says there is room) the device is full (wait until it says there is room)
*/ */
spin_lock_bh(&port->lock); spin_lock_irqsave(&port->lock, flags);
if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) { if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) {
spin_unlock_bh(&port->lock); spin_unlock_irqrestore(&port->lock, flags);
return 0; return 0;
} }
clear_bit(0, &port->write_urbs_free); clear_bit(0, &port->write_urbs_free);
spin_unlock_bh(&port->lock); spin_unlock_irqrestore(&port->lock, flags);
/* At this point the URB is in our control, nobody else can submit it /* At this point the URB is in our control, nobody else can submit it
again (the only sudden transition was the one from EINPROGRESS to again (the only sudden transition was the one from EINPROGRESS to