Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / serial / serial_core.c
index 17839e7..c59dcb7 100644 (file)
@@ -22,7 +22,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/slab.h>
  */
 static DEFINE_MUTEX(port_mutex);
 
+/*
+ * lockdep: port->lock is initialized in two places, but we
+ *          want only one lock-class:
+ */
+static struct lock_class_key port_lock_key;
+
 #define HIGH_BITS_OFFSET       ((sizeof(long)-sizeof(int))*8)
 
 #define uart_users(state)      ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
@@ -691,7 +696,8 @@ static int uart_set_info(struct uart_state *state,
                    (new_serial.baud_base != port->uartclk / 16) ||
                    (close_delay != state->close_delay) ||
                    (closing_wait != state->closing_wait) ||
-                   (new_serial.xmit_fifo_size != port->fifosize) ||
+                   (new_serial.xmit_fifo_size &&
+                    new_serial.xmit_fifo_size != port->fifosize) ||
                    (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
                        goto exit;
                port->flags = ((port->flags & ~UPF_USR_MASK) |
@@ -796,7 +802,8 @@ static int uart_set_info(struct uart_state *state,
        port->custom_divisor   = new_serial.custom_divisor;
        state->close_delay     = close_delay;
        state->closing_wait    = closing_wait;
-       port->fifosize         = new_serial.xmit_fifo_size;
+       if (new_serial.xmit_fifo_size)
+               port->fifosize = new_serial.xmit_fifo_size;
        if (state->info->tty)
                state->info->tty->low_latency =
                        (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
@@ -1866,6 +1873,7 @@ uart_set_options(struct uart_port *port, struct console *co,
         * early.
         */
        spin_lock_init(&port->lock);
+       lockdep_set_class(&port->lock, &port_lock_key);
 
        memset(&termios, 0, sizeof(struct termios));
 
@@ -1924,6 +1932,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);
@@ -1983,7 +1994,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;
 
@@ -1995,15 +2006,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);
@@ -2028,6 +2041,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
        case UPIO_MEM:
        case UPIO_MEM32:
        case UPIO_AU:
+       case UPIO_TSI:
                snprintf(address, sizeof(address),
                         "MMIO 0x%lx", port->mapbase);
                break;
@@ -2153,7 +2167,6 @@ int uart_register_driver(struct uart_driver *drv)
 
        normal->owner           = drv->owner;
        normal->driver_name     = drv->driver_name;
-       normal->devfs_name      = drv->devfs_name;
        normal->name            = drv->dev_name;
        normal->major           = drv->major;
        normal->minor_start     = drv->minor;
@@ -2161,7 +2174,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->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+       normal->flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        normal->driver_state    = drv;
        tty_set_operations(normal, &uart_ops);
 
@@ -2249,8 +2262,10 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
         * If this port is a console, then the spinlock is already
         * initialised.
         */
-       if (!(uart_console(port) && (port->cons->flags & CON_ENABLED)))
+       if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
                spin_lock_init(&port->lock);
+               lockdep_set_class(&port->lock, &port_lock_key);
+       }
 
        uart_configure_port(drv, state, port);
 
@@ -2312,7 +2327,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
        mutex_unlock(&state->mutex);
 
        /*
-        * Remove the devices from devfs
+        * Remove the devices from the tty layer
         */
        tty_unregister_device(drv->tty_driver, port->line);
 
@@ -2367,6 +2382,9 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
                return (port1->iobase == port2->iobase) &&
                       (port1->hub6   == port2->hub6);
        case UPIO_MEM:
+       case UPIO_MEM32:
+       case UPIO_AU:
+       case UPIO_TSI:
                return (port1->mapbase == port2->mapbase);
        }
        return 0;