diff options
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 22 |
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) |