| From stable-bounces@linux.kernel.org Tue Oct 17 04:27:39 2006 |
| Date: Tue, 17 Oct 2006 13:26:34 +0200 |
| From: Russell King <rmk+kernel@arm.linux.org.uk> |
| To: stable@kernel.org |
| Message-ID: <20061017112634.GD24505@nancy> |
| MIME-Version: 1.0 |
| Content-Disposition: inline |
| Subject: SERIAL: Fix oops when removing suspended serial port |
| Content-Type: text/plain; charset="us-ascii" |
| |
| From: Russell King <rmk+kernel@arm.linux.org.uk> |
| |
| [SERIAL] Fix oops when removing suspended serial port |
| |
| A serial card might have been removed when the system is resumed. |
| This results in a suspended port being shut down, which results in |
| the ports shutdown method being called twice in a row. This causes |
| BUGs. Avoid this by tracking the suspended state separately from |
| the initialised state. |
| |
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> |
| Signed-off-by: maximilian attems <maks@sternwelten.at> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
| |
| --- |
| drivers/serial/serial_core.c | 9 +++++++-- |
| include/linux/serial_core.h | 1 + |
| 2 files changed, 8 insertions(+), 2 deletions(-) |
| |
| --- linux-2.6.18.1.orig/drivers/serial/serial_core.c |
| +++ linux-2.6.18.1/drivers/serial/serial_core.c |
| @@ -1932,6 +1932,9 @@ int uart_suspend_port(struct uart_driver |
| 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); |
| @@ -1991,7 +1994,7 @@ int uart_resume_port(struct uart_driver |
| 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; |
| |
| @@ -2003,15 +2006,17 @@ int uart_resume_port(struct uart_driver |
| 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); |
| --- linux-2.6.18.1.orig/include/linux/serial_core.h |
| +++ linux-2.6.18.1/include/linux/serial_core.h |
| @@ -319,6 +319,7 @@ struct uart_info { |
| #define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) |
| #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) |
| #define UIF_INITIALIZED ((__force uif_t) (1 << 31)) |
| +#define UIF_SUSPENDED ((__force uif_t) (1 << 30)) |
| |
| int blocked_open; |
| |