USB: serial: option: add WeTelecom WM-D200
[pandora-kernel.git] / drivers / tty / n_tty.c
index 39d6ab6..4671f8d 100644 (file)
@@ -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);
        }
 
        /*
@@ -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;