serial: don't optimise away baud rate changes when BOTHER is used
[linux-2.6-block.git] / drivers / serial / serial_core.c
index 0422c0f1f85207715ebe221d182de4f48f85b655..a055f58f342f3a1570f8648eb35c4df8550be353 100644 (file)
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTK(x...)  printk(x)
-#else
-#define DPRINTK(x...)  do { } while (0)
-#endif
-
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -552,7 +545,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
                return;
        }
 
-       DPRINTK("uart_flush_buffer(%d) called\n", tty->index);
+       pr_debug("uart_flush_buffer(%d) called\n", tty->index);
 
        spin_lock_irqsave(&port->lock, flags);
        uart_circ_clear(&state->info->xmit);
@@ -633,7 +626,7 @@ static int uart_get_info(struct uart_state *state,
        tmp.hub6            = port->hub6;
        tmp.io_type         = port->iotype;
        tmp.iomem_reg_shift = port->regshift;
-       tmp.iomem_base      = (void *)port->mapbase;
+       tmp.iomem_base      = (void *)(unsigned long)port->mapbase;
 
        if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
                return -EFAULT;
@@ -672,19 +665,21 @@ static int uart_set_info(struct uart_state *state,
         */
        mutex_lock(&state->mutex);
 
-       change_irq  = new_serial.irq != port->irq;
+       change_irq  = !(port->flags & UPF_FIXED_PORT)
+               && new_serial.irq != port->irq;
 
        /*
         * Since changing the 'type' of the port changes its resource
         * allocations, we should treat type changes the same as
         * IO port changes.
         */
-       change_port = new_port != port->iobase ||
-                     (unsigned long)new_serial.iomem_base != port->mapbase ||
-                     new_serial.hub6 != port->hub6 ||
-                     new_serial.io_type != port->iotype ||
-                     new_serial.iomem_reg_shift != port->regshift ||
-                     new_serial.type != port->type;
+       change_port = !(port->flags & UPF_FIXED_PORT)
+               && (new_port != port->iobase ||
+                   (unsigned long)new_serial.iomem_base != port->mapbase ||
+                   new_serial.hub6 != port->hub6 ||
+                   new_serial.io_type != port->iotype ||
+                   new_serial.iomem_reg_shift != port->regshift ||
+                   new_serial.type != port->type);
 
        old_flags = port->flags;
        new_flags = new_serial.flags;
@@ -796,8 +791,10 @@ static int uart_set_info(struct uart_state *state,
                }
        }
 
-       port->irq              = new_serial.irq;
-       port->uartclk          = new_serial.baud_base * 16;
+       if (change_irq)
+               port->irq      = new_serial.irq;
+       if (!(port->flags & UPF_FIXED_PORT))
+               port->uartclk  = new_serial.baud_base * 16;
        port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
                                 (new_flags & UPF_CHANGE_MASK);
        port->custom_divisor   = new_serial.custom_divisor;
@@ -1149,11 +1146,14 @@ static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termio
 
        /*
         * These are the bits that are used to setup various
-        * flags in the low level driver.
+        * flags in the low level driver. We can ignore the Bfoo
+        * bits in c_cflag; c_[io]speed will always be set
+        * appropriately by set_termios() in tty_ioctl.c
         */
 #define RELEVANT_IFLAG(iflag)  ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
        if ((cflag ^ old_termios->c_cflag) == 0 &&
+           tty->termios->c_ospeed == old_termios->c_ospeed &&
+           tty->termios->c_ispeed == old_termios->c_ispeed &&
            RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
                return;
 
@@ -1220,7 +1220,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 
        port = state->port;
 
-       DPRINTK("uart_close(%d) called\n", port->line);
+       pr_debug("uart_close(%d) called\n", port->line);
 
        mutex_lock(&state->mutex);
 
@@ -1339,7 +1339,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
 
        expire = jiffies + timeout;
 
-       DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
+       pr_debug("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
                port->line, jiffies, expire);
 
        /*
@@ -1368,7 +1368,7 @@ static void uart_hangup(struct tty_struct *tty)
        struct uart_state *state = tty->driver_data;
 
        BUG_ON(!kernel_locked());
-       DPRINTK("uart_hangup(%d)\n", state->port->line);
+       pr_debug("uart_hangup(%d)\n", state->port->line);
 
        mutex_lock(&state->mutex);
        if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
@@ -1566,7 +1566,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
        int retval, line = tty->index;
 
        BUG_ON(!kernel_locked());
-       DPRINTK("uart_open(%d) called\n", line);
+       pr_debug("uart_open(%d) called\n", line);
 
        /*
         * tty->driver->num won't change, so we won't fail here with
@@ -1669,10 +1669,11 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i)
                return 0;
 
        mmio = port->iotype >= UPIO_MEM;
-       ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d",
+       ret = sprintf(buf, "%d: uart:%s %s%08llX irq:%d",
                        port->line, uart_type(port),
                        mmio ? "mmio:0x" : "port:",
-                       mmio ? port->mapbase : (unsigned long) port->iobase,
+                       mmio ? (unsigned long long)port->mapbase
+                            : (unsigned long long) port->iobase,
                        port->irq);
 
        if (port->type == PORT_UNKNOWN) {
@@ -1913,6 +1914,12 @@ uart_set_options(struct uart_port *port, struct console *co,
        if (flow == 'r')
                termios.c_cflag |= CRTSCTS;
 
+       /*
+        * some uarts on other side don't support no flow control.
+        * So we set * DTR in host uart to make them happy
+        */
+       port->mctrl |= TIOCM_DTR;
+
        port->ops->set_termios(port, &termios, NULL);
        co->cflag = termios.c_cflag;
 
@@ -2064,8 +2071,9 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
        case UPIO_MEM32:
        case UPIO_AU:
        case UPIO_TSI:
+       case UPIO_DWAPB:
                snprintf(address, sizeof(address),
-                        "MMIO 0x%lx", port->mapbase);
+                        "MMIO 0x%llx", (unsigned long long)port->mapbase);
                break;
        default:
                strlcpy(address, "*unknown*", sizeof(address));
@@ -2409,6 +2417,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
        case UPIO_MEM32:
        case UPIO_AU:
        case UPIO_TSI:
+       case UPIO_DWAPB:
                return (port1->mapbase == port2->mapbase);
        }
        return 0;