diff options
author | Pavel Machek <pavel@ucw.cz> | 2006-03-07 21:55:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-08 14:14:00 -0800 |
commit | d5f735e52fb41e032b0db08aa20c02dbb9cd0db3 (patch) | |
tree | 901eb8df0c58c1776dda88e91b997e6c0d39b48c | |
parent | 1c6cc5fd32978ffdc4d0acf8592d3901adefbdad (diff) | |
download | op-kernel-dev-d5f735e52fb41e032b0db08aa20c02dbb9cd0db3.zip op-kernel-dev-d5f735e52fb41e032b0db08aa20c02dbb9cd0db3.tar.gz |
[PATCH] serial core: work around sub-driver bugs
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>
-rw-r--r-- | drivers/serial/serial_core.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 95fb493..cc1faa3 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -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); |