diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index b811442c5ce6..6bdf1a25b883 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -41,6 +41,9 @@ config VT If unsure, say Y, or else you won't be able to do much with your new shiny Linux system :-) +config TTY_FLUSH_LOCAL_ECHO + bool + config CONSOLE_TRANSLATIONS depends on VT default y diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0475f9685a41..d9ca2119b8f3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -128,6 +128,10 @@ struct n_tty_data { #define MASK(x) ((x) & (N_TTY_BUF_SIZE - 1)) +#if defined(CONFIG_TTY_FLUSH_LOCAL_ECHO) +static void continue_process_echoes(struct work_struct *work); +#endif + static inline size_t read_cnt(struct n_tty_data *ldata) { return ldata->read_head - ldata->read_tail; @@ -751,7 +755,17 @@ static size_t __process_echoes(struct tty_struct *tty) tail++; } - not_yet_stored: +#if defined(CONFIG_TTY_FLUSH_LOCAL_ECHO) + if (ldata->echo_commit != tail) { + if (!tty->delayed_work) { + INIT_DELAYED_WORK(&tty->echo_delayed_work, continue_process_echoes); + schedule_delayed_work(&tty->echo_delayed_work, 1); + } + tty->delayed_work = 1; + } +#endif + +not_yet_stored: ldata->echo_tail = tail; return old_space - space; } @@ -817,6 +831,20 @@ static void flush_echoes(struct tty_struct *tty) mutex_unlock(&ldata->output_lock); } +#if defined(CONFIG_TTY_FLUSH_LOCAL_ECHO) +static void continue_process_echoes(struct work_struct *work) +{ + struct tty_struct *tty = + container_of(work, struct tty_struct, echo_delayed_work.work); + struct n_tty_data *ldata = tty->disc_data; + + mutex_lock(&ldata->output_lock); + tty->delayed_work = 0; + __process_echoes(tty); + mutex_unlock(&ldata->output_lock); +} +#endif + /** * add_echo_byte - add a byte to the echo buffer * @c: unicode byte to echo diff --git a/include/linux/tty.h b/include/linux/tty.h index 1dd587ba6d88..b7094d07eae0 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -322,6 +322,10 @@ struct tty_struct { wait_queue_head_t write_wait; wait_queue_head_t read_wait; struct work_struct hangup_work; +#if defined(CONFIG_TTY_FLUSH_LOCAL_ECHO) + int delayed_work; + struct delayed_work echo_delayed_work; +#endif void *disc_data; void *driver_data; spinlock_t files_lock; /* protects tty_files list */