tty: Make tiocgicount a handler
[cascardo/linux.git] / drivers / serial / serial_core.c
index 7f28307..c4ea146 100644 (file)
@@ -58,9 +58,9 @@ static struct lock_class_key port_lock_key;
 #define uart_console(port)     (0)
 #endif
 
-static void uart_change_speed(struct uart_state *state,
+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_wait_until_sent(struct uart_port *port, int timeout);
 static void uart_change_pm(struct uart_state *state, int pm_state);
 
 /*
@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
  * Startup the port.  This will be called once per open.  All calls
  * will be serialised by the per-port mutex.
  */
-static int uart_startup(struct uart_state *state, int init_hw)
+static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)
 {
        struct uart_port *uport = state->uart_port;
        struct tty_port *port = &state->port;
@@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw)
         * once we have successfully opened the port.  Also set
         * up the tty->alt_speed kludge
         */
-       set_bit(TTY_IO_ERROR, &port->tty->flags);
+       set_bit(TTY_IO_ERROR, &tty->flags);
 
        if (uport->type == PORT_UNKNOWN)
                return 0;
@@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw)
                        /*
                         * Initialise the hardware port settings.
                         */
-                       uart_change_speed(state, NULL);
+                       uart_change_speed(tty, state, NULL);
 
                        /*
                         * Setup the RTS and DTR signals once the
                         * port is open and ready to respond.
                         */
-                       if (port->tty->termios->c_cflag & CBAUD)
+                       if (tty->termios->c_cflag & CBAUD)
                                uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
                }
 
                if (port->flags & ASYNC_CTS_FLOW) {
                        spin_lock_irq(&uport->lock);
                        if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
-                               port->tty->hw_stopped = 1;
+                               tty->hw_stopped = 1;
                        spin_unlock_irq(&uport->lock);
                }
 
                set_bit(ASYNCB_INITIALIZED, &port->flags);
 
-               clear_bit(TTY_IO_ERROR, &port->tty->flags);
+               clear_bit(TTY_IO_ERROR, &tty->flags);
        }
 
        if (retval && capable(CAP_SYS_ADMIN))
@@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw)
  * DTR is dropped if the hangup on close termio flag is on.  Calls to
  * uart_shutdown are serialised by the per-port semaphore.
  */
-static void uart_shutdown(struct uart_state *state)
+static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
 {
        struct uart_port *uport = state->uart_port;
        struct tty_port *port = &state->port;
-       struct tty_struct *tty = port->tty;
 
        /*
         * Set the TTY IO error marker
@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
 EXPORT_SYMBOL(uart_get_divisor);
 
 /* FIXME: Consistent locking policy */
-static void
-uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
+static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
+                                       struct ktermios *old_termios)
 {
        struct tty_port *port = &state->port;
-       struct tty_struct *tty = port->tty;
        struct uart_port *uport = state->uart_port;
        struct ktermios *termios;
 
@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
        uport->ops->set_termios(uport, termios, old_termios);
 }
 
-static inline int
-__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
+static inline int __uart_put_char(struct uart_port *port,
+                               struct circ_buf *circ, unsigned char c)
 {
        unsigned long flags;
        int ret = 0;
@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty)
        uart_start(tty);
 }
 
-static int
-uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
+static int uart_write(struct tty_struct *tty,
+                                       const unsigned char *buf, int count)
 {
        struct uart_state *state = tty->driver_data;
        struct uart_port *port;
@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state,
        return 0;
 }
 
-static int uart_set_info(struct uart_state *state,
+static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
                         struct serial_struct __user *newinfo)
 {
        struct serial_struct new_serial;
@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state,
                 * We need to shutdown the serial port at the old
                 * port/type/irq combination.
                 */
-               uart_shutdown(state);
+               uart_shutdown(tty, state);
        }
 
        if (change_port) {
@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state,
                                       "is deprecated.\n", current->comm,
                                       tty_name(port->tty, buf));
                        }
-                       uart_change_speed(state, NULL);
+                       uart_change_speed(tty, state, NULL);
                }
        } else
-               retval = uart_startup(state, 1);
+               retval = uart_startup(tty, state, 1);
  exit:
        mutex_unlock(&port->mutex);
        return retval;
 }
 
-
-/*
- * uart_get_lsr_info - get line status register info.
- * Note: uart_ioctl protects us against hangups.
+/**
+ *     uart_get_lsr_info       -       get line status register info
+ *     @tty: tty associated with the UART
+ *     @state: UART being queried
+ *     @value: returned modem value
+ *
+ *     Note: uart_ioctl protects us against hangups.
  */
-static int uart_get_lsr_info(struct uart_state *state,
-                            unsigned int __user *value)
+static int uart_get_lsr_info(struct tty_struct *tty,
+                       struct uart_state *state, unsigned int __user *value)
 {
        struct uart_port *uport = state->uart_port;
-       struct tty_port *port = &state->port;
        unsigned int result;
 
        result = uport->ops->tx_empty(uport);
@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state,
         */
        if (uport->x_char ||
            ((uart_circ_chars_pending(&state->xmit) > 0) &&
-            !port->tty->stopped && !port->tty->hw_stopped))
+            !tty->stopped && !tty->hw_stopped))
                result &= ~TIOCSER_TEMT;
 
        return put_user(result, value);
@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
        return 0;
 }
 
-static int uart_do_autoconfig(struct uart_state *state)
+static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
 {
        struct uart_port *uport = state->uart_port;
        struct tty_port *port = &state->port;
@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state)
 
        ret = -EBUSY;
        if (tty_port_users(port) == 1) {
-               uart_shutdown(state);
+               uart_shutdown(tty, state);
 
                /*
                 * If we already have a port type configured,
@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state)
                 */
                uport->ops->config_port(uport, flags);
 
-               ret = uart_startup(state, 1);
+               ret = uart_startup(tty, state, 1);
        }
        mutex_unlock(&port->mutex);
        return ret;
@@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int uart_get_count(struct uart_state *state,
-                         struct serial_icounter_struct __user *icnt)
+static int uart_get_icount(struct tty_struct *tty,
+                         struct serial_icounter_struct *icount)
 {
-       struct serial_icounter_struct icount;
+       struct uart_state *state = tty->driver_data;
        struct uart_icount cnow;
        struct uart_port *uport = state->uart_port;
 
@@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_state *state,
        memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
        spin_unlock_irq(&uport->lock);
 
-       icount.cts         = cnow.cts;
-       icount.dsr         = cnow.dsr;
-       icount.rng         = cnow.rng;
-       icount.dcd         = cnow.dcd;
-       icount.rx          = cnow.rx;
-       icount.tx          = cnow.tx;
-       icount.frame       = cnow.frame;
-       icount.overrun     = cnow.overrun;
-       icount.parity      = cnow.parity;
-       icount.brk         = cnow.brk;
-       icount.buf_overrun = cnow.buf_overrun;
+       icount->cts         = cnow.cts;
+       icount->dsr         = cnow.dsr;
+       icount->rng         = cnow.rng;
+       icount->dcd         = cnow.dcd;
+       icount->rx          = cnow.rx;
+       icount->tx          = cnow.tx;
+       icount->frame       = cnow.frame;
+       icount->overrun     = cnow.overrun;
+       icount->parity      = cnow.parity;
+       icount->brk         = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
 
-       return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+       return 0;
 }
 
 /*
@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
                break;
 
        case TIOCSSERIAL:
-               ret = uart_set_info(state, uarg);
+               ret = uart_set_info(tty, state, uarg);
                break;
 
        case TIOCSERCONFIG:
-               ret = uart_do_autoconfig(state);
+               ret = uart_do_autoconfig(tty, state);
                break;
 
        case TIOCSERGWILD: /* obsolete */
@@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
        case TIOCMIWAIT:
                ret = uart_wait_modem_status(state, arg);
                break;
-
-       case TIOCGICOUNT:
-               ret = uart_get_count(state, uarg);
-               break;
        }
 
        if (ret != -ENOIOCTLCMD)
@@ -1172,7 +1168,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
         */
        switch (cmd) {
        case TIOCSERGETLSR: /* Get line status register */
-               ret = uart_get_lsr_info(state, uarg);
+               ret = uart_get_lsr_info(tty, state, uarg);
                break;
 
        default: {
@@ -1194,7 +1190,7 @@ static void uart_set_ldisc(struct tty_struct *tty)
        struct uart_port *uport = state->uart_port;
 
        if (uport->ops->set_ldisc)
-               uport->ops->set_ldisc(uport);
+               uport->ops->set_ldisc(uport, tty->termios->c_line);
 }
 
 static void uart_set_termios(struct tty_struct *tty,
@@ -1219,7 +1215,7 @@ static void uart_set_termios(struct tty_struct *tty,
                return;
        }
 
-       uart_change_speed(state, old_termios);
+       uart_change_speed(tty, state, old_termios);
 
        /* Handle transition to B0 status */
        if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@@ -1272,8 +1268,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
        struct uart_state *state = tty->driver_data;
        struct tty_port *port;
        struct uart_port *uport;
+       unsigned long flags;
 
-       BUG_ON(!kernel_locked());
+       BUG_ON(!tty_locked());
 
        if (!state)
                return;
@@ -1284,9 +1281,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
        pr_debug("uart_close(%d) called\n", uport->line);
 
        mutex_lock(&port->mutex);
+       spin_lock_irqsave(&port->lock, flags);
 
-       if (tty_hung_up_p(filp))
+       if (tty_hung_up_p(filp)) {
+               spin_unlock_irqrestore(&port->lock, flags);
                goto done;
+       }
 
        if ((tty->count == 1) && (port->count != 1)) {
                /*
@@ -1305,8 +1305,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
                       tty->name, port->count);
                port->count = 0;
        }
-       if (port->count)
+       if (port->count) {
+               spin_unlock_irqrestore(&port->lock, flags);
                goto done;
+       }
 
        /*
         * Now we wait for the transmit buffer to clear; and we notify
@@ -1314,9 +1316,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
         * setting tty->closing.
         */
        tty->closing = 1;
+       spin_unlock_irqrestore(&port->lock, flags);
 
-       if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait));
+       if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+               /*
+                * hack: open-coded tty_wait_until_sent to avoid
+                * recursive tty_lock
+                */
+               long timeout = msecs_to_jiffies(port->closing_wait);
+               if (wait_event_interruptible_timeout(tty->write_wait,
+                               !tty_chars_in_buffer(tty), timeout) >= 0)
+                       __uart_wait_until_sent(uport, timeout);
+       }
 
        /*
         * At this point, we stop accepting input.  To do this, we
@@ -1332,45 +1343,47 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
                 * has completely drained; this is especially
                 * important if there is a transmit FIFO!
                 */
-               uart_wait_until_sent(tty, uport->timeout);
+               __uart_wait_until_sent(uport, uport->timeout);
        }
 
-       uart_shutdown(state);
+       uart_shutdown(tty, state);
        uart_flush_buffer(tty);
 
        tty_ldisc_flush(tty);
 
-       tty->closing = 0;
        tty_port_tty_set(port, NULL);
+       spin_lock_irqsave(&port->lock, flags);
+       tty->closing = 0;
 
        if (port->blocked_open) {
+               spin_unlock_irqrestore(&port->lock, flags);
                if (port->close_delay)
                        msleep_interruptible(port->close_delay);
+               spin_lock_irqsave(&port->lock, flags);
        } else if (!uart_console(uport)) {
+               spin_unlock_irqrestore(&port->lock, flags);
                uart_change_pm(state, 3);
+               spin_lock_irqsave(&port->lock, flags);
        }
 
        /*
         * Wake up anyone trying to open this port.
         */
        clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+       spin_unlock_irqrestore(&port->lock, flags);
        wake_up_interruptible(&port->open_wait);
 
 done:
        mutex_unlock(&port->mutex);
 }
 
-static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
+static void __uart_wait_until_sent(struct uart_port *port, int timeout)
 {
-       struct uart_state *state = tty->driver_data;
-       struct uart_port *port = state->uart_port;
        unsigned long char_time, expire;
 
        if (port->type == PORT_UNKNOWN || port->fifosize == 0)
                return;
 
-       lock_kernel();
-
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1416,7 +1429,16 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        set_current_state(TASK_RUNNING); /* might not be needed */
-       unlock_kernel();
+}
+
+static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+       struct uart_state *state = tty->driver_data;
+       struct uart_port *port = state->uart_port;
+
+       tty_lock();
+       __uart_wait_until_sent(port, timeout);
+       tty_unlock();
 }
 
 /*
@@ -1429,16 +1451,19 @@ static void uart_hangup(struct tty_struct *tty)
 {
        struct uart_state *state = tty->driver_data;
        struct tty_port *port = &state->port;
+       unsigned long flags;
 
-       BUG_ON(!kernel_locked());
+       BUG_ON(!tty_locked());
        pr_debug("uart_hangup(%d)\n", state->uart_port->line);
 
        mutex_lock(&port->mutex);
        if (port->flags & ASYNC_NORMAL_ACTIVE) {
                uart_flush_buffer(tty);
-               uart_shutdown(state);
+               uart_shutdown(tty, state);
+               spin_lock_irqsave(&port->lock, flags);
                port->count = 0;
                clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+               spin_unlock_irqrestore(&port->lock, flags);
                tty_port_tty_set(port, NULL);
                wake_up_interruptible(&port->open_wait);
                wake_up_interruptible(&port->delta_msr_wait);
@@ -1446,15 +1471,19 @@ static void uart_hangup(struct tty_struct *tty)
        mutex_unlock(&port->mutex);
 }
 
-/*
- * Copy across the serial console cflag setting into the termios settings
- * for the initial open of the port.  This allows continuity between the
- * kernel settings, and the settings init adopts when it opens the port
- * for the first time.
+/**
+ *     uart_update_termios     -       update the terminal hw settings
+ *     @tty: tty associated with UART
+ *     @state: UART to update
+ *
+ *     Copy across the serial console cflag setting into the termios settings
+ *     for the initial open of the port.  This allows continuity between the
+ *     kernel settings, and the settings init adopts when it opens the port
+ *     for the first time.
  */
-static void uart_update_termios(struct uart_state *state)
+static void uart_update_termios(struct tty_struct *tty,
+                                               struct uart_state *state)
 {
-       struct tty_struct *tty = state->port.tty;
        struct uart_port *port = state->uart_port;
 
        if (uart_console(port) && port->cons->cflag) {
@@ -1471,7 +1500,7 @@ static void uart_update_termios(struct uart_state *state)
                /*
                 * Make termios settings take effect.
                 */
-               uart_change_speed(state, NULL);
+               uart_change_speed(tty, state, NULL);
 
                /*
                 * And finally enable the RTS and DTR signals.
@@ -1481,90 +1510,37 @@ static void uart_update_termios(struct uart_state *state)
        }
 }
 
-/*
- * 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)
+static int uart_carrier_raised(struct tty_port *port)
 {
-       DECLARE_WAITQUEUE(wait, current);
+       struct uart_state *state = container_of(port, struct uart_state, port);
        struct uart_port *uport = state->uart_port;
-       struct tty_port *port = &state->port;
-       unsigned int mctrl;
-
-       port->blocked_open++;
-       port->count--;
-
-       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;
+       int mctrl;
+       spin_lock_irq(&uport->lock);
+       uport->ops->enable_ms(uport);
+       mctrl = uport->ops->get_mctrl(uport);
+       spin_unlock_irq(&uport->lock);
+       if (mctrl & TIOCM_CAR)
+               return 1;
+       return 0;
+}
 
-               /*
-                * 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;
+static void uart_dtr_rts(struct tty_port *port, int onoff)
+{
+       struct uart_state *state = container_of(port, struct uart_state, port);
+       struct uart_port *uport = state->uart_port;
 
-               /*
-                * 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)
-                       uart_set_mctrl(uport, TIOCM_DTR);
+       if (onoff) {
+               uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 
                /*
-                * and wait for the carrier to indicate that the
-                * modem is ready for us.
+                * If this is the first open to succeed,
+                * adjust things to suit.
                 */
-               spin_lock_irq(&uport->lock);
-               uport->ops->enable_ms(uport);
-               mctrl = uport->ops->get_mctrl(uport);
-               spin_unlock_irq(&uport->lock);
-               if (mctrl & TIOCM_CAR)
-                       break;
-
-               mutex_unlock(&port->mutex);
-               schedule();
-               mutex_lock(&port->mutex);
-
-               if (signal_pending(current))
-                       break;
+               if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
+                       uart_update_termios(port->tty, state);
        }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&port->open_wait, &wait);
-
-       port->count++;
-       port->blocked_open--;
-
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       if (!port->tty || tty_hung_up_p(filp))
-               return -EAGAIN;
-
-       return 0;
+       else
+               uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 }
 
 static struct uart_state *uart_get(struct uart_driver *drv, int line)
@@ -1611,7 +1587,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
        struct tty_port *port;
        int retval, line = tty->index;
 
-       BUG_ON(!kernel_locked());
+       BUG_ON(!tty_locked());
        pr_debug("uart_open(%d) called\n", line);
 
        /*
@@ -1668,23 +1644,14 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
        /*
         * Start up the serial port.
         */
-       retval = uart_startup(state, 0);
+       retval = uart_startup(tty, state, 0);
 
        /*
         * If we succeeded, wait until the port is ready.
         */
-       if (retval == 0)
-               retval = uart_block_til_ready(filp, state);
        mutex_unlock(&port->mutex);
-
-       /*
-        * If this is the first open to succeed, adjust things to suit.
-        */
-       if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) {
-               set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
-
-               uart_update_termios(state);
-       }
+       if (retval == 0)
+               retval = tty_port_block_til_ready(port, tty, filp);
 
 fail:
        return retval;
@@ -2010,9 +1977,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
        struct tty_port *port = &state->port;
        struct device *tty_dev;
        struct uart_match match = {uport, drv};
+       struct tty_struct *tty;
 
        mutex_lock(&port->mutex);
 
+       /* Must be inside the mutex lock until we convert to tty_port */
+       tty = port->tty;
+
        tty_dev = device_find_child(uport->dev, &match, serial_match_port);
        if (device_may_wakeup(tty_dev)) {
                enable_irq_wake(uport->irq);
@@ -2090,7 +2061,19 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
        /*
         * Re-enable the console device after suspending.
         */
-       if (uart_console(uport)) {
+       if (console_suspend_enabled && uart_console(uport)) {
+               /*
+                * First try to use the console cflag setting.
+                */
+               memset(&termios, 0, sizeof(struct ktermios));
+               termios.c_cflag = uport->cons->cflag;
+
+               /*
+                * If that's unset, use the tty termios setting.
+                */
+               if (port->tty && port->tty->termios && termios.c_cflag == 0)
+                       termios = *(port->tty->termios);
+
                uart_change_pm(state, 0);
                uport->ops->set_termios(uport, &termios, NULL);
                console_start(uport->cons);
@@ -2105,9 +2088,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
                ops->set_mctrl(uport, 0);
                spin_unlock_irq(&uport->lock);
                if (console_suspend_enabled || !uart_console(uport)) {
+                       /* Protected by port mutex for now */
+                       struct tty_struct *tty = port->tty;
                        ret = ops->startup(uport);
                        if (ret == 0) {
-                               uart_change_speed(state, NULL);
+                               if (tty)
+                                       uart_change_speed(tty, state, NULL);
                                spin_lock_irq(&uport->lock);
                                ops->set_mctrl(uport, uport->mctrl);
                                ops->start_tx(uport);
@@ -2119,7 +2105,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
                                 * Clear the "initialized" flag so we won't try
                                 * to call the low level drivers shutdown method.
                                 */
-                               uart_shutdown(state);
+                               uart_shutdown(tty, state);
                        }
                }
 
@@ -2305,6 +2291,7 @@ static const struct tty_operations uart_ops = {
 #endif
        .tiocmget       = uart_tiocmget,
        .tiocmset       = uart_tiocmset,
+       .get_icount     = uart_get_icount,
 #ifdef CONFIG_CONSOLE_POLL
        .poll_init      = uart_poll_init,
        .poll_get_char  = uart_poll_get_char,
@@ -2312,6 +2299,11 @@ static const struct tty_operations uart_ops = {
 #endif
 };
 
+static const struct tty_port_operations uart_port_ops = {
+       .carrier_raised = uart_carrier_raised,
+       .dtr_rts        = uart_dtr_rts,
+};
+
 /**
  *     uart_register_driver - register a driver with the uart core layer
  *     @drv: low level driver structure
@@ -2368,6 +2360,7 @@ int uart_register_driver(struct uart_driver *drv)
                struct tty_port *port = &state->port;
 
                tty_port_init(port);
+               port->ops = &uart_port_ops;
                port->close_delay     = 500;    /* .5 seconds */
                port->closing_wait    = 30000;  /* 30 seconds */
                tasklet_init(&state->tlet, uart_tasklet_action,