diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 9bbdb1de12e2..7c4447a5c0f4 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef CONFIG_UNIX98_PTYS @@ -312,6 +313,42 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) return 0; } +/** + * pty_start - start() handler + * pty_stop - stop() handler + * @tty: tty being flow-controlled + * + * Propagates the TIOCPKT status to the master pty. + * + * NB: only the master pty can be in packet mode so only the slave + * needs start()/stop() handlers + */ +static void pty_start(struct tty_struct *tty) +{ + unsigned long flags; + + spin_lock_irqsave(&tty->ctrl_lock, flags); + if (tty->link && tty->link->packet) { + tty->ctrl_status &= ~TIOCPKT_STOP; + tty->ctrl_status |= TIOCPKT_START; + wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); + } + spin_unlock_irqrestore(&tty->ctrl_lock, flags); +} + +static void pty_stop(struct tty_struct *tty) +{ + unsigned long flags; + + spin_lock_irqsave(&tty->ctrl_lock, flags); + if (tty->link && tty->link->packet) { + tty->ctrl_status &= ~TIOCPKT_START; + tty->ctrl_status |= TIOCPKT_STOP; + wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); + } + spin_unlock_irqrestore(&tty->ctrl_lock, flags); +} + /** * pty_common_install - set up the pty pair * @driver: the pty driver @@ -471,6 +508,8 @@ static const struct tty_operations slave_pty_ops_bsd = { .set_termios = pty_set_termios, .cleanup = pty_cleanup, .resize = pty_resize, + .start = pty_start, + .stop = pty_stop, .remove = pty_remove }; @@ -646,6 +685,8 @@ static const struct tty_operations pty_unix98_ops = { .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, + .start = pty_start, + .stop = pty_stop, .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup, }; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b8ddfef6b5d8..c249ff1d51ce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -908,8 +908,7 @@ void no_tty(void) * stop_tty - propagate flow control * @tty: tty to stop * - * Perform flow control to the driver. For PTY/TTY pairs we - * must also propagate the TIOCKPKT status. May be called + * Perform flow control to the driver. May be called * on an already stopped device and will not re-call the driver * method. * @@ -919,24 +918,14 @@ void no_tty(void) * but not always. * * Locking: - * ctrl_lock * flow_lock */ void __stop_tty(struct tty_struct *tty) { - unsigned long flags; - if (tty->stopped) return; tty->stopped = 1; - spin_lock_irqsave(&tty->ctrl_lock, flags); - if (tty->link && tty->link->packet) { - tty->ctrl_status &= ~TIOCPKT_START; - tty->ctrl_status |= TIOCPKT_STOP; - wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); - } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (tty->ops->stop) (tty->ops->stop)(tty); } @@ -955,33 +944,21 @@ EXPORT_SYMBOL(stop_tty); * start_tty - propagate flow control * @tty: tty to start * - * Start a tty that has been stopped if at all possible. Perform - * any necessary wakeups and propagate the TIOCPKT status. If this - * is the tty was previous stopped and is being started then the - * driver start method is invoked and the line discipline woken. + * Start a tty that has been stopped if at all possible. If this + * tty was previous stopped and is now being started, the driver + * start method is invoked and the line discipline woken. * * Locking: - * ctrl_lock * flow_lock */ void __start_tty(struct tty_struct *tty) { - unsigned long flags; - if (!tty->stopped || tty->flow_stopped) return; tty->stopped = 0; - spin_lock_irqsave(&tty->ctrl_lock, flags); - if (tty->link && tty->link->packet) { - tty->ctrl_status &= ~TIOCPKT_STOP; - tty->ctrl_status |= TIOCPKT_START; - wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); - } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (tty->ops->start) (tty->ops->start)(tty); - /* If we have a running line discipline it may need kicking */ tty_wakeup(tty); }