diff options
author | Alan Cox <alan@linux.intel.com> | 2010-06-01 16:52:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 16:47:41 -0400 |
commit | 192251352f912bccfb942ea35801d2357f11f592 (patch) | |
tree | bd6215250edc64b9c5844455cdfcd800ea395b16 /drivers/serial | |
parent | a360fae67bc173942f620d44d1b23cfb5ccaaf96 (diff) |
tty: serial - fix various misuses/mishandlings of port->tty
Make it robust against hang up events. In most cases we can do this simply
by passing the right things in the first place.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/serial_core.c | 109 |
1 files changed, 60 insertions, 49 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 7f2830709512..12ee7e0f99ce 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -58,7 +58,7 @@ static struct lock_class_key port_lock_key; | |||
58 | #define uart_console(port) (0) | 58 | #define uart_console(port) (0) |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static void uart_change_speed(struct uart_state *state, | 61 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
62 | struct ktermios *old_termios); | 62 | struct ktermios *old_termios); |
63 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 63 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
64 | static void uart_change_pm(struct uart_state *state, int pm_state); | 64 | static void uart_change_pm(struct uart_state *state, int pm_state); |
@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
137 | * Startup the port. This will be called once per open. All calls | 137 | * Startup the port. This will be called once per open. All calls |
138 | * will be serialised by the per-port mutex. | 138 | * will be serialised by the per-port mutex. |
139 | */ | 139 | */ |
140 | static int uart_startup(struct uart_state *state, int init_hw) | 140 | static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) |
141 | { | 141 | { |
142 | struct uart_port *uport = state->uart_port; | 142 | struct uart_port *uport = state->uart_port; |
143 | struct tty_port *port = &state->port; | 143 | struct tty_port *port = &state->port; |
@@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
152 | * once we have successfully opened the port. Also set | 152 | * once we have successfully opened the port. Also set |
153 | * up the tty->alt_speed kludge | 153 | * up the tty->alt_speed kludge |
154 | */ | 154 | */ |
155 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 155 | set_bit(TTY_IO_ERROR, &tty->flags); |
156 | 156 | ||
157 | if (uport->type == PORT_UNKNOWN) | 157 | if (uport->type == PORT_UNKNOWN) |
158 | return 0; | 158 | return 0; |
@@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
177 | /* | 177 | /* |
178 | * Initialise the hardware port settings. | 178 | * Initialise the hardware port settings. |
179 | */ | 179 | */ |
180 | uart_change_speed(state, NULL); | 180 | uart_change_speed(tty, state, NULL); |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * Setup the RTS and DTR signals once the | 183 | * Setup the RTS and DTR signals once the |
184 | * port is open and ready to respond. | 184 | * port is open and ready to respond. |
185 | */ | 185 | */ |
186 | if (port->tty->termios->c_cflag & CBAUD) | 186 | if (tty->termios->c_cflag & CBAUD) |
187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); | 187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
188 | } | 188 | } |
189 | 189 | ||
190 | if (port->flags & ASYNC_CTS_FLOW) { | 190 | if (port->flags & ASYNC_CTS_FLOW) { |
191 | spin_lock_irq(&uport->lock); | 191 | spin_lock_irq(&uport->lock); |
192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) | 192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) |
193 | port->tty->hw_stopped = 1; | 193 | tty->hw_stopped = 1; |
194 | spin_unlock_irq(&uport->lock); | 194 | spin_unlock_irq(&uport->lock); |
195 | } | 195 | } |
196 | 196 | ||
197 | set_bit(ASYNCB_INITIALIZED, &port->flags); | 197 | set_bit(ASYNCB_INITIALIZED, &port->flags); |
198 | 198 | ||
199 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 199 | clear_bit(TTY_IO_ERROR, &tty->flags); |
200 | } | 200 | } |
201 | 201 | ||
202 | if (retval && capable(CAP_SYS_ADMIN)) | 202 | if (retval && capable(CAP_SYS_ADMIN)) |
@@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
210 | * DTR is dropped if the hangup on close termio flag is on. Calls to | 210 | * DTR is dropped if the hangup on close termio flag is on. Calls to |
211 | * uart_shutdown are serialised by the per-port semaphore. | 211 | * uart_shutdown are serialised by the per-port semaphore. |
212 | */ | 212 | */ |
213 | static void uart_shutdown(struct uart_state *state) | 213 | static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) |
214 | { | 214 | { |
215 | struct uart_port *uport = state->uart_port; | 215 | struct uart_port *uport = state->uart_port; |
216 | struct tty_port *port = &state->port; | 216 | struct tty_port *port = &state->port; |
217 | struct tty_struct *tty = port->tty; | ||
218 | 217 | ||
219 | /* | 218 | /* |
220 | * Set the TTY IO error marker | 219 | * Set the TTY IO error marker |
@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) | |||
430 | EXPORT_SYMBOL(uart_get_divisor); | 429 | EXPORT_SYMBOL(uart_get_divisor); |
431 | 430 | ||
432 | /* FIXME: Consistent locking policy */ | 431 | /* FIXME: Consistent locking policy */ |
433 | static void | 432 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
434 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 433 | struct ktermios *old_termios) |
435 | { | 434 | { |
436 | struct tty_port *port = &state->port; | 435 | struct tty_port *port = &state->port; |
437 | struct tty_struct *tty = port->tty; | ||
438 | struct uart_port *uport = state->uart_port; | 436 | struct uart_port *uport = state->uart_port; |
439 | struct ktermios *termios; | 437 | struct ktermios *termios; |
440 | 438 | ||
@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | |||
463 | uport->ops->set_termios(uport, termios, old_termios); | 461 | uport->ops->set_termios(uport, termios, old_termios); |
464 | } | 462 | } |
465 | 463 | ||
466 | static inline int | 464 | static inline int __uart_put_char(struct uart_port *port, |
467 | __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) | 465 | struct circ_buf *circ, unsigned char c) |
468 | { | 466 | { |
469 | unsigned long flags; | 467 | unsigned long flags; |
470 | int ret = 0; | 468 | int ret = 0; |
@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty) | |||
494 | uart_start(tty); | 492 | uart_start(tty); |
495 | } | 493 | } |
496 | 494 | ||
497 | static int | 495 | static int uart_write(struct tty_struct *tty, |
498 | uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | 496 | const unsigned char *buf, int count) |
499 | { | 497 | { |
500 | struct uart_state *state = tty->driver_data; | 498 | struct uart_state *state = tty->driver_data; |
501 | struct uart_port *port; | 499 | struct uart_port *port; |
@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state, | |||
675 | return 0; | 673 | return 0; |
676 | } | 674 | } |
677 | 675 | ||
678 | static int uart_set_info(struct uart_state *state, | 676 | static int uart_set_info(struct tty_struct *tty, struct uart_state *state, |
679 | struct serial_struct __user *newinfo) | 677 | struct serial_struct __user *newinfo) |
680 | { | 678 | { |
681 | struct serial_struct new_serial; | 679 | struct serial_struct new_serial; |
@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state, | |||
770 | * We need to shutdown the serial port at the old | 768 | * We need to shutdown the serial port at the old |
771 | * port/type/irq combination. | 769 | * port/type/irq combination. |
772 | */ | 770 | */ |
773 | uart_shutdown(state); | 771 | uart_shutdown(tty, state); |
774 | } | 772 | } |
775 | 773 | ||
776 | if (change_port) { | 774 | if (change_port) { |
@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state, | |||
869 | "is deprecated.\n", current->comm, | 867 | "is deprecated.\n", current->comm, |
870 | tty_name(port->tty, buf)); | 868 | tty_name(port->tty, buf)); |
871 | } | 869 | } |
872 | uart_change_speed(state, NULL); | 870 | uart_change_speed(tty, state, NULL); |
873 | } | 871 | } |
874 | } else | 872 | } else |
875 | retval = uart_startup(state, 1); | 873 | retval = uart_startup(tty, state, 1); |
876 | exit: | 874 | exit: |
877 | mutex_unlock(&port->mutex); | 875 | mutex_unlock(&port->mutex); |
878 | return retval; | 876 | return retval; |
879 | } | 877 | } |
880 | 878 | ||
881 | 879 | /** | |
882 | /* | 880 | * uart_get_lsr_info - get line status register info |
883 | * uart_get_lsr_info - get line status register info. | 881 | * @tty: tty associated with the UART |
884 | * Note: uart_ioctl protects us against hangups. | 882 | * @state: UART being queried |
883 | * @value: returned modem value | ||
884 | * | ||
885 | * Note: uart_ioctl protects us against hangups. | ||
885 | */ | 886 | */ |
886 | static int uart_get_lsr_info(struct uart_state *state, | 887 | static int uart_get_lsr_info(struct tty_struct *tty, |
887 | unsigned int __user *value) | 888 | struct uart_state *state, unsigned int __user *value) |
888 | { | 889 | { |
889 | struct uart_port *uport = state->uart_port; | 890 | struct uart_port *uport = state->uart_port; |
890 | struct tty_port *port = &state->port; | ||
891 | unsigned int result; | 891 | unsigned int result; |
892 | 892 | ||
893 | result = uport->ops->tx_empty(uport); | 893 | result = uport->ops->tx_empty(uport); |
@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
900 | */ | 900 | */ |
901 | if (uport->x_char || | 901 | if (uport->x_char || |
902 | ((uart_circ_chars_pending(&state->xmit) > 0) && | 902 | ((uart_circ_chars_pending(&state->xmit) > 0) && |
903 | !port->tty->stopped && !port->tty->hw_stopped)) | 903 | !tty->stopped && !tty->hw_stopped)) |
904 | result &= ~TIOCSER_TEMT; | 904 | result &= ~TIOCSER_TEMT; |
905 | 905 | ||
906 | return put_user(result, value); | 906 | return put_user(result, value); |
@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) | |||
961 | return 0; | 961 | return 0; |
962 | } | 962 | } |
963 | 963 | ||
964 | static int uart_do_autoconfig(struct uart_state *state) | 964 | static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) |
965 | { | 965 | { |
966 | struct uart_port *uport = state->uart_port; | 966 | struct uart_port *uport = state->uart_port; |
967 | struct tty_port *port = &state->port; | 967 | struct tty_port *port = &state->port; |
@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
980 | 980 | ||
981 | ret = -EBUSY; | 981 | ret = -EBUSY; |
982 | if (tty_port_users(port) == 1) { | 982 | if (tty_port_users(port) == 1) { |
983 | uart_shutdown(state); | 983 | uart_shutdown(tty, state); |
984 | 984 | ||
985 | /* | 985 | /* |
986 | * If we already have a port type configured, | 986 | * If we already have a port type configured, |
@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
999 | */ | 999 | */ |
1000 | uport->ops->config_port(uport, flags); | 1000 | uport->ops->config_port(uport, flags); |
1001 | 1001 | ||
1002 | ret = uart_startup(state, 1); | 1002 | ret = uart_startup(tty, state, 1); |
1003 | } | 1003 | } |
1004 | mutex_unlock(&port->mutex); | 1004 | mutex_unlock(&port->mutex); |
1005 | return ret; | 1005 | return ret; |
@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1122 | break; | 1122 | break; |
1123 | 1123 | ||
1124 | case TIOCSSERIAL: | 1124 | case TIOCSSERIAL: |
1125 | ret = uart_set_info(state, uarg); | 1125 | ret = uart_set_info(tty, state, uarg); |
1126 | break; | 1126 | break; |
1127 | 1127 | ||
1128 | case TIOCSERCONFIG: | 1128 | case TIOCSERCONFIG: |
1129 | ret = uart_do_autoconfig(state); | 1129 | ret = uart_do_autoconfig(tty, state); |
1130 | break; | 1130 | break; |
1131 | 1131 | ||
1132 | case TIOCSERGWILD: /* obsolete */ | 1132 | case TIOCSERGWILD: /* obsolete */ |
@@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1172 | */ | 1172 | */ |
1173 | switch (cmd) { | 1173 | switch (cmd) { |
1174 | case TIOCSERGETLSR: /* Get line status register */ | 1174 | case TIOCSERGETLSR: /* Get line status register */ |
1175 | ret = uart_get_lsr_info(state, uarg); | 1175 | ret = uart_get_lsr_info(tty, state, uarg); |
1176 | break; | 1176 | break; |
1177 | 1177 | ||
1178 | default: { | 1178 | default: { |
@@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1219 | return; | 1219 | return; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | uart_change_speed(state, old_termios); | 1222 | uart_change_speed(tty, state, old_termios); |
1223 | 1223 | ||
1224 | /* Handle transition to B0 status */ | 1224 | /* Handle transition to B0 status */ |
1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
@@ -1335,7 +1335,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1335 | uart_wait_until_sent(tty, uport->timeout); | 1335 | uart_wait_until_sent(tty, uport->timeout); |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | uart_shutdown(state); | 1338 | uart_shutdown(tty, state); |
1339 | uart_flush_buffer(tty); | 1339 | uart_flush_buffer(tty); |
1340 | 1340 | ||
1341 | tty_ldisc_flush(tty); | 1341 | tty_ldisc_flush(tty); |
@@ -1436,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty) | |||
1436 | mutex_lock(&port->mutex); | 1436 | mutex_lock(&port->mutex); |
1437 | if (port->flags & ASYNC_NORMAL_ACTIVE) { | 1437 | if (port->flags & ASYNC_NORMAL_ACTIVE) { |
1438 | uart_flush_buffer(tty); | 1438 | uart_flush_buffer(tty); |
1439 | uart_shutdown(state); | 1439 | uart_shutdown(tty, state); |
1440 | port->count = 0; | 1440 | port->count = 0; |
1441 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1441 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1442 | tty_port_tty_set(port, NULL); | 1442 | tty_port_tty_set(port, NULL); |
@@ -1446,15 +1446,19 @@ static void uart_hangup(struct tty_struct *tty) | |||
1446 | mutex_unlock(&port->mutex); | 1446 | mutex_unlock(&port->mutex); |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | /* | 1449 | /** |
1450 | * Copy across the serial console cflag setting into the termios settings | 1450 | * uart_update_termios - update the terminal hw settings |
1451 | * for the initial open of the port. This allows continuity between the | 1451 | * @tty: tty associated with UART |
1452 | * kernel settings, and the settings init adopts when it opens the port | 1452 | * @state: UART to update |
1453 | * for the first time. | 1453 | * |
1454 | * Copy across the serial console cflag setting into the termios settings | ||
1455 | * for the initial open of the port. This allows continuity between the | ||
1456 | * kernel settings, and the settings init adopts when it opens the port | ||
1457 | * for the first time. | ||
1454 | */ | 1458 | */ |
1455 | static void uart_update_termios(struct uart_state *state) | 1459 | static void uart_update_termios(struct tty_struct *tty, |
1460 | struct uart_state *state) | ||
1456 | { | 1461 | { |
1457 | struct tty_struct *tty = state->port.tty; | ||
1458 | struct uart_port *port = state->uart_port; | 1462 | struct uart_port *port = state->uart_port; |
1459 | 1463 | ||
1460 | if (uart_console(port) && port->cons->cflag) { | 1464 | if (uart_console(port) && port->cons->cflag) { |
@@ -1471,7 +1475,7 @@ static void uart_update_termios(struct uart_state *state) | |||
1471 | /* | 1475 | /* |
1472 | * Make termios settings take effect. | 1476 | * Make termios settings take effect. |
1473 | */ | 1477 | */ |
1474 | uart_change_speed(state, NULL); | 1478 | uart_change_speed(tty, state, NULL); |
1475 | 1479 | ||
1476 | /* | 1480 | /* |
1477 | * And finally enable the RTS and DTR signals. | 1481 | * And finally enable the RTS and DTR signals. |
@@ -1668,7 +1672,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1668 | /* | 1672 | /* |
1669 | * Start up the serial port. | 1673 | * Start up the serial port. |
1670 | */ | 1674 | */ |
1671 | retval = uart_startup(state, 0); | 1675 | retval = uart_startup(tty, state, 0); |
1672 | 1676 | ||
1673 | /* | 1677 | /* |
1674 | * If we succeeded, wait until the port is ready. | 1678 | * If we succeeded, wait until the port is ready. |
@@ -1683,7 +1687,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1683 | if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { | 1687 | if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { |
1684 | set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1688 | set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1685 | 1689 | ||
1686 | uart_update_termios(state); | 1690 | uart_update_termios(tty, state); |
1687 | } | 1691 | } |
1688 | 1692 | ||
1689 | fail: | 1693 | fail: |
@@ -2010,9 +2014,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) | |||
2010 | struct tty_port *port = &state->port; | 2014 | struct tty_port *port = &state->port; |
2011 | struct device *tty_dev; | 2015 | struct device *tty_dev; |
2012 | struct uart_match match = {uport, drv}; | 2016 | struct uart_match match = {uport, drv}; |
2017 | struct tty_struct *tty; | ||
2013 | 2018 | ||
2014 | mutex_lock(&port->mutex); | 2019 | mutex_lock(&port->mutex); |
2015 | 2020 | ||
2021 | /* Must be inside the mutex lock until we convert to tty_port */ | ||
2022 | tty = port->tty; | ||
2023 | |||
2016 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); | 2024 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); |
2017 | if (device_may_wakeup(tty_dev)) { | 2025 | if (device_may_wakeup(tty_dev)) { |
2018 | enable_irq_wake(uport->irq); | 2026 | enable_irq_wake(uport->irq); |
@@ -2105,9 +2113,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2105 | ops->set_mctrl(uport, 0); | 2113 | ops->set_mctrl(uport, 0); |
2106 | spin_unlock_irq(&uport->lock); | 2114 | spin_unlock_irq(&uport->lock); |
2107 | if (console_suspend_enabled || !uart_console(uport)) { | 2115 | if (console_suspend_enabled || !uart_console(uport)) { |
2116 | /* Protected by port mutex for now */ | ||
2117 | struct tty_struct *tty = port->tty; | ||
2108 | ret = ops->startup(uport); | 2118 | ret = ops->startup(uport); |
2109 | if (ret == 0) { | 2119 | if (ret == 0) { |
2110 | uart_change_speed(state, NULL); | 2120 | if (tty) |
2121 | uart_change_speed(tty, state, NULL); | ||
2111 | spin_lock_irq(&uport->lock); | 2122 | spin_lock_irq(&uport->lock); |
2112 | ops->set_mctrl(uport, uport->mctrl); | 2123 | ops->set_mctrl(uport, uport->mctrl); |
2113 | ops->start_tx(uport); | 2124 | ops->start_tx(uport); |
@@ -2119,7 +2130,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2119 | * Clear the "initialized" flag so we won't try | 2130 | * Clear the "initialized" flag so we won't try |
2120 | * to call the low level drivers shutdown method. | 2131 | * to call the low level drivers shutdown method. |
2121 | */ | 2132 | */ |
2122 | uart_shutdown(state); | 2133 | uart_shutdown(tty, state); |
2123 | } | 2134 | } |
2124 | } | 2135 | } |
2125 | 2136 | ||