Commit 91b32f54 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

serial: core: Fix port count when uart_open() errors

A port count mismatch occurs if mutex_lock_interruptible()
exits uart_open() and the port has already been opened. This may
prematurely close a port on an open tty. Since uart_close() is _always_
called if uart_open() fails, the port count must be corrected if errors
occur.

Always increment the port count in uart_open(), regardless of errors;
always decrement the port count in uart_close(). Note that
tty_port_close_start() decrements the port count when uart_open()
was successful.
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 64dbee31
...@@ -1338,8 +1338,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1338,8 +1338,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
struct uart_port *uport; struct uart_port *uport;
unsigned long flags; unsigned long flags;
if (!state) if (!state) {
struct uart_driver *drv = tty->driver->driver_state;
state = drv->state + tty->index;
port = &state->port;
spin_lock_irq(&port->lock);
--port->count;
spin_unlock_irq(&port->lock);
return; return;
}
uport = state->uart_port; uport = state->uart_port;
port = &state->port; port = &state->port;
...@@ -1556,6 +1564,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp) ...@@ -1556,6 +1564,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
pr_debug("uart_open(%d) called\n", line); pr_debug("uart_open(%d) called\n", line);
spin_lock_irq(&port->lock);
++port->count;
spin_unlock_irq(&port->lock);
/* /*
* We take the semaphore here to guarantee that we won't be re-entered * We take the semaphore here to guarantee that we won't be re-entered
* while allocating the state structure, or while we request any IRQs * while allocating the state structure, or while we request any IRQs
...@@ -1568,17 +1580,11 @@ static int uart_open(struct tty_struct *tty, struct file *filp) ...@@ -1568,17 +1580,11 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
goto end; goto end;
} }
port->count++;
if (!state->uart_port || state->uart_port->flags & UPF_DEAD) { if (!state->uart_port || state->uart_port->flags & UPF_DEAD) {
retval = -ENXIO; retval = -ENXIO;
goto err_dec_count; goto err_unlock;
} }
/*
* Once we set tty->driver_data here, we are guaranteed that
* uart_close() will decrement the driver module use count.
* Any failures from here onwards should not touch the count.
*/
tty->driver_data = state; tty->driver_data = state;
state->uart_port->state = state; state->uart_port->state = state;
state->port.low_latency = state->port.low_latency =
...@@ -1599,8 +1605,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) ...@@ -1599,8 +1605,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
end: end:
return retval; return retval;
err_dec_count: err_unlock:
port->count--;
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
goto end; goto end;
} }
......
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