Commit 4d496dde authored by Russell King's avatar Russell King Committed by Chris Wright

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

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarmaximilian attems <maks@sternwelten.at>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarChris Wright <chrisw@sous-sol.org>
parent 9b1bb2cd
...@@ -1932,6 +1932,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) ...@@ -1932,6 +1932,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
if (state->info && state->info->flags & UIF_INITIALIZED) { if (state->info && state->info->flags & UIF_INITIALIZED) {
const struct uart_ops *ops = port->ops; const struct uart_ops *ops = port->ops;
state->info->flags = (state->info->flags & ~UIF_INITIALIZED)
| UIF_SUSPENDED;
spin_lock_irq(&port->lock); spin_lock_irq(&port->lock);
ops->stop_tx(port); ops->stop_tx(port);
ops->set_mctrl(port, 0); ops->set_mctrl(port, 0);
...@@ -1991,7 +1994,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) ...@@ -1991,7 +1994,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
console_start(port->cons); 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; const struct uart_ops *ops = port->ops;
int ret; int ret;
...@@ -2003,15 +2006,17 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) ...@@ -2003,15 +2006,17 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
ops->set_mctrl(port, port->mctrl); ops->set_mctrl(port, port->mctrl);
ops->start_tx(port); ops->start_tx(port);
spin_unlock_irq(&port->lock); spin_unlock_irq(&port->lock);
state->info->flags |= UIF_INITIALIZED;
} else { } else {
/* /*
* Failed to resume - maybe hardware went away? * Failed to resume - maybe hardware went away?
* Clear the "initialized" flag so we won't try * Clear the "initialized" flag so we won't try
* to call the low level drivers shutdown method. * to call the low level drivers shutdown method.
*/ */
state->info->flags &= ~UIF_INITIALIZED;
uart_shutdown(state); uart_shutdown(state);
} }
state->info->flags &= ~UIF_SUSPENDED;
} }
mutex_unlock(&state->mutex); mutex_unlock(&state->mutex);
......
...@@ -319,6 +319,7 @@ struct uart_info { ...@@ -319,6 +319,7 @@ struct uart_info {
#define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) #define UIF_CTS_FLOW ((__force uif_t) (1 << 26))
#define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29))
#define UIF_INITIALIZED ((__force uif_t) (1 << 31)) #define UIF_INITIALIZED ((__force uif_t) (1 << 31))
#define UIF_SUSPENDED ((__force uif_t) (1 << 30))
int blocked_open; int blocked_open;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment