aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2014-09-10 15:06:24 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-09-24 00:19:35 -0400
commit299245a145b2ad4cfb4c5432eb1264299f55e7e0 (patch)
tree53eb54bc7cf744f3813c34c79769529d0df6c223 /drivers/tty
parent4d90bb147ef6b91f529a21b498ff2b5fdc6785b4 (diff)
serial: core: Privatize modem status enable flags
The serial core uses the tty port flags, ASYNC_CTS_FLOW and ASYNC_CD_CHECK, to track whether CTS and DCD changes should be ignored or handled. However, the tty port flags are not safe for atomic bit operations and no lock provides serialized updates. Introduce the struct uart_port status field to track CTS and DCD enable states, and serialize access with uart port lock. Substitute uart_cts_enabled() helper for tty_port_cts_enabled(). 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/mxs-auart.c2
-rw-r--r--drivers/tty/serial/serial_core.c29
2 files changed, 18 insertions, 13 deletions
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index b5c329248c81..10c29334fe2f 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -408,7 +408,7 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
408 408
409 ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); 409 ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
410 if (mctrl & TIOCM_RTS) { 410 if (mctrl & TIOCM_RTS) {
411 if (tty_port_cts_enabled(&u->state->port)) 411 if (uart_cts_enabled(u))
412 ctrl |= AUART_CTRL2_RTSEN; 412 ctrl |= AUART_CTRL2_RTSEN;
413 else 413 else
414 ctrl |= AUART_CTRL2_RTS; 414 ctrl |= AUART_CTRL2_RTS;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index f764de32b658..dd21ed900635 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -59,6 +59,11 @@ static void uart_change_pm(struct uart_state *state,
59 59
60static void uart_port_shutdown(struct tty_port *port); 60static void uart_port_shutdown(struct tty_port *port);
61 61
62static int uart_dcd_enabled(struct uart_port *uport)
63{
64 return uport->status & UPSTAT_DCD_ENABLE;
65}
66
62/* 67/*
63 * This routine is used by the interrupt handler to schedule processing in 68 * This routine is used by the interrupt handler to schedule processing in
64 * the software interrupt portion of the driver. 69 * the software interrupt portion of the driver.
@@ -130,7 +135,6 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
130 int init_hw) 135 int init_hw)
131{ 136{
132 struct uart_port *uport = state->uart_port; 137 struct uart_port *uport = state->uart_port;
133 struct tty_port *port = &state->port;
134 unsigned long page; 138 unsigned long page;
135 int retval = 0; 139 int retval = 0;
136 140
@@ -176,12 +180,12 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
176 uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); 180 uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
177 } 181 }
178 182
179 if (tty_port_cts_enabled(port)) { 183 spin_lock_irq(&uport->lock);
180 spin_lock_irq(&uport->lock); 184 if (uart_cts_enabled(uport)) {
181 if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) 185 if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
182 tty->hw_stopped = 1; 186 tty->hw_stopped = 1;
183 spin_unlock_irq(&uport->lock);
184 } 187 }
188 spin_unlock_irq(&uport->lock);
185 } 189 }
186 190
187 /* 191 /*
@@ -435,7 +439,6 @@ EXPORT_SYMBOL(uart_get_divisor);
435static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, 439static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
436 struct ktermios *old_termios) 440 struct ktermios *old_termios)
437{ 441{
438 struct tty_port *port = &state->port;
439 struct uart_port *uport = state->uart_port; 442 struct uart_port *uport = state->uart_port;
440 struct ktermios *termios; 443 struct ktermios *termios;
441 444
@@ -450,17 +453,19 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
450 uport->ops->set_termios(uport, termios, old_termios); 453 uport->ops->set_termios(uport, termios, old_termios);
451 454
452 /* 455 /*
453 * Set flags based on termios cflag 456 * Set modem status enables based on termios cflag
454 */ 457 */
458 spin_lock_irq(&uport->lock);
455 if (termios->c_cflag & CRTSCTS) 459 if (termios->c_cflag & CRTSCTS)
456 set_bit(ASYNCB_CTS_FLOW, &port->flags); 460 uport->status |= UPSTAT_CTS_ENABLE;
457 else 461 else
458 clear_bit(ASYNCB_CTS_FLOW, &port->flags); 462 uport->status &= ~UPSTAT_CTS_ENABLE;
459 463
460 if (termios->c_cflag & CLOCAL) 464 if (termios->c_cflag & CLOCAL)
461 clear_bit(ASYNCB_CHECK_CD, &port->flags); 465 uport->status &= ~UPSTAT_DCD_ENABLE;
462 else 466 else
463 set_bit(ASYNCB_CHECK_CD, &port->flags); 467 uport->status |= UPSTAT_DCD_ENABLE;
468 spin_unlock_irq(&uport->lock);
464} 469}
465 470
466static inline int __uart_put_char(struct uart_port *port, 471static inline int __uart_put_char(struct uart_port *port,
@@ -2765,7 +2770,7 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status)
2765 2770
2766 uport->icount.dcd++; 2771 uport->icount.dcd++;
2767 2772
2768 if (port->flags & ASYNC_CHECK_CD) { 2773 if (uart_dcd_enabled(uport)) {
2769 if (status) 2774 if (status)
2770 wake_up_interruptible(&port->open_wait); 2775 wake_up_interruptible(&port->open_wait);
2771 else if (tty) 2776 else if (tty)
@@ -2790,7 +2795,7 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status)
2790 2795
2791 uport->icount.cts++; 2796 uport->icount.cts++;
2792 2797
2793 if (tty_port_cts_enabled(port)) { 2798 if (uart_cts_enabled(uport)) {
2794 if (tty->hw_stopped) { 2799 if (tty->hw_stopped) {
2795 if (status) { 2800 if (status) {
2796 tty->hw_stopped = 0; 2801 tty->hw_stopped = 0;