Commit 21622939fc452c7fb739464b8e49368c3ceaa0ee
Committed by
Greg Kroah-Hartman
1 parent
91debb0383
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
tty: Add diagnostic for halted line discipline
Flip buffer work must not be scheduled by the line discipline after the line discipline has been halted; issue warning. Note: drivers can still schedule flip buffer work. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 3 changed files with 15 additions and 1 deletions Side-by-side Diff
drivers/tty/n_tty.c
... | ... | @@ -153,6 +153,12 @@ |
153 | 153 | if (left && !old_left) { |
154 | 154 | WARN_RATELIMIT(tty->port->itty == NULL, |
155 | 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 | 162 | schedule_work(&tty->port->buf.work); |
157 | 163 | } |
158 | 164 | } |
... | ... | @@ -1624,6 +1630,8 @@ |
1624 | 1630 | goto err_free_bufs; |
1625 | 1631 | |
1626 | 1632 | tty->disc_data = ldata; |
1633 | + /* indicate buffer work may resume */ | |
1634 | + clear_bit(TTY_LDISC_HALTED, &tty->flags); | |
1627 | 1635 | reset_buffer_flags(tty); |
1628 | 1636 | tty_unthrottle(tty); |
1629 | 1637 | ldata->column = 0; |
drivers/tty/tty_ldisc.c
... | ... | @@ -375,6 +375,7 @@ |
375 | 375 | |
376 | 376 | void tty_ldisc_enable(struct tty_struct *tty) |
377 | 377 | { |
378 | + clear_bit(TTY_LDISC_HALTED, &tty->flags); | |
378 | 379 | set_bit(TTY_LDISC, &tty->flags); |
379 | 380 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
380 | 381 | wake_up(&tty_ldisc_wait); |
381 | 382 | |
... | ... | @@ -513,8 +514,11 @@ |
513 | 514 | |
514 | 515 | static int tty_ldisc_halt(struct tty_struct *tty) |
515 | 516 | { |
517 | + int scheduled; | |
516 | 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 @@ |
820 | 824 | clear_bit(TTY_LDISC, &tty->flags); |
821 | 825 | tty_unlock(tty); |
822 | 826 | cancel_work_sync(&tty->port->buf.work); |
827 | + set_bit(TTY_LDISC_HALTED, &tty->flags); | |
823 | 828 | mutex_unlock(&tty->ldisc_mutex); |
824 | 829 | retry: |
825 | 830 | tty_lock(tty); |
include/linux/tty.h
... | ... | @@ -315,6 +315,7 @@ |
315 | 315 | #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ |
316 | 316 | #define TTY_HUPPED 18 /* Post driver->hangup() */ |
317 | 317 | #define TTY_HUPPING 21 /* ->hangup() in progress */ |
318 | +#define TTY_LDISC_HALTED 22 /* Line discipline is halted */ | |
318 | 319 | |
319 | 320 | #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) |
320 | 321 |