[PATCH 20/61] SERIAL: Fix oops when removing suspended serial port

From: Chris Wright
Date: Wed Nov 01 2006 - 00:40:06 EST


-stable review patch. If anyone has any objections, please let us know.
------------------

From: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx>

[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@xxxxxxxxxxxxxxxx>
Signed-off-by: maximilian attems <maks@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
Signed-off-by: Chris Wright <chrisw@xxxxxxxxxxxx>

---
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;


--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/