aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/serial_core.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-10-01 12:17:40 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-10-01 12:17:40 -0400
commita6b93a908508810c5d51dd9b390283345af6f2d9 (patch)
tree71b48d3a659a025ebf333abfeec7b828becb60cb /drivers/serial/serial_core.c
parentfe59d5372ae719ca4550958f1e5bb4dd6eeac9cd (diff)
[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>
Diffstat (limited to 'drivers/serial/serial_core.c')
-rw-r--r--drivers/serial/serial_core.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index d814bb1dcb0..397147a7054 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1940,6 +1940,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
1940 if (state->info && state->info->flags & UIF_INITIALIZED) { 1940 if (state->info && state->info->flags & UIF_INITIALIZED) {
1941 const struct uart_ops *ops = port->ops; 1941 const struct uart_ops *ops = port->ops;
1942 1942
1943 state->info->flags = (state->info->flags & ~UIF_INITIALIZED)
1944 | UIF_SUSPENDED;
1945
1943 spin_lock_irq(&port->lock); 1946 spin_lock_irq(&port->lock);
1944 ops->stop_tx(port); 1947 ops->stop_tx(port);
1945 ops->set_mctrl(port, 0); 1948 ops->set_mctrl(port, 0);
@@ -2006,7 +2009,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
2006 console_start(port->cons); 2009 console_start(port->cons);
2007 } 2010 }
2008 2011
2009 if (state->info && state->info->flags & UIF_INITIALIZED) { 2012 if (state->info && state->info->flags & UIF_SUSPENDED) {
2010 const struct uart_ops *ops = port->ops; 2013 const struct uart_ops *ops = port->ops;
2011 int ret; 2014 int ret;
2012 2015
@@ -2018,15 +2021,17 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
2018 ops->set_mctrl(port, port->mctrl); 2021 ops->set_mctrl(port, port->mctrl);
2019 ops->start_tx(port); 2022 ops->start_tx(port);
2020 spin_unlock_irq(&port->lock); 2023 spin_unlock_irq(&port->lock);
2024 state->info->flags |= UIF_INITIALIZED;
2021 } else { 2025 } else {
2022 /* 2026 /*
2023 * Failed to resume - maybe hardware went away? 2027 * Failed to resume - maybe hardware went away?
2024 * Clear the "initialized" flag so we won't try 2028 * Clear the "initialized" flag so we won't try
2025 * to call the low level drivers shutdown method. 2029 * to call the low level drivers shutdown method.
2026 */ 2030 */
2027 state->info->flags &= ~UIF_INITIALIZED;
2028 uart_shutdown(state); 2031 uart_shutdown(state);
2029 } 2032 }
2033
2034 state->info->flags &= ~UIF_SUSPENDED;
2030 } 2035 }
2031 2036
2032 mutex_unlock(&state->mutex); 2037 mutex_unlock(&state->mutex);