aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/serial_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r--drivers/tty/serial/serial_core.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 6bc20d7..65db939 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -91,6 +91,9 @@ static void __uart_start(struct tty_struct *tty)
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
+ if (port->ops->wake_peer)
+ port->ops->wake_peer(port);
+
if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&
!tty->stopped && !tty->hw_stopped)
port->ops->start_tx(port);
@@ -159,13 +162,17 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
* buffer.
*/
if (!state->xmit.buf) {
+ unsigned long flags;
+
/* This is protected by the per port mutex */
page = get_zeroed_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
+ spin_lock_irqsave(&uport->lock, flags);
state->xmit.buf = (unsigned char *) page;
uart_circ_clear(&state->xmit);
+ spin_unlock_irqrestore(&uport->lock, flags);
}
retval = uport->ops->startup(uport);
@@ -258,8 +265,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
* Free the transmit buffer page.
*/
if (state->xmit.buf) {
+ unsigned long flags;
+ spin_lock_irqsave(&uport->lock, flags);
free_page((unsigned long)state->xmit.buf);
state->xmit.buf = NULL;
+ spin_unlock_irqrestore(&uport->lock, flags);
}
}
@@ -468,10 +478,12 @@ static inline int __uart_put_char(struct uart_port *port,
unsigned long flags;
int ret = 0;
- if (!circ->buf)
+ spin_lock_irqsave(&port->lock, flags);
+ if (!circ->buf) {
+ spin_unlock_irqrestore(&port->lock, flags);
return 0;
+ }
- spin_lock_irqsave(&port->lock, flags);
if (uart_circ_chars_free(circ) != 0) {
circ->buf[circ->head] = c;
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -514,10 +526,12 @@ static int uart_write(struct tty_struct *tty,
port = state->uart_port;
circ = &state->xmit;
- if (!circ->buf)
+ spin_lock_irqsave(&port->lock, flags);
+ if (!circ->buf) {
+ spin_unlock_irqrestore(&port->lock, flags);
return 0;
+ }
- spin_lock_irqsave(&port->lock, flags);
while (1) {
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
if (count < c)