diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2014-09-10 15:06:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-23 21:19:35 -0700 |
commit | d01f4d181c92877ecc678adce248a30cb7077ff1 (patch) | |
tree | f4b9a5723be98e63e2b238f8290fd418179a238a /drivers/tty | |
parent | 317c1360200059a7a8a832294a58409c73b784bf (diff) | |
download | talos-obmc-linux-d01f4d181c92877ecc678adce248a30cb7077ff1.tar.gz talos-obmc-linux-d01f4d181c92877ecc678adce248a30cb7077ff1.zip |
serial: core: Privatize tty->hw_stopped
tty->hw_stopped is not used by the tty core and is thread-unsafe;
hw_stopped is a member of a bitfield whose fields are updated
non-atomically and no lock is suitable for serializing updates.
Replace serial core usage of tty->hw_stopped with uport->hw_stopped.
Use int storage which works around Alpha EV4/5 non-atomic byte storage,
since uart_port uses different locks to protect certain fields within the
structure.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/bfin_uart.c | 14 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 28 |
2 files changed, 20 insertions, 22 deletions
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index dec0fd725d80..fc9fbf3f24a7 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -108,22 +108,22 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; - unsigned int status = bfin_serial_get_mctrl(&uart->port); + struct uart_port *uport = &uart->port; + unsigned int status = bfin_serial_get_mctrl(uport); #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS - struct tty_struct *tty = uart->port.state->port.tty; UART_CLEAR_SCTS(uart); - if (tty->hw_stopped) { + if (uport->hw_stopped) { if (status) { - tty->hw_stopped = 0; - uart_write_wakeup(&uart->port); + uport->hw_stopped = 0; + uart_write_wakeup(uport); } } else { if (!status) - tty->hw_stopped = 1; + uport->hw_stopped = 1; } #endif - uart_handle_cts_change(&uart->port, status & TIOCM_CTS); + uart_handle_cts_change(uport, status & TIOCM_CTS); return IRQ_HANDLED; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index dd21ed900635..7d51e26627fb 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -95,7 +95,7 @@ static void __uart_start(struct tty_struct *tty) struct uart_state *state = tty->driver_data; struct uart_port *port = state->uart_port; - if (!tty->stopped && !tty->hw_stopped) + if (!uart_tx_stopped(port)) port->ops->start_tx(port); } @@ -181,10 +181,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, } spin_lock_irq(&uport->lock); - if (uart_cts_enabled(uport)) { - if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) - tty->hw_stopped = 1; - } + if (uart_cts_enabled(uport) && + !(uport->ops->get_mctrl(uport) & TIOCM_CTS)) + uport->hw_stopped = 1; + else + uport->hw_stopped = 0; spin_unlock_irq(&uport->lock); } @@ -949,7 +950,7 @@ static int uart_get_lsr_info(struct tty_struct *tty, */ if (uport->x_char || ((uart_circ_chars_pending(&state->xmit) > 0) && - !tty->stopped && !tty->hw_stopped)) + !uart_tx_stopped(uport))) result &= ~TIOCSER_TEMT; return put_user(result, value); @@ -1295,7 +1296,7 @@ static void uart_set_termios(struct tty_struct *tty, /* * If the port is doing h/w assisted flow control, do nothing. - * We assume that tty->hw_stopped has never been set. + * We assume that port->hw_stopped has never been set. */ if (uport->flags & UPF_HARD_FLOW) return; @@ -1303,7 +1304,7 @@ static void uart_set_termios(struct tty_struct *tty, /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { spin_lock_irqsave(&uport->lock, flags); - tty->hw_stopped = 0; + uport->hw_stopped = 0; __uart_start(tty); spin_unlock_irqrestore(&uport->lock, flags); } @@ -1311,7 +1312,7 @@ static void uart_set_termios(struct tty_struct *tty, else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { spin_lock_irqsave(&uport->lock, flags); if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) { - tty->hw_stopped = 1; + uport->hw_stopped = 1; uport->ops->stop_tx(uport); } spin_unlock_irqrestore(&uport->lock, flags); @@ -2788,23 +2789,20 @@ EXPORT_SYMBOL_GPL(uart_handle_dcd_change); */ void uart_handle_cts_change(struct uart_port *uport, unsigned int status) { - struct tty_port *port = &uport->state->port; - struct tty_struct *tty = port->tty; - lockdep_assert_held_once(&uport->lock); uport->icount.cts++; if (uart_cts_enabled(uport)) { - if (tty->hw_stopped) { + if (uport->hw_stopped) { if (status) { - tty->hw_stopped = 0; + uport->hw_stopped = 0; uport->ops->start_tx(uport); uart_write_wakeup(uport); } } else { if (!status) { - tty->hw_stopped = 1; + uport->hw_stopped = 1; uport->ops->stop_tx(uport); } } |