diff options
author | Alan Cox <alan@linux.intel.com> | 2009-11-30 13:17:46 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 15:18:07 -0800 |
commit | 2493c0c166565e36831196446af594eb07892daf (patch) | |
tree | 0175b121f39076dbd858fd7e475885e9d804a5f4 | |
parent | 07f86c03fec711692121bf7f5316e0b3426acc05 (diff) | |
download | linux-2493c0c166565e36831196446af594eb07892daf.tar.bz2 |
tty: isicom: fix deadlock on shutdown
Alexander Strakh <strakh@ispras.ru> reported
KERNEL_VERSION: 2.6.31
DESCRIBE:
Driver drivers/char/isicom.c might sleep in atomic context, because it
calls
tty_port_xmit_buf under spin_lock.
./drivers/char/isicom.c:
1307 static void isicom_hangup(struct tty_struct *tty)
1308 {
...
1315 spin_lock_irqsave(&port->card->card_lock, flags);
1316 isicom_shutdown_port(port);
...
Path to might_sleep macro from isicom_hangup:
1. isicom_hangup calls spin_lock_irqsave (drivers/char/isicom.c:1315) and
then
calls isicom_shutdown_port.
2. isiscom_shutdown_port calls tty_port_free_xmit_buf at
drivers/char/isicom.c:906
3. tty_port_free_xmit_buf calls mutex_lock at drivers/char/tty_port:48
Found by Linux Driver Verification Project.
Reported-by: Alexander Strakh <strakh@ispras.ru>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/char/isicom.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 1e91c302ee42..300d5bd6cd06 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -887,7 +887,6 @@ static void isicom_shutdown_port(struct isi_port *port) { struct isi_board *card = port->card; - tty_port_free_xmit_buf(&port->port); if (--card->count < 0) { pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", card->base, card->count); @@ -927,6 +926,7 @@ static void isicom_shutdown(struct tty_port *port) outw(card->port_status, card->base + 0x02); isicom_shutdown_port(ip); spin_unlock_irqrestore(&card->card_lock, flags); + tty_port_free_xmit_buf(port); } static void isicom_close(struct tty_struct *tty, struct file *filp) |