X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Ftty%2Fn_tty.c;h=304f58ee440d25e3a27e5f46b26a7f9c7938fb03;hp=39d6ab6551e0884db2237f6ffeba184de92f4c22;hb=8711719778f9e003be82bba0362e87b97b46c891;hpb=6ad390a25a9d1d8606b9b826878f0a30639dc2b3 diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 39d6ab6551e0..304f58ee440d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1298,8 +1298,7 @@ handle_newline: tty->canon_data++; spin_unlock_irqrestore(&tty->read_lock, flags); kill_fasync(&tty->fasync, SIGIO, POLL_IN); - if (waitqueue_active(&tty->read_wait)) - wake_up_interruptible(&tty->read_wait); + wake_up_interruptible(&tty->read_wait); return; } } @@ -1422,8 +1421,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); - if (waitqueue_active(&tty->read_wait)) - wake_up_interruptible(&tty->read_wait); + wake_up_interruptible(&tty->read_wait); } /* @@ -1461,7 +1459,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) BUG_ON(!tty); if (old) - canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON; + canon_change = (old->c_lflag ^ tty->termios->c_lflag) & (ICANON | EXTPROC); if (canon_change) { memset(&tty->read_flags, 0, sizeof tty->read_flags); tty->canon_head = tty->read_tail; @@ -1530,6 +1528,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) tty->real_raw = 0; } n_tty_set_room(tty); + /* + * Fix tty hang when I_IXON(tty) is cleared, but the tty + * been stopped by STOP_CHAR(tty) before it. + */ + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { + start_tty(tty); + } + /* The termios change make the tty ready for I/O */ wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); @@ -1728,7 +1734,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, do_it_again: - BUG_ON(!tty->read_buf); + if (WARN_ON(!tty->read_buf)) + return -EAGAIN; c = job_control(tty, file); if (c < 0) @@ -1988,7 +1995,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, tty->ops->flush_chars(tty); } else { while (nr > 0) { + mutex_lock(&tty->output_lock); c = tty->ops->write(tty, b, nr); + mutex_unlock(&tty->output_lock); if (c < 0) { retval = c; goto break_out; @@ -2087,7 +2096,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, case TIOCINQ: /* FIXME: Locking */ retval = tty->read_cnt; - if (L_ICANON(tty)) + if (L_ICANON(tty) && !L_EXTPROC(tty)) retval = inq_canon(tty); return put_user(retval, (unsigned int __user *) arg); default: