diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-18 23:08:58 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-18 23:08:58 +0200 |
commit | 02730d3c053a9af1d402e1c8dc8bbbc5a1340406 (patch) | |
tree | db289a08de50eb4b5caf7840d5b7356ddfa1c51f /drivers/tty/tty_buffer.c | |
parent | vt: Don't check KD_GRAPHICS when binding/unbinding (diff) | |
parent | Linux 4.1-rc4 (diff) | |
download | linux-02730d3c053a9af1d402e1c8dc8bbbc5a1340406.tar.xz linux-02730d3c053a9af1d402e1c8dc8bbbc5a1340406.zip |
Merge 4.1-rc4 into tty-next
This resolves some tty driver merge issues.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_buffer.c')
-rw-r--r-- | drivers/tty/tty_buffer.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 5b2b0ffdde28..4cf263d7dffc 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -37,6 +37,28 @@ #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) +/* + * If all tty flip buffers have been processed by flush_to_ldisc() or + * dropped by tty_buffer_flush(), check if the linked pty has been closed. + * If so, wake the reader/poll to process + */ +static inline void check_other_closed(struct tty_struct *tty) +{ + unsigned long flags, old; + + /* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */ + for (flags = ACCESS_ONCE(tty->flags); + test_bit(TTY_OTHER_CLOSED, &flags); + ) { + old = flags; + __set_bit(TTY_OTHER_DONE, &flags); + flags = cmpxchg(&tty->flags, old, flags); + if (old == flags) { + wake_up_interruptible(&tty->read_wait); + break; + } + } +} /** * tty_buffer_lock_exclusive - gain exclusive access to buffer @@ -229,6 +251,8 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) if (ld && ld->ops->flush_buffer) ld->ops->flush_buffer(tty); + check_other_closed(tty); + atomic_dec(&buf->priority); mutex_unlock(&buf->lock); } @@ -472,8 +496,10 @@ static void flush_to_ldisc(struct work_struct *work) smp_rmb(); count = head->commit - head->read; if (!count) { - if (next == NULL) + if (next == NULL) { + check_other_closed(tty); break; + } buf->head = next; tty_buffer_free(port, head); continue; @@ -490,19 +516,6 @@ static void flush_to_ldisc(struct work_struct *work) } /** - * tty_flush_to_ldisc - * @tty: tty to push - * - * Push the terminal flip buffers to the line discipline. - * - * Must not be called from IRQ context. - */ -void tty_flush_to_ldisc(struct tty_struct *tty) -{ - flush_work(&tty->port->buf.work); -} - -/** * tty_flip_buffer_push - terminal * @port: tty port to push * |