From 3955f605b4722373586dca20401aa2b440de3273 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 23 Jun 2010 23:32:44 +0200 Subject: [PATCH 54/54] Revert "serial: Use block_til_ready helper" This reverts commit 34ffc9670d67fe068f9d8582dd4d2a18d9a61205. --- drivers/serial/serial_core.c | 87 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 86 insertions(+), 1 deletions(-) diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 78b1eac..ce10627 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1539,6 +1539,91 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); } +/* + * Block the open until the port is ready. We must be called with + * the per-port semaphore held. + */ +static int +uart_block_til_ready(struct file *filp, struct uart_state *state) +{ + DECLARE_WAITQUEUE(wait, current); + struct tty_port *port = &state->port; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->count--; + port->blocked_open++; + spin_unlock_irqrestore(&port->lock, flags); + + add_wait_queue(&port->open_wait, &wait); + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + + /* + * If we have been hung up, tell userspace/restart open. + */ + if (tty_hung_up_p(filp) || port->tty == NULL) + break; + + /* + * If the port has been closed, tell userspace/restart open. + */ + if (!(port->flags & ASYNC_INITIALIZED)) + break; + + /* + * If non-blocking mode is set, or CLOCAL mode is set, + * we don't want to wait for the modem status lines to + * indicate that the port is ready. + * + * Also, if the port is not enabled/configured, we want + * to allow the open to succeed here. Note that we will + * have set TTY_IO_ERROR for a non-existant port. + */ + if ((filp->f_flags & O_NONBLOCK) || + (port->tty->termios->c_cflag & CLOCAL) || + (port->tty->flags & (1 << TTY_IO_ERROR))) + break; + + /* + * Set DTR to allow modem to know we're waiting. Do + * not set RTS here - we want to make sure we catch + * the data from the modem. + */ + if (port->tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); + + /* + * and wait for the carrier to indicate that the + * modem is ready for us. + */ + if (tty_port_carrier_raised(port)) + break; + + schedule(); + + if (signal_pending(current)) + break; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->count++; + port->blocked_open--; + spin_unlock_irqrestore(&port->lock, flags); + + if (signal_pending(current)) + return -ERESTARTSYS; + + if (!port->tty || tty_hung_up_p(filp)) + return -EAGAIN; + + return 0; +} + static struct uart_state *uart_get(struct uart_driver *drv, int line) { struct uart_state *state; @@ -1647,7 +1732,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) */ mutex_unlock(&port->mutex); if (retval == 0) - retval = tty_port_block_til_ready(port, tty, filp); + retval = uart_block_til_ready(filp, state); /* * If this is the first open to succeed, adjust things to suit. -- 1.6.3.3