Merge tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / tty / serial / 8250 / 8250_core.c
index 27483d3fcfa0b7bb51e64069546d784bfe7f2909..11c66856ba2fcb59edf96bba1459b0a9b5e4f9db 100644 (file)
@@ -541,23 +541,25 @@ void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 }
 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
 
-static void serial8250_rpm_get(struct uart_8250_port *p)
+void serial8250_rpm_get(struct uart_8250_port *p)
 {
        if (!(p->capabilities & UART_CAP_RPM))
                return;
        pm_runtime_get_sync(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
 
-static void serial8250_rpm_put(struct uart_8250_port *p)
+void serial8250_rpm_put(struct uart_8250_port *p)
 {
        if (!(p->capabilities & UART_CAP_RPM))
                return;
        pm_runtime_mark_last_busy(p->port.dev);
        pm_runtime_put_autosuspend(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
 
 /*
- * This two wrapper ensure, that enable_runtime_pm_tx() can be called more than
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
  * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
  * empty and the HW can idle again.
  */
@@ -595,6 +597,7 @@ static void serial8250_rpm_put_tx(struct uart_8250_port *p)
  */
 static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 {
+       unsigned char lcr = 0, efr = 0;
        /*
         * Exar UARTs have a SLEEP register that enables or disables
         * each UART to enter sleep mode separately.  On the XR17V35x the
@@ -611,6 +614,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 
        if (p->capabilities & UART_CAP_SLEEP) {
                if (p->capabilities & UART_CAP_EFR) {
+                       lcr = serial_in(p, UART_LCR);
+                       efr = serial_in(p, UART_EFR);
                        serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
                        serial_out(p, UART_EFR, UART_EFR_ECB);
                        serial_out(p, UART_LCR, 0);
@@ -618,8 +623,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
                serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
                if (p->capabilities & UART_CAP_EFR) {
                        serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_out(p, UART_EFR, 0);
-                       serial_out(p, UART_LCR, 0);
+                       serial_out(p, UART_EFR, efr);
+                       serial_out(p, UART_LCR, lcr);
                }
        }
 out:
@@ -1350,7 +1355,7 @@ static void serial8250_start_tx(struct uart_port *port)
        struct uart_8250_port *up = up_to_u8250p(port);
 
        serial8250_rpm_get_tx(up);
-       if (up->dma && !serial8250_tx_dma(up)) {
+       if (up->dma && !up->dma->tx_dma(up)) {
                return;
        } else if (!(up->ier & UART_IER_THRI)) {
                up->ier |= UART_IER_THRI;
@@ -1397,6 +1402,19 @@ static void serial8250_stop_rx(struct uart_port *port)
        serial8250_rpm_put(up);
 }
 
+static void serial8250_disable_ms(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
+       up->ier &= ~UART_IER_MSI;
+       serial_port_out(port, UART_IER, up->ier);
+}
+
 static void serial8250_enable_ms(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
@@ -1483,7 +1501,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
 
 ignore_char:
                lsr = serial_in(up, UART_LSR);
-       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
        spin_unlock(&port->lock);
        tty_flip_buffer_push(&port->state->port);
        spin_lock(&port->lock);
@@ -1532,7 +1550,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
        DEBUG_INTR("THRE...");
 
        /*
-        * With RPM enabled, we have to wait once the FIFO is empty before the
+        * With RPM enabled, we have to wait until the FIFO is empty before the
         * HW can go idle. So we get here once again with empty FIFO and disable
         * the interrupt and RPM in __stop_tx()
         */
@@ -1588,13 +1606,14 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 
        if (status & (UART_LSR_DR | UART_LSR_BI)) {
                if (up->dma)
-                       dma_err = serial8250_rx_dma(up, iir);
+                       dma_err = up->dma->rx_dma(up, iir);
 
                if (!up->dma || dma_err)
                        status = serial8250_rx_chars(up, status);
        }
        serial8250_modem_status(up);
-       if (!up->dma && (status & UART_LSR_THRE))
+       if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+           (status & UART_LSR_THRE))
                serial8250_tx_chars(up);
 
        spin_unlock_irqrestore(&port->lock, flags);
@@ -2603,13 +2622,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
 }
 
 static void
-serial8250_set_ldisc(struct uart_port *port, int new)
+serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
 {
-       if (new == N_PPS) {
+       if (termios->c_line == N_PPS) {
                port->flags |= UPF_HARDPPS_CD;
+               spin_lock_irq(&port->lock);
                serial8250_enable_ms(port);
-       } else
+               spin_unlock_irq(&port->lock);
+       } else {
                port->flags &= ~UPF_HARDPPS_CD;
+               if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+                       spin_lock_irq(&port->lock);
+                       serial8250_disable_ms(port);
+                       spin_unlock_irq(&port->lock);
+               }
+       }
 }
 
 
@@ -2634,8 +2661,11 @@ serial8250_pm(struct uart_port *port, unsigned int state,
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
-       if (pt->port.iotype == UPIO_AU)
+       if (pt->port.iotype == UPIO_AU) {
+               if (pt->port.type == PORT_RT2880)
+                       return 0x100;
                return 0x1000;
+       }
        if (is_omap1_8250(pt))
                return 0x16 << pt->port.regshift;
 
@@ -2975,42 +3005,6 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
        return 0;
 }
 
-static int serial8250_ioctl(struct uart_port *port, unsigned int cmd,
-                          unsigned long arg)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       int ret;
-       struct serial_rs485 rs485_config;
-
-       if (!up->rs485_config)
-               return -ENOIOCTLCMD;
-
-       switch (cmd) {
-       case TIOCSRS485:
-               if (copy_from_user(&rs485_config, (void __user *)arg,
-                                  sizeof(rs485_config)))
-                       return -EFAULT;
-
-               ret = up->rs485_config(up, &rs485_config);
-               if (ret)
-                       return ret;
-
-               memcpy(&up->rs485, &rs485_config, sizeof(rs485_config));
-
-               return 0;
-       case TIOCGRS485:
-               if (copy_to_user((void __user *)arg, &up->rs485,
-                                sizeof(up->rs485)))
-                       return -EFAULT;
-               return 0;
-       default:
-               break;
-       }
-
-       return -ENOIOCTLCMD;
-}
-
 static const char *
 serial8250_type(struct uart_port *port)
 {
@@ -3042,7 +3036,6 @@ static struct uart_ops serial8250_pops = {
        .request_port   = serial8250_request_port,
        .config_port    = serial8250_config_port,
        .verify_port    = serial8250_verify_port,
-       .ioctl          = serial8250_ioctl,
 #ifdef CONFIG_CONSOLE_POLL
        .poll_get_char = serial8250_get_poll_char,
        .poll_put_char = serial8250_put_poll_char,
@@ -3198,7 +3191,9 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 
        serial8250_rpm_get(up);
 
-       if (port->sysrq || oops_in_progress)
+       if (port->sysrq)
+               locked = 0;
+       else if (oops_in_progress)
                locked = spin_trylock_irqsave(&port->lock, flags);
        else
                spin_lock_irqsave(&port->lock, flags);
@@ -3237,7 +3232,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        serial8250_rpm_put(up);
 }
 
-static int __init serial8250_console_setup(struct console *co, char *options)
+static int serial8250_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        int baud = 9600;
@@ -3584,10 +3579,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->port.fifosize     = up->port.fifosize;
                uart->tx_loadsz         = up->tx_loadsz;
                uart->capabilities      = up->capabilities;
-               uart->rs485_config      = up->rs485_config;
-               uart->rs485             = up->rs485;
                uart->port.throttle     = up->port.throttle;
                uart->port.unthrottle   = up->port.unthrottle;
+               uart->port.rs485_config = up->port.rs485_config;
+               uart->port.rs485        = up->port.rs485;
 
                /* Take tx_loadsz from fifosize if it wasn't set separately */
                if (uart->port.fifosize && !uart->tx_loadsz)
@@ -3622,8 +3617,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                        uart->dl_read = up->dl_read;
                if (up->dl_write)
                        uart->dl_write = up->dl_write;
-               if (up->dma)
+               if (up->dma) {
                        uart->dma = up->dma;
+                       if (!uart->dma->tx_dma)
+                               uart->dma->tx_dma = serial8250_tx_dma;
+                       if (!uart->dma->rx_dma)
+                               uart->dma->rx_dma = serial8250_rx_dma;
+               }
 
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(0, &uart->port,