]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.36.2/tty_ldisc-fix-bug-on-hangup.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / tty_ldisc-fix-bug-on-hangup.patch
1 From 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= <philippe.retornaz@epfl.ch>
3 Date: Wed, 27 Oct 2010 17:13:21 +0200
4 Subject: tty_ldisc: Fix BUG() on hangup
5
6 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= <philippe.retornaz@epfl.ch>
7
8 commit 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae upstream.
9
10 A kernel BUG when bluetooth rfcomm connection drop while the associated
11 serial port is open is sometime triggered.
12
13 It seems that the line discipline can disappear between the
14 tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line
15 discipline if the previous discipline is not available anymore.
16
17 Signed-off-by: Philippe Retornaz <philippe.retornaz@epfl.ch>
18 Acked-by: Alan Cox <alan@linux.intel.com>
19 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
20
21 ---
22 drivers/char/tty_ldisc.c | 20 +++++++++++++-------
23 1 file changed, 13 insertions(+), 7 deletions(-)
24
25 --- a/drivers/char/tty_ldisc.c
26 +++ b/drivers/char/tty_ldisc.c
27 @@ -743,9 +743,12 @@ static void tty_reset_termios(struct tty
28 * state closed
29 */
30
31 -static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
32 +static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
33 {
34 - struct tty_ldisc *ld;
35 + struct tty_ldisc *ld = tty_ldisc_get(ldisc);
36 +
37 + if (IS_ERR(ld))
38 + return -1;
39
40 tty_ldisc_close(tty, tty->ldisc);
41 tty_ldisc_put(tty->ldisc);
42 @@ -753,10 +756,10 @@ static void tty_ldisc_reinit(struct tty_
43 /*
44 * Switch the line discipline back
45 */
46 - ld = tty_ldisc_get(ldisc);
47 - BUG_ON(IS_ERR(ld));
48 tty_ldisc_assign(tty, ld);
49 tty_set_termios_ldisc(tty, ldisc);
50 +
51 + return 0;
52 }
53
54 /**
55 @@ -831,13 +834,16 @@ void tty_ldisc_hangup(struct tty_struct
56 a FIXME */
57 if (tty->ldisc) { /* Not yet closed */
58 if (reset == 0) {
59 - tty_ldisc_reinit(tty, tty->termios->c_line);
60 - err = tty_ldisc_open(tty, tty->ldisc);
61 +
62 + if (!tty_ldisc_reinit(tty, tty->termios->c_line))
63 + err = tty_ldisc_open(tty, tty->ldisc);
64 + else
65 + err = 1;
66 }
67 /* If the re-open fails or we reset then go to N_TTY. The
68 N_TTY open cannot fail */
69 if (reset || err) {
70 - tty_ldisc_reinit(tty, N_TTY);
71 + BUG_ON(tty_ldisc_reinit(tty, N_TTY));
72 WARN_ON(tty_ldisc_open(tty, tty->ldisc));
73 }
74 tty_ldisc_enable(tty);