diff options
author | Alan Cox <alan@linux.intel.com> | 2009-11-30 08:17:46 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 18:18:07 -0500 |
commit | 2493c0c166565e36831196446af594eb07892daf (patch) | |
tree | 0175b121f39076dbd858fd7e475885e9d804a5f4 /drivers/char | |
parent | 07f86c03fec711692121bf7f5316e0b3426acc05 (diff) |
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>
Diffstat (limited to 'drivers/char')
-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) | |||
887 | { | 887 | { |
888 | struct isi_board *card = port->card; | 888 | struct isi_board *card = port->card; |
889 | 889 | ||
890 | tty_port_free_xmit_buf(&port->port); | ||
891 | if (--card->count < 0) { | 890 | if (--card->count < 0) { |
892 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 891 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", |
893 | card->base, card->count); | 892 | card->base, card->count); |
@@ -927,6 +926,7 @@ static void isicom_shutdown(struct tty_port *port) | |||
927 | outw(card->port_status, card->base + 0x02); | 926 | outw(card->port_status, card->base + 0x02); |
928 | isicom_shutdown_port(ip); | 927 | isicom_shutdown_port(ip); |
929 | spin_unlock_irqrestore(&card->card_lock, flags); | 928 | spin_unlock_irqrestore(&card->card_lock, flags); |
929 | tty_port_free_xmit_buf(port); | ||
930 | } | 930 | } |
931 | 931 | ||
932 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 932 | static void isicom_close(struct tty_struct *tty, struct file *filp) |