aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/n_tty.c8
-rw-r--r--drivers/tty/tty_ldisc.c7
-rw-r--r--include/linux/tty.h1
3 files changed, 15 insertions, 1 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 68865d9af8a0..16793eccc6ae 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -153,6 +153,12 @@ static void n_tty_set_room(struct tty_struct *tty)
153 if (left && !old_left) { 153 if (left && !old_left) {
154 WARN_RATELIMIT(tty->port->itty == NULL, 154 WARN_RATELIMIT(tty->port->itty == NULL,
155 "scheduling with invalid itty\n"); 155 "scheduling with invalid itty\n");
156 /* see if ldisc has been killed - if so, this means that
157 * even though the ldisc has been halted and ->buf.work
158 * cancelled, ->buf.work is about to be rescheduled
159 */
160 WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
161 "scheduling buffer work for halted ldisc\n");
156 schedule_work(&tty->port->buf.work); 162 schedule_work(&tty->port->buf.work);
157 } 163 }
158} 164}
@@ -1624,6 +1630,8 @@ static int n_tty_open(struct tty_struct *tty)
1624 goto err_free_bufs; 1630 goto err_free_bufs;
1625 1631
1626 tty->disc_data = ldata; 1632 tty->disc_data = ldata;
1633 /* indicate buffer work may resume */
1634 clear_bit(TTY_LDISC_HALTED, &tty->flags);
1627 reset_buffer_flags(tty); 1635 reset_buffer_flags(tty);
1628 tty_unthrottle(tty); 1636 tty_unthrottle(tty);
1629 ldata->column = 0; 1637 ldata->column = 0;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index d794087c327e..c641321b9404 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -375,6 +375,7 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld)
375 375
376void tty_ldisc_enable(struct tty_struct *tty) 376void tty_ldisc_enable(struct tty_struct *tty)
377{ 377{
378 clear_bit(TTY_LDISC_HALTED, &tty->flags);
378 set_bit(TTY_LDISC, &tty->flags); 379 set_bit(TTY_LDISC, &tty->flags);
379 clear_bit(TTY_LDISC_CHANGING, &tty->flags); 380 clear_bit(TTY_LDISC_CHANGING, &tty->flags);
380 wake_up(&tty_ldisc_wait); 381 wake_up(&tty_ldisc_wait);
@@ -513,8 +514,11 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
513 514
514static int tty_ldisc_halt(struct tty_struct *tty) 515static int tty_ldisc_halt(struct tty_struct *tty)
515{ 516{
517 int scheduled;
516 clear_bit(TTY_LDISC, &tty->flags); 518 clear_bit(TTY_LDISC, &tty->flags);
517 return cancel_work_sync(&tty->port->buf.work); 519 scheduled = cancel_work_sync(&tty->port->buf.work);
520 set_bit(TTY_LDISC_HALTED, &tty->flags);
521 return scheduled;
518} 522}
519 523
520/** 524/**
@@ -820,6 +824,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
820 clear_bit(TTY_LDISC, &tty->flags); 824 clear_bit(TTY_LDISC, &tty->flags);
821 tty_unlock(tty); 825 tty_unlock(tty);
822 cancel_work_sync(&tty->port->buf.work); 826 cancel_work_sync(&tty->port->buf.work);
827 set_bit(TTY_LDISC_HALTED, &tty->flags);
823 mutex_unlock(&tty->ldisc_mutex); 828 mutex_unlock(&tty->ldisc_mutex);
824retry: 829retry:
825 tty_lock(tty); 830 tty_lock(tty);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d3548f871968..66ae020e8a98 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -315,6 +315,7 @@ struct tty_file_private {
315#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ 315#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */
316#define TTY_HUPPED 18 /* Post driver->hangup() */ 316#define TTY_HUPPED 18 /* Post driver->hangup() */
317#define TTY_HUPPING 21 /* ->hangup() in progress */ 317#define TTY_HUPPING 21 /* ->hangup() in progress */
318#define TTY_LDISC_HALTED 22 /* Line discipline is halted */
318 319
319#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) 320#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
320 321