diff options
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9c14a453f73c..80bb56facfb6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -182,6 +182,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, { struct uart_port *uport = uart_port_check(state); unsigned long page; + unsigned long flags = 0; int retval = 0; if (uport->type == PORT_UNKNOWN) @@ -196,15 +197,18 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, * Initialise and allocate the transmit and temporary * buffer. */ - if (!state->xmit.buf) { - /* This is protected by the per port mutex */ - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + uart_port_lock(state, flags); + if (!state->xmit.buf) { state->xmit.buf = (unsigned char *) page; uart_circ_clear(&state->xmit); + } else { + free_page(page); } + uart_port_unlock(uport, flags); retval = uport->ops->startup(uport); if (retval == 0) { @@ -263,6 +267,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) { struct uart_port *uport = uart_port_check(state); struct tty_port *port = &state->port; + unsigned long flags = 0; /* * Set the TTY IO error marker @@ -295,10 +300,12 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) /* * Free the transmit buffer page. */ + uart_port_lock(state, flags); if (state->xmit.buf) { free_page((unsigned long)state->xmit.buf); state->xmit.buf = NULL; } + uart_port_unlock(uport, flags); } /** |