tty_port: handle the nonblocking open of a dead port corner case
[linux-2.6.git] / drivers / char / tty_port.c
index 549bd0f..c63f3d3 100644 (file)
@@ -23,6 +23,7 @@ void tty_port_init(struct tty_port *port)
        memset(port, 0, sizeof(*port));
        init_waitqueue_head(&port->open_wait);
        init_waitqueue_head(&port->close_wait);
+       init_waitqueue_head(&port->delta_msr_wait);
        mutex_init(&port->mutex);
        spin_lock_init(&port->lock);
        port->close_delay = (50 * HZ) / 100;
@@ -99,7 +100,7 @@ EXPORT_SYMBOL(tty_port_tty_set);
 static void tty_port_shutdown(struct tty_port *port)
 {
        if (port->ops->shutdown &&
-               test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
+               test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
                        port->ops->shutdown(port);
 
 }
@@ -124,6 +125,7 @@ void tty_port_hangup(struct tty_port *port)
        port->tty = NULL;
        spin_unlock_irqrestore(&port->lock, flags);
        wake_up_interruptible(&port->open_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
        tty_port_shutdown(port);
 }
 EXPORT_SYMBOL(tty_port_hangup);
@@ -217,8 +219,14 @@ int tty_port_block_til_ready(struct tty_port *port,
 
        /* if non-blocking mode is set we can pass directly to open unless
           the port has just hung up or is in another error state */
-       if ((filp->f_flags & O_NONBLOCK) ||
-                       (tty->flags & (1 << TTY_IO_ERROR))) {
+       if (tty->flags & (1 << TTY_IO_ERROR)) {
+               port->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;
+       }
+       if (filp->f_flags & O_NONBLOCK) {
+               /* Indicate we are open */
+               if (tty->termios->c_cflag & CBAUD)
+                       tty_port_raise_dtr_rts(port);
                port->flags |= ASYNC_NORMAL_ACTIVE;
                return 0;
        }
@@ -309,7 +317,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
                        port->ops->drop(port);
                return 0;
        }
-       set_bit(ASYNC_CLOSING, &port->flags);
+       set_bit(ASYNCB_CLOSING, &port->flags);
        tty->closing = 1;
        spin_unlock_irqrestore(&port->lock, flags);
        /* Don't block on a stalled port, just pull the chain */