diff options
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e18c8e864110..c6f970d63060 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -257,6 +257,9 @@ const struct file_operations tty_ldiscs_proc_fops = { * reference to it. If the line discipline is in flux then * wait patiently until it changes. * + * Returns: NULL if the tty has been hungup and not re-opened with + * a new file descriptor, otherwise valid ldisc reference + * * Note: Must not be called from an IRQ/timer context. The caller * must also be careful not to hold other locks that will deadlock * against a discipline change, such as an existing ldisc reference @@ -642,14 +645,15 @@ static void tty_reset_termios(struct tty_struct *tty) * @disc: line discipline to reinitialize * * Completely reinitialize the line discipline state, by closing the - * current instance and opening a new instance. If an error occurs opening - * the new non-N_TTY instance, the instance is dropped and tty->ldisc reset - * to NULL. The caller can then retry with N_TTY instead. + * current instance, if there is one, and opening a new instance. If + * an error occurs opening the new non-N_TTY instance, the instance + * is dropped and tty->ldisc reset to NULL. The caller can then retry + * with N_TTY instead. * * Returns 0 if successful, otherwise error code < 0 */ -static int tty_ldisc_reinit(struct tty_struct *tty, int disc) +int tty_ldisc_reinit(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; int retval; @@ -693,11 +697,9 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int disc) * tty itself so we must be careful about locking rules. */ -void tty_ldisc_hangup(struct tty_struct *tty) +void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) { struct tty_ldisc *ld; - int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; - int err = 0; tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); @@ -725,25 +727,17 @@ void tty_ldisc_hangup(struct tty_struct *tty) */ tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT); - if (tty->ldisc) { + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) + tty_reset_termios(tty); - /* At this point we have a halted ldisc; we want to close it and - reopen a new ldisc. We could defer the reopen to the next - open but it means auditing a lot of other paths so this is - a FIXME */ - if (reset == 0) - err = tty_ldisc_reinit(tty, tty->termios.c_line); - - /* If the re-open fails or we reset then go to N_TTY. The - N_TTY open cannot fail */ - if (reset || err < 0) - tty_ldisc_reinit(tty, N_TTY); + if (tty->ldisc) { + if (reinit) { + if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0) + tty_ldisc_reinit(tty, N_TTY); + } else + tty_ldisc_kill(tty); } tty_ldisc_unlock(tty); - if (reset) - tty_reset_termios(tty); - - tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc); } /** |