diff options
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2c7230aaefd4..ca98a3f65fe1 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -59,7 +59,8 @@ static struct lock_class_key port_lock_key; static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); -static void uart_change_pm(struct uart_state *state, int pm_state); +static void uart_change_pm(struct uart_state *state, + enum uart_pm_state pm_state); static void uart_port_shutdown(struct tty_port *port); @@ -866,9 +867,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, port->closing_wait = closing_wait; if (new_info->xmit_fifo_size) uport->fifosize = new_info->xmit_fifo_size; - if (port->tty) - port->tty->low_latency = - (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; + port->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; check_and_exit: retval = 0; @@ -1308,9 +1307,10 @@ static void uart_set_termios(struct tty_struct *tty, } /* - * In 2.4.5, calls to this will be serialized via the BKL in - * linux/drivers/char/tty_io.c:tty_release() - * linux/drivers/char/tty_io.c:do_tty_handup() + * Calls to uart_close() are serialised via the tty_lock in + * drivers/tty/tty_io.c:tty_release() + * drivers/tty/tty_io.c:do_tty_hangup() + * This runs from a workqueue and can sleep for a _short_ time only. */ static void uart_close(struct tty_struct *tty, struct file *filp) { @@ -1365,7 +1365,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) spin_lock_irqsave(&port->lock, flags); } else if (!uart_console(uport)) { spin_unlock_irqrestore(&port->lock, flags); - uart_change_pm(state, 3); + uart_change_pm(state, UART_PM_STATE_OFF); spin_lock_irqsave(&port->lock, flags); } @@ -1437,10 +1437,9 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) } /* - * This is called with the BKL held in - * linux/drivers/char/tty_io.c:do_tty_hangup() - * We're called from the eventd thread, so we can sleep for - * a _short_ time only. + * Calls to uart_hangup() are serialised by the tty_lock in + * drivers/tty/tty_io.c:do_tty_hangup() + * This runs from a workqueue and can sleep for a _short_ time only. */ static void uart_hangup(struct tty_struct *tty) { @@ -1521,8 +1520,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) } /* - * calls to uart_open are serialised by the BKL in - * fs/char_dev.c:chrdev_open() + * Calls to uart_open are serialised by the tty_lock in + * drivers/tty/tty_io.c:tty_open() * Note that if this fails, then uart_close() _will_ be called. * * In time, we want to scrap the "opening nonpresent ports" @@ -1564,7 +1563,8 @@ static int uart_open(struct tty_struct *tty, struct file *filp) */ tty->driver_data = state; state->uart_port->state = state; - tty->low_latency = (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0; + state->port.low_latency = + (state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0; tty_port_tty_set(port, tty); /* @@ -1579,7 +1579,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) * Make sure the device is in D0 state. */ if (port->count == 1) - uart_change_pm(state, 0); + uart_change_pm(state, UART_PM_STATE_ON); /* * Start up the serial port. @@ -1620,7 +1620,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) { struct uart_state *state = drv->state + i; struct tty_port *port = &state->port; - int pm_state; + enum uart_pm_state pm_state; struct uart_port *uport = state->uart_port; char stat_buf[32]; unsigned int status; @@ -1645,12 +1645,12 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) if (capable(CAP_SYS_ADMIN)) { mutex_lock(&port->mutex); pm_state = state->pm_state; - if (pm_state) - uart_change_pm(state, 0); + if (pm_state != UART_PM_STATE_ON) + uart_change_pm(state, UART_PM_STATE_ON); spin_lock_irq(&uport->lock); status = uport->ops->get_mctrl(uport); spin_unlock_irq(&uport->lock); - if (pm_state) + if (pm_state != UART_PM_STATE_ON) uart_change_pm(state, pm_state); mutex_unlock(&port->mutex); @@ -1897,7 +1897,8 @@ EXPORT_SYMBOL_GPL(uart_set_options); * * Locking: port->mutex has to be held */ -static void uart_change_pm(struct uart_state *state, int pm_state) +static void uart_change_pm(struct uart_state *state, + enum uart_pm_state pm_state) { struct uart_port *port = state->uart_port; @@ -1982,7 +1983,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) console_stop(uport->cons); if (console_suspend_enabled || !uart_console(uport)) - uart_change_pm(state, 3); + uart_change_pm(state, UART_PM_STATE_OFF); mutex_unlock(&port->mutex); @@ -2027,7 +2028,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) termios = port->tty->termios; if (console_suspend_enabled) - uart_change_pm(state, 0); + uart_change_pm(state, UART_PM_STATE_ON); uport->ops->set_termios(uport, &termios, NULL); if (console_suspend_enabled) console_start(uport->cons); @@ -2037,7 +2038,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) const struct uart_ops *ops = uport->ops; int ret; - uart_change_pm(state, 0); + uart_change_pm(state, UART_PM_STATE_ON); spin_lock_irq(&uport->lock); ops->set_mctrl(uport, 0); spin_unlock_irq(&uport->lock); @@ -2137,7 +2138,7 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, uart_report_port(drv, port); /* Power up port for set_mctrl() */ - uart_change_pm(state, 0); + uart_change_pm(state, UART_PM_STATE_ON); /* * Ensure that the modem control lines are de-activated. @@ -2161,7 +2162,7 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, * console if we have one. */ if (!uart_console(port)) - uart_change_pm(state, 3); + uart_change_pm(state, UART_PM_STATE_OFF); } } @@ -2588,7 +2589,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) } state->uart_port = uport; - state->pm_state = -1; + state->pm_state = UART_PM_STATE_UNDEFINED; uport->cons = drv->cons; uport->state = state; @@ -2642,6 +2643,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) { struct uart_state *state = drv->state + uport->line; struct tty_port *port = &state->port; + int ret = 0; BUG_ON(in_interrupt()); @@ -2656,6 +2658,11 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) * succeeding while we shut down the port. */ mutex_lock(&port->mutex); + if (!state->uart_port) { + mutex_unlock(&port->mutex); + ret = -EINVAL; + goto out; + } uport->flags |= UPF_DEAD; mutex_unlock(&port->mutex); @@ -2679,9 +2686,10 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) uport->type = PORT_UNKNOWN; state->uart_port = NULL; +out: mutex_unlock(&port_mutex); - return 0; + return ret; } /* @@ -2790,10 +2798,10 @@ EXPORT_SYMBOL_GPL(uart_handle_cts_change); void uart_insert_char(struct uart_port *port, unsigned int status, unsigned int overrun, unsigned int ch, unsigned int flag) { - struct tty_struct *tty = port->state->port.tty; + struct tty_port *tport = &port->state->port; if ((status & port->ignore_status_mask & ~overrun) == 0) - if (tty_insert_flip_char(tty, ch, flag) == 0) + if (tty_insert_flip_char(tport, ch, flag) == 0) ++port->icount.buf_overrun; /* @@ -2801,7 +2809,7 @@ void uart_insert_char(struct uart_port *port, unsigned int status, * it doesn't affect the current character. */ if (status & ~port->ignore_status_mask & overrun) - if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0) + if (tty_insert_flip_char(tport, 0, TTY_OVERRUN) == 0) ++port->icount.buf_overrun; } EXPORT_SYMBOL_GPL(uart_insert_char); |