Skip to content

Commit

Permalink
tty_ldisc: Fix BUG() on hangup
Browse files Browse the repository at this point in the history
A kernel BUG when bluetooth rfcomm connection drop while the associated
serial port is open is sometime triggered.

It seems that the line discipline can disappear between the
tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line
discipline if the previous discipline is not available anymore.

Signed-off-by: Philippe Retornaz <philippe.retornaz@epfl.ch>
Acked-by: Alan Cox <alan@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Philippe Rétornaz authored and Greg Kroah-Hartman committed Nov 9, 2010
1 parent 100eeae commit 1c95ba1
Showing 1 changed file with 13 additions and 7 deletions.
20 changes: 13 additions & 7 deletions drivers/tty/tty_ldisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,20 +743,23 @@ static void tty_reset_termios(struct tty_struct *tty)
* state closed
*/

static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
{
struct tty_ldisc *ld;
struct tty_ldisc *ld = tty_ldisc_get(ldisc);

if (IS_ERR(ld))
return -1;

tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
tty->ldisc = NULL;
/*
* Switch the line discipline back
*/
ld = tty_ldisc_get(ldisc);
BUG_ON(IS_ERR(ld));
tty_ldisc_assign(tty, ld);
tty_set_termios_ldisc(tty, ldisc);

return 0;
}

/**
Expand Down Expand Up @@ -831,13 +834,16 @@ void tty_ldisc_hangup(struct tty_struct *tty)
a FIXME */
if (tty->ldisc) { /* Not yet closed */
if (reset == 0) {
tty_ldisc_reinit(tty, tty->termios->c_line);
err = tty_ldisc_open(tty, tty->ldisc);

if (!tty_ldisc_reinit(tty, tty->termios->c_line))
err = tty_ldisc_open(tty, tty->ldisc);
else
err = 1;
}
/* If the re-open fails or we reset then go to N_TTY. The
N_TTY open cannot fail */
if (reset || err) {
tty_ldisc_reinit(tty, N_TTY);
BUG_ON(tty_ldisc_reinit(tty, N_TTY));
WARN_ON(tty_ldisc_open(tty, tty->ldisc));
}
tty_ldisc_enable(tty);
Expand Down

0 comments on commit 1c95ba1

Please sign in to comment.