]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/tty_ldisc-fix-bug-on-hangup.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / tty_ldisc-fix-bug-on-hangup.patch
CommitLineData
b5d7ff57
GKH
1From 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= <philippe.retornaz@epfl.ch>
3Date: Wed, 27 Oct 2010 17:13:21 +0200
4Subject: tty_ldisc: Fix BUG() on hangup
5
6From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= <philippe.retornaz@epfl.ch>
7
8commit 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae upstream.
9
10A kernel BUG when bluetooth rfcomm connection drop while the associated
11serial port is open is sometime triggered.
12
13It seems that the line discipline can disappear between the
14tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line
15discipline if the previous discipline is not available anymore.
16
17Signed-off-by: Philippe Retornaz <philippe.retornaz@epfl.ch>
18Acked-by: Alan Cox <alan@linux.intel.com>
19Signed-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);