[PATCH] serial core: work around sub-driver bugs
authorPavel Machek <pavel@ucw.cz>
Wed, 8 Mar 2006 05:55:20 +0000 (21:55 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 8 Mar 2006 22:14:00 +0000 (14:14 -0800)
We're presently getting oopses because Bluetooth (and possibly other) drivers
are calling core functions after things have been shut down.

So rather than oopsing, let's drop a warning then take avoiding action, so the
machine survives.  Once all the sub-drivers are fixed up we can remove the
take-avoiding-action part.

Signed-off-by: Pavel Machek <pavel@suse.cz>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/serial/serial_core.c

index 95fb493..cc1faa3 100644 (file)
@@ -71,6 +71,11 @@ static void uart_change_pm(struct uart_state *state, int pm_state);
 void uart_write_wakeup(struct uart_port *port)
 {
        struct uart_info *info = port->info;
+       /*
+        * This means you called this function _after_ the port was
+        * closed.  No cookie for you.
+        */
+       BUG_ON(!info);
        tasklet_schedule(&info->tlet);
 }
 
@@ -471,14 +476,26 @@ static void uart_flush_chars(struct tty_struct *tty)
 }
 
 static int
-uart_write(struct tty_struct *tty, const unsigned char * buf, int count)
+uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
        struct uart_state *state = tty->driver_data;
-       struct uart_port *port = state->port;
-       struct circ_buf *circ = &state->info->xmit;
+       struct uart_port *port;
+       struct circ_buf *circ;
        unsigned long flags;
        int c, ret = 0;
 
+       /*
+        * This means you called this function _after_ the port was
+        * closed.  No cookie for you.
+        */
+       if (!state || !state->info) {
+               WARN_ON(1);
+               return -EL3HLT;
+       }
+
+       port = state->port;
+       circ = &state->info->xmit;
+
        if (!circ->buf)
                return 0;
 
@@ -521,6 +538,15 @@ static void uart_flush_buffer(struct tty_struct *tty)
        struct uart_port *port = state->port;
        unsigned long flags;
 
+       /*
+        * This means you called this function _after_ the port was
+        * closed.  No cookie for you.
+        */
+       if (!state || !state->info) {
+               WARN_ON(1);
+               return;
+       }
+
        DPRINTK("uart_flush_buffer(%d) called\n", tty->index);
 
        spin_lock_irqsave(&port->lock, flags);