]> Pileus Git - ~andy/linux/blobdiff - drivers/serial/serial_core.c
USB: ratelimit debounce error messages
[~andy/linux] / drivers / serial / serial_core.c
index d814bb1dcb052b246f707c64c89ae01e3b775eee..0422c0f1f85207715ebe221d182de4f48f85b655 100644 (file)
@@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key;
 #define uart_console(port)     (0)
 #endif
 
-static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
+static void uart_change_speed(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);
 
@@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout);
  *     we're actually going to be using.
  */
 unsigned int
-uart_get_baud_rate(struct uart_port *port, struct termios *termios,
-                  struct termios *old, unsigned int min, unsigned int max)
+uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+                  struct ktermios *old, unsigned int min, unsigned int max)
 {
        unsigned int try, baud, altbaud = 38400;
        upf_t flags = port->flags & UPF_SPD_MASK;
@@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
 EXPORT_SYMBOL(uart_get_divisor);
 
 static void
-uart_change_speed(struct uart_state *state, struct termios *old_termios)
+uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
 {
        struct tty_struct *tty = state->info->tty;
        struct uart_port *port = state->port;
-       struct termios *termios;
+       struct ktermios *termios;
 
        /*
         * If we have no tty, termios, or the port does not exist,
@@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
        return ret;
 }
 
-static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct uart_state *state = tty->driver_data;
        unsigned long flags;
@@ -1523,9 +1523,8 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
        }
 
        if (!state->info) {
-               state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
+               state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL);
                if (state->info) {
-                       memset(state->info, 0, sizeof(struct uart_info));
                        init_waitqueue_head(&state->info->open_wait);
                        init_waitqueue_head(&state->info->delta_msr_wait);
 
@@ -1660,6 +1659,7 @@ static const char *uart_type(struct uart_port *port)
 static int uart_line_info(char *buf, struct uart_driver *drv, int i)
 {
        struct uart_state *state = drv->state + i;
+       int pm_state;
        struct uart_port *port = state->port;
        char stat_buf[32];
        unsigned int status;
@@ -1682,9 +1682,16 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i)
 
        if(capable(CAP_SYS_ADMIN))
        {
+               mutex_lock(&state->mutex);
+               pm_state = state->pm_state;
+               if (pm_state)
+                       uart_change_pm(state, 0);
                spin_lock_irq(&port->lock);
                status = port->ops->get_mctrl(port);
                spin_unlock_irq(&port->lock);
+               if (pm_state)
+                       uart_change_pm(state, pm_state);
+               mutex_unlock(&state->mutex);
 
                ret += sprintf(buf + ret, " tx:%d rx:%d",
                                port->icount.tx, port->icount.rx);
@@ -1866,7 +1873,7 @@ int __init
 uart_set_options(struct uart_port *port, struct console *co,
                 int baud, int parity, int bits, int flow)
 {
-       struct termios termios;
+       struct ktermios termios;
        int i;
 
        /*
@@ -1876,7 +1883,7 @@ uart_set_options(struct uart_port *port, struct console *co,
        spin_lock_init(&port->lock);
        lockdep_set_class(&port->lock, &port_lock_key);
 
-       memset(&termios, 0, sizeof(struct termios));
+       memset(&termios, 0, sizeof(struct ktermios));
 
        termios.c_cflag = CREAD | HUPCL | CLOCAL;
 
@@ -1940,6 +1947,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
        if (state->info && state->info->flags & UIF_INITIALIZED) {
                const struct uart_ops *ops = port->ops;
 
+               state->info->flags = (state->info->flags & ~UIF_INITIALIZED)
+                                    | UIF_SUSPENDED;
+
                spin_lock_irq(&port->lock);
                ops->stop_tx(port);
                ops->set_mctrl(port, 0);
@@ -1988,12 +1998,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
         * Re-enable the console device after suspending.
         */
        if (uart_console(port)) {
-               struct termios termios;
+               struct ktermios termios;
 
                /*
                 * First try to use the console cflag setting.
                 */
-               memset(&termios, 0, sizeof(struct termios));
+               memset(&termios, 0, sizeof(struct ktermios));
                termios.c_cflag = port->cons->cflag;
 
                /*
@@ -2006,7 +2016,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
                console_start(port->cons);
        }
 
-       if (state->info && state->info->flags & UIF_INITIALIZED) {
+       if (state->info && state->info->flags & UIF_SUSPENDED) {
                const struct uart_ops *ops = port->ops;
                int ret;
 
@@ -2018,15 +2028,17 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
                        ops->set_mctrl(port, port->mctrl);
                        ops->start_tx(port);
                        spin_unlock_irq(&port->lock);
+                       state->info->flags |= UIF_INITIALIZED;
                } else {
                        /*
                         * Failed to resume - maybe hardware went away?
                         * Clear the "initialized" flag so we won't try
                         * to call the low level drivers shutdown method.
                         */
-                       state->info->flags &= ~UIF_INITIALIZED;
                        uart_shutdown(state);
                }
+
+               state->info->flags &= ~UIF_SUSPENDED;
        }
 
        mutex_unlock(&state->mutex);
@@ -2095,6 +2107,9 @@ 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);
+
                /*
                 * Ensure that the modem control lines are de-activated.
                 * We probably don't need a spinlock around this, but
@@ -2112,7 +2127,7 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
        }
 }
 
-static struct tty_operations uart_ops = {
+static const struct tty_operations uart_ops = {
        .open           = uart_open,
        .close          = uart_close,
        .write          = uart_write,
@@ -2162,13 +2177,11 @@ int uart_register_driver(struct uart_driver *drv)
         * Maybe we should be using a slab cache for this, especially if
         * we have a large number of ports to handle.
         */
-       drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+       drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
        retval = -ENOMEM;
        if (!drv->state)
                goto out;
 
-       memset(drv->state, 0, sizeof(struct uart_state) * drv->nr);
-
        normal  = alloc_tty_driver(drv->nr);
        if (!normal)
                goto out;
@@ -2184,6 +2197,7 @@ int uart_register_driver(struct uart_driver *drv)
        normal->subtype         = SERIAL_TYPE_NORMAL;
        normal->init_termios    = tty_std_termios;
        normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
        normal->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        normal->driver_state    = drv;
        tty_set_operations(normal, &uart_ops);