diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:49:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:42 -0500 |
commit | f751928e0ddf54ea4fe5546f35e99efc5b5d9938 (patch) | |
tree | a8198e420a70408dc58cabb54e10f67e0c1c0ebf /drivers | |
parent | 6ef53066ff7991d5f9670340e92d42ee1776bbe4 (diff) |
tty: We want the port object to be persistent
Move the tty_port and uart_info bits around a little. By embedding the uart_info
into the uart_port we get rid of lots of corner case testing and also get the
ability to go port<->state<->info which is a bit more elegant than the current
data structures.
Downsides - we allocate a tiny bit more memory for unused ports, upside we've
removed as much code as it saved for most users..
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 2 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 144 |
2 files changed, 62 insertions, 84 deletions
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index a697914ae3d0..3547558d2caf 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -272,7 +272,7 @@ static void jsm_tty_close(struct uart_port *port) | |||
272 | jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); | 272 | jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); |
273 | 273 | ||
274 | bd = channel->ch_bd; | 274 | bd = channel->ch_bd; |
275 | ts = channel->uart_port.info->port.tty->termios; | 275 | ts = port->info->port.tty->termios; |
276 | 276 | ||
277 | channel->ch_flags &= ~(CH_STOPI); | 277 | channel->ch_flags &= ~(CH_STOPI); |
278 | 278 | ||
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 874786a11fe9..daeba1c52c8e 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -50,7 +50,7 @@ static struct lock_class_key port_lock_key; | |||
50 | 50 | ||
51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
52 | 52 | ||
53 | #define uart_users(state) ((state)->count + ((state)->info ? (state)->info->port.blocked_open : 0)) | 53 | #define uart_users(state) ((state)->count + (state)->info.port.blocked_open) |
54 | 54 | ||
55 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | 55 | #ifdef CONFIG_SERIAL_CORE_CONSOLE |
56 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) | 56 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) |
@@ -94,7 +94,7 @@ static void __uart_start(struct tty_struct *tty) | |||
94 | struct uart_state *state = tty->driver_data; | 94 | struct uart_state *state = tty->driver_data; |
95 | struct uart_port *port = state->port; | 95 | struct uart_port *port = state->port; |
96 | 96 | ||
97 | if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && | 97 | if (!uart_circ_empty(&state->info.xmit) && state->info.xmit.buf && |
98 | !tty->stopped && !tty->hw_stopped) | 98 | !tty->stopped && !tty->hw_stopped) |
99 | port->ops->start_tx(port); | 99 | port->ops->start_tx(port); |
100 | } | 100 | } |
@@ -113,7 +113,7 @@ static void uart_start(struct tty_struct *tty) | |||
113 | static void uart_tasklet_action(unsigned long data) | 113 | static void uart_tasklet_action(unsigned long data) |
114 | { | 114 | { |
115 | struct uart_state *state = (struct uart_state *)data; | 115 | struct uart_state *state = (struct uart_state *)data; |
116 | tty_wakeup(state->info->port.tty); | 116 | tty_wakeup(state->info.port.tty); |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void | 119 | static inline void |
@@ -139,7 +139,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
139 | */ | 139 | */ |
140 | static int uart_startup(struct uart_state *state, int init_hw) | 140 | static int uart_startup(struct uart_state *state, int init_hw) |
141 | { | 141 | { |
142 | struct uart_info *info = state->info; | 142 | struct uart_info *info = &state->info; |
143 | struct uart_port *port = state->port; | 143 | struct uart_port *port = state->port; |
144 | unsigned long page; | 144 | unsigned long page; |
145 | int retval = 0; | 145 | int retval = 0; |
@@ -212,14 +212,15 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
212 | */ | 212 | */ |
213 | static void uart_shutdown(struct uart_state *state) | 213 | static void uart_shutdown(struct uart_state *state) |
214 | { | 214 | { |
215 | struct uart_info *info = state->info; | 215 | struct uart_info *info = &state->info; |
216 | struct uart_port *port = state->port; | 216 | struct uart_port *port = state->port; |
217 | struct tty_struct *tty = info->port.tty; | ||
217 | 218 | ||
218 | /* | 219 | /* |
219 | * Set the TTY IO error marker | 220 | * Set the TTY IO error marker |
220 | */ | 221 | */ |
221 | if (info->port.tty) | 222 | if (tty) |
222 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | 223 | set_bit(TTY_IO_ERROR, &tty->flags); |
223 | 224 | ||
224 | if (info->flags & UIF_INITIALIZED) { | 225 | if (info->flags & UIF_INITIALIZED) { |
225 | info->flags &= ~UIF_INITIALIZED; | 226 | info->flags &= ~UIF_INITIALIZED; |
@@ -227,7 +228,7 @@ static void uart_shutdown(struct uart_state *state) | |||
227 | /* | 228 | /* |
228 | * Turn off DTR and RTS early. | 229 | * Turn off DTR and RTS early. |
229 | */ | 230 | */ |
230 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | 231 | if (!tty || (tty->termios->c_cflag & HUPCL)) |
231 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 232 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
232 | 233 | ||
233 | /* | 234 | /* |
@@ -427,7 +428,7 @@ EXPORT_SYMBOL(uart_get_divisor); | |||
427 | static void | 428 | static void |
428 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 429 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) |
429 | { | 430 | { |
430 | struct tty_struct *tty = state->info->port.tty; | 431 | struct tty_struct *tty = state->info.port.tty; |
431 | struct uart_port *port = state->port; | 432 | struct uart_port *port = state->port; |
432 | struct ktermios *termios; | 433 | struct ktermios *termios; |
433 | 434 | ||
@@ -444,14 +445,14 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | |||
444 | * Set flags based on termios cflag | 445 | * Set flags based on termios cflag |
445 | */ | 446 | */ |
446 | if (termios->c_cflag & CRTSCTS) | 447 | if (termios->c_cflag & CRTSCTS) |
447 | state->info->flags |= UIF_CTS_FLOW; | 448 | state->info.flags |= UIF_CTS_FLOW; |
448 | else | 449 | else |
449 | state->info->flags &= ~UIF_CTS_FLOW; | 450 | state->info.flags &= ~UIF_CTS_FLOW; |
450 | 451 | ||
451 | if (termios->c_cflag & CLOCAL) | 452 | if (termios->c_cflag & CLOCAL) |
452 | state->info->flags &= ~UIF_CHECK_CD; | 453 | state->info.flags &= ~UIF_CHECK_CD; |
453 | else | 454 | else |
454 | state->info->flags |= UIF_CHECK_CD; | 455 | state->info.flags |= UIF_CHECK_CD; |
455 | 456 | ||
456 | port->ops->set_termios(port, termios, old_termios); | 457 | port->ops->set_termios(port, termios, old_termios); |
457 | } | 458 | } |
@@ -479,7 +480,7 @@ static int uart_put_char(struct tty_struct *tty, unsigned char ch) | |||
479 | { | 480 | { |
480 | struct uart_state *state = tty->driver_data; | 481 | struct uart_state *state = tty->driver_data; |
481 | 482 | ||
482 | return __uart_put_char(state->port, &state->info->xmit, ch); | 483 | return __uart_put_char(state->port, &state->info.xmit, ch); |
483 | } | 484 | } |
484 | 485 | ||
485 | static void uart_flush_chars(struct tty_struct *tty) | 486 | static void uart_flush_chars(struct tty_struct *tty) |
@@ -500,13 +501,13 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
500 | * This means you called this function _after_ the port was | 501 | * This means you called this function _after_ the port was |
501 | * closed. No cookie for you. | 502 | * closed. No cookie for you. |
502 | */ | 503 | */ |
503 | if (!state || !state->info) { | 504 | if (!state) { |
504 | WARN_ON(1); | 505 | WARN_ON(1); |
505 | return -EL3HLT; | 506 | return -EL3HLT; |
506 | } | 507 | } |
507 | 508 | ||
508 | port = state->port; | 509 | port = state->port; |
509 | circ = &state->info->xmit; | 510 | circ = &state->info.xmit; |
510 | 511 | ||
511 | if (!circ->buf) | 512 | if (!circ->buf) |
512 | return 0; | 513 | return 0; |
@@ -537,7 +538,7 @@ static int uart_write_room(struct tty_struct *tty) | |||
537 | int ret; | 538 | int ret; |
538 | 539 | ||
539 | spin_lock_irqsave(&state->port->lock, flags); | 540 | spin_lock_irqsave(&state->port->lock, flags); |
540 | ret = uart_circ_chars_free(&state->info->xmit); | 541 | ret = uart_circ_chars_free(&state->info.xmit); |
541 | spin_unlock_irqrestore(&state->port->lock, flags); | 542 | spin_unlock_irqrestore(&state->port->lock, flags); |
542 | return ret; | 543 | return ret; |
543 | } | 544 | } |
@@ -549,7 +550,7 @@ static int uart_chars_in_buffer(struct tty_struct *tty) | |||
549 | int ret; | 550 | int ret; |
550 | 551 | ||
551 | spin_lock_irqsave(&state->port->lock, flags); | 552 | spin_lock_irqsave(&state->port->lock, flags); |
552 | ret = uart_circ_chars_pending(&state->info->xmit); | 553 | ret = uart_circ_chars_pending(&state->info.xmit); |
553 | spin_unlock_irqrestore(&state->port->lock, flags); | 554 | spin_unlock_irqrestore(&state->port->lock, flags); |
554 | return ret; | 555 | return ret; |
555 | } | 556 | } |
@@ -564,7 +565,7 @@ static void uart_flush_buffer(struct tty_struct *tty) | |||
564 | * This means you called this function _after_ the port was | 565 | * This means you called this function _after_ the port was |
565 | * closed. No cookie for you. | 566 | * closed. No cookie for you. |
566 | */ | 567 | */ |
567 | if (!state || !state->info) { | 568 | if (!state) { |
568 | WARN_ON(1); | 569 | WARN_ON(1); |
569 | return; | 570 | return; |
570 | } | 571 | } |
@@ -573,7 +574,7 @@ static void uart_flush_buffer(struct tty_struct *tty) | |||
573 | pr_debug("uart_flush_buffer(%d) called\n", tty->index); | 574 | pr_debug("uart_flush_buffer(%d) called\n", tty->index); |
574 | 575 | ||
575 | spin_lock_irqsave(&port->lock, flags); | 576 | spin_lock_irqsave(&port->lock, flags); |
576 | uart_circ_clear(&state->info->xmit); | 577 | uart_circ_clear(&state->info.xmit); |
577 | if (port->ops->flush_buffer) | 578 | if (port->ops->flush_buffer) |
578 | port->ops->flush_buffer(port); | 579 | port->ops->flush_buffer(port); |
579 | spin_unlock_irqrestore(&port->lock, flags); | 580 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -837,15 +838,15 @@ static int uart_set_info(struct uart_state *state, | |||
837 | state->closing_wait = closing_wait; | 838 | state->closing_wait = closing_wait; |
838 | if (new_serial.xmit_fifo_size) | 839 | if (new_serial.xmit_fifo_size) |
839 | port->fifosize = new_serial.xmit_fifo_size; | 840 | port->fifosize = new_serial.xmit_fifo_size; |
840 | if (state->info->port.tty) | 841 | if (state->info.port.tty) |
841 | state->info->port.tty->low_latency = | 842 | state->info.port.tty->low_latency = |
842 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 843 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
843 | 844 | ||
844 | check_and_exit: | 845 | check_and_exit: |
845 | retval = 0; | 846 | retval = 0; |
846 | if (port->type == PORT_UNKNOWN) | 847 | if (port->type == PORT_UNKNOWN) |
847 | goto exit; | 848 | goto exit; |
848 | if (state->info->flags & UIF_INITIALIZED) { | 849 | if (state->info.flags & UIF_INITIALIZED) { |
849 | if (((old_flags ^ port->flags) & UPF_SPD_MASK) || | 850 | if (((old_flags ^ port->flags) & UPF_SPD_MASK) || |
850 | old_custom_divisor != port->custom_divisor) { | 851 | old_custom_divisor != port->custom_divisor) { |
851 | /* | 852 | /* |
@@ -858,7 +859,7 @@ static int uart_set_info(struct uart_state *state, | |||
858 | printk(KERN_NOTICE | 859 | printk(KERN_NOTICE |
859 | "%s sets custom speed on %s. This " | 860 | "%s sets custom speed on %s. This " |
860 | "is deprecated.\n", current->comm, | 861 | "is deprecated.\n", current->comm, |
861 | tty_name(state->info->port.tty, buf)); | 862 | tty_name(state->info.port.tty, buf)); |
862 | } | 863 | } |
863 | uart_change_speed(state, NULL); | 864 | uart_change_speed(state, NULL); |
864 | } | 865 | } |
@@ -889,8 +890,8 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
889 | * interrupt happens). | 890 | * interrupt happens). |
890 | */ | 891 | */ |
891 | if (port->x_char || | 892 | if (port->x_char || |
892 | ((uart_circ_chars_pending(&state->info->xmit) > 0) && | 893 | ((uart_circ_chars_pending(&state->info.xmit) > 0) && |
893 | !state->info->port.tty->stopped && !state->info->port.tty->hw_stopped)) | 894 | !state->info.port.tty->stopped && !state->info.port.tty->hw_stopped)) |
894 | result &= ~TIOCSER_TEMT; | 895 | result &= ~TIOCSER_TEMT; |
895 | 896 | ||
896 | return put_user(result, value); | 897 | return put_user(result, value); |
@@ -1017,7 +1018,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) | |||
1017 | port->ops->enable_ms(port); | 1018 | port->ops->enable_ms(port); |
1018 | spin_unlock_irq(&port->lock); | 1019 | spin_unlock_irq(&port->lock); |
1019 | 1020 | ||
1020 | add_wait_queue(&state->info->delta_msr_wait, &wait); | 1021 | add_wait_queue(&state->info.delta_msr_wait, &wait); |
1021 | for (;;) { | 1022 | for (;;) { |
1022 | spin_lock_irq(&port->lock); | 1023 | spin_lock_irq(&port->lock); |
1023 | memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); | 1024 | memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); |
@@ -1045,7 +1046,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) | |||
1045 | } | 1046 | } |
1046 | 1047 | ||
1047 | current->state = TASK_RUNNING; | 1048 | current->state = TASK_RUNNING; |
1048 | remove_wait_queue(&state->info->delta_msr_wait, &wait); | 1049 | remove_wait_queue(&state->info.delta_msr_wait, &wait); |
1049 | 1050 | ||
1050 | return ret; | 1051 | return ret; |
1051 | } | 1052 | } |
@@ -1241,7 +1242,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1241 | */ | 1242 | */ |
1242 | if (!(old_termios->c_cflag & CLOCAL) && | 1243 | if (!(old_termios->c_cflag & CLOCAL) && |
1243 | (tty->termios->c_cflag & CLOCAL)) | 1244 | (tty->termios->c_cflag & CLOCAL)) |
1244 | wake_up_interruptible(&state->info->port.open_wait); | 1245 | wake_up_interruptible(&info->port.open_wait); |
1245 | #endif | 1246 | #endif |
1246 | } | 1247 | } |
1247 | 1248 | ||
@@ -1303,7 +1304,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1303 | * At this point, we stop accepting input. To do this, we | 1304 | * At this point, we stop accepting input. To do this, we |
1304 | * disable the receive line status interrupts. | 1305 | * disable the receive line status interrupts. |
1305 | */ | 1306 | */ |
1306 | if (state->info->flags & UIF_INITIALIZED) { | 1307 | if (state->info.flags & UIF_INITIALIZED) { |
1307 | unsigned long flags; | 1308 | unsigned long flags; |
1308 | spin_lock_irqsave(&port->lock, flags); | 1309 | spin_lock_irqsave(&port->lock, flags); |
1309 | port->ops->stop_rx(port); | 1310 | port->ops->stop_rx(port); |
@@ -1322,9 +1323,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1322 | tty_ldisc_flush(tty); | 1323 | tty_ldisc_flush(tty); |
1323 | 1324 | ||
1324 | tty->closing = 0; | 1325 | tty->closing = 0; |
1325 | state->info->port.tty = NULL; | 1326 | state->info.port.tty = NULL; |
1326 | 1327 | ||
1327 | if (state->info->port.blocked_open) { | 1328 | if (state->info.port.blocked_open) { |
1328 | if (state->close_delay) | 1329 | if (state->close_delay) |
1329 | msleep_interruptible(state->close_delay); | 1330 | msleep_interruptible(state->close_delay); |
1330 | } else if (!uart_console(port)) { | 1331 | } else if (!uart_console(port)) { |
@@ -1334,8 +1335,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1334 | /* | 1335 | /* |
1335 | * Wake up anyone trying to open this port. | 1336 | * Wake up anyone trying to open this port. |
1336 | */ | 1337 | */ |
1337 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1338 | state->info.flags &= ~UIF_NORMAL_ACTIVE; |
1338 | wake_up_interruptible(&state->info->port.open_wait); | 1339 | wake_up_interruptible(&state->info.port.open_wait); |
1339 | 1340 | ||
1340 | done: | 1341 | done: |
1341 | mutex_unlock(&state->mutex); | 1342 | mutex_unlock(&state->mutex); |
@@ -1409,19 +1410,20 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1409 | static void uart_hangup(struct tty_struct *tty) | 1410 | static void uart_hangup(struct tty_struct *tty) |
1410 | { | 1411 | { |
1411 | struct uart_state *state = tty->driver_data; | 1412 | struct uart_state *state = tty->driver_data; |
1413 | struct uart_info *info = &state->info; | ||
1412 | 1414 | ||
1413 | BUG_ON(!kernel_locked()); | 1415 | BUG_ON(!kernel_locked()); |
1414 | pr_debug("uart_hangup(%d)\n", state->port->line); | 1416 | pr_debug("uart_hangup(%d)\n", state->port->line); |
1415 | 1417 | ||
1416 | mutex_lock(&state->mutex); | 1418 | mutex_lock(&state->mutex); |
1417 | if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { | 1419 | if (info->flags & UIF_NORMAL_ACTIVE) { |
1418 | uart_flush_buffer(tty); | 1420 | uart_flush_buffer(tty); |
1419 | uart_shutdown(state); | 1421 | uart_shutdown(state); |
1420 | state->count = 0; | 1422 | state->count = 0; |
1421 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1423 | info->flags &= ~UIF_NORMAL_ACTIVE; |
1422 | state->info->port.tty = NULL; | 1424 | info->port.tty = NULL; |
1423 | wake_up_interruptible(&state->info->port.open_wait); | 1425 | wake_up_interruptible(&info->port.open_wait); |
1424 | wake_up_interruptible(&state->info->delta_msr_wait); | 1426 | wake_up_interruptible(&info->delta_msr_wait); |
1425 | } | 1427 | } |
1426 | mutex_unlock(&state->mutex); | 1428 | mutex_unlock(&state->mutex); |
1427 | } | 1429 | } |
@@ -1434,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty) | |||
1434 | */ | 1436 | */ |
1435 | static void uart_update_termios(struct uart_state *state) | 1437 | static void uart_update_termios(struct uart_state *state) |
1436 | { | 1438 | { |
1437 | struct tty_struct *tty = state->info->port.tty; | 1439 | struct tty_struct *tty = state->info.port.tty; |
1438 | struct uart_port *port = state->port; | 1440 | struct uart_port *port = state->port; |
1439 | 1441 | ||
1440 | if (uart_console(port) && port->cons->cflag) { | 1442 | if (uart_console(port) && port->cons->cflag) { |
@@ -1469,7 +1471,7 @@ static int | |||
1469 | uart_block_til_ready(struct file *filp, struct uart_state *state) | 1471 | uart_block_til_ready(struct file *filp, struct uart_state *state) |
1470 | { | 1472 | { |
1471 | DECLARE_WAITQUEUE(wait, current); | 1473 | DECLARE_WAITQUEUE(wait, current); |
1472 | struct uart_info *info = state->info; | 1474 | struct uart_info *info = &state->info; |
1473 | struct uart_port *port = state->port; | 1475 | struct uart_port *port = state->port; |
1474 | unsigned int mctrl; | 1476 | unsigned int mctrl; |
1475 | 1477 | ||
@@ -1563,28 +1565,6 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1563 | ret = -ENXIO; | 1565 | ret = -ENXIO; |
1564 | goto err_unlock; | 1566 | goto err_unlock; |
1565 | } | 1567 | } |
1566 | |||
1567 | /* BKL: RACE HERE - LEAK */ | ||
1568 | /* We should move this into the uart_state structure and kill off | ||
1569 | this whole complexity */ | ||
1570 | if (!state->info) { | ||
1571 | state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL); | ||
1572 | if (state->info) { | ||
1573 | init_waitqueue_head(&state->info->port.open_wait); | ||
1574 | init_waitqueue_head(&state->info->delta_msr_wait); | ||
1575 | |||
1576 | /* | ||
1577 | * Link the info into the other structures. | ||
1578 | */ | ||
1579 | state->port->info = state->info; | ||
1580 | |||
1581 | tasklet_init(&state->info->tlet, uart_tasklet_action, | ||
1582 | (unsigned long)state); | ||
1583 | } else { | ||
1584 | ret = -ENOMEM; | ||
1585 | goto err_unlock; | ||
1586 | } | ||
1587 | } | ||
1588 | return state; | 1568 | return state; |
1589 | 1569 | ||
1590 | err_unlock: | 1570 | err_unlock: |
@@ -1641,9 +1621,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1641 | * Any failures from here onwards should not touch the count. | 1621 | * Any failures from here onwards should not touch the count. |
1642 | */ | 1622 | */ |
1643 | tty->driver_data = state; | 1623 | tty->driver_data = state; |
1624 | state->port->info = &state->info; | ||
1644 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 1625 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
1645 | tty->alt_speed = 0; | 1626 | tty->alt_speed = 0; |
1646 | state->info->port.tty = tty; | 1627 | state->info.port.tty = tty; |
1647 | 1628 | ||
1648 | /* | 1629 | /* |
1649 | * If the port is in the middle of closing, bail out now. | 1630 | * If the port is in the middle of closing, bail out now. |
@@ -1676,8 +1657,8 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1676 | /* | 1657 | /* |
1677 | * If this is the first open to succeed, adjust things to suit. | 1658 | * If this is the first open to succeed, adjust things to suit. |
1678 | */ | 1659 | */ |
1679 | if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { | 1660 | if (retval == 0 && !(state->info.flags & UIF_NORMAL_ACTIVE)) { |
1680 | state->info->flags |= UIF_NORMAL_ACTIVE; | 1661 | state->info.flags |= UIF_NORMAL_ACTIVE; |
1681 | 1662 | ||
1682 | uart_update_termios(state); | 1663 | uart_update_termios(state); |
1683 | } | 1664 | } |
@@ -2028,11 +2009,11 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | |||
2028 | } | 2009 | } |
2029 | port->suspended = 1; | 2010 | port->suspended = 1; |
2030 | 2011 | ||
2031 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 2012 | if (state->info.flags & UIF_INITIALIZED) { |
2032 | const struct uart_ops *ops = port->ops; | 2013 | const struct uart_ops *ops = port->ops; |
2033 | int tries; | 2014 | int tries; |
2034 | 2015 | ||
2035 | state->info->flags = (state->info->flags & ~UIF_INITIALIZED) | 2016 | state->info.flags = (state->info.flags & ~UIF_INITIALIZED) |
2036 | | UIF_SUSPENDED; | 2017 | | UIF_SUSPENDED; |
2037 | 2018 | ||
2038 | spin_lock_irq(&port->lock); | 2019 | spin_lock_irq(&port->lock); |
@@ -2107,15 +2088,15 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2107 | /* | 2088 | /* |
2108 | * If that's unset, use the tty termios setting. | 2089 | * If that's unset, use the tty termios setting. |
2109 | */ | 2090 | */ |
2110 | if (state->info && state->info->port.tty && termios.c_cflag == 0) | 2091 | if (state->info.port.tty && termios.c_cflag == 0) |
2111 | termios = *state->info->port.tty->termios; | 2092 | termios = *state->info.port.tty->termios; |
2112 | 2093 | ||
2113 | uart_change_pm(state, 0); | 2094 | uart_change_pm(state, 0); |
2114 | port->ops->set_termios(port, &termios, NULL); | 2095 | port->ops->set_termios(port, &termios, NULL); |
2115 | console_start(port->cons); | 2096 | console_start(port->cons); |
2116 | } | 2097 | } |
2117 | 2098 | ||
2118 | if (state->info && state->info->flags & UIF_SUSPENDED) { | 2099 | if (state->info.flags & UIF_SUSPENDED) { |
2119 | const struct uart_ops *ops = port->ops; | 2100 | const struct uart_ops *ops = port->ops; |
2120 | int ret; | 2101 | int ret; |
2121 | 2102 | ||
@@ -2130,7 +2111,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2130 | ops->set_mctrl(port, port->mctrl); | 2111 | ops->set_mctrl(port, port->mctrl); |
2131 | ops->start_tx(port); | 2112 | ops->start_tx(port); |
2132 | spin_unlock_irq(&port->lock); | 2113 | spin_unlock_irq(&port->lock); |
2133 | state->info->flags |= UIF_INITIALIZED; | 2114 | state->info.flags |= UIF_INITIALIZED; |
2134 | } else { | 2115 | } else { |
2135 | /* | 2116 | /* |
2136 | * Failed to resume - maybe hardware went away? | 2117 | * Failed to resume - maybe hardware went away? |
@@ -2140,7 +2121,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2140 | uart_shutdown(state); | 2121 | uart_shutdown(state); |
2141 | } | 2122 | } |
2142 | 2123 | ||
2143 | state->info->flags &= ~UIF_SUSPENDED; | 2124 | state->info.flags &= ~UIF_SUSPENDED; |
2144 | } | 2125 | } |
2145 | 2126 | ||
2146 | mutex_unlock(&state->mutex); | 2127 | mutex_unlock(&state->mutex); |
@@ -2383,8 +2364,12 @@ int uart_register_driver(struct uart_driver *drv) | |||
2383 | 2364 | ||
2384 | state->close_delay = 500; /* .5 seconds */ | 2365 | state->close_delay = 500; /* .5 seconds */ |
2385 | state->closing_wait = 30000; /* 30 seconds */ | 2366 | state->closing_wait = 30000; /* 30 seconds */ |
2386 | |||
2387 | mutex_init(&state->mutex); | 2367 | mutex_init(&state->mutex); |
2368 | |||
2369 | tty_port_init(&state->info.port); | ||
2370 | init_waitqueue_head(&state->info.delta_msr_wait); | ||
2371 | tasklet_init(&state->info.tlet, uart_tasklet_action, | ||
2372 | (unsigned long)state); | ||
2388 | } | 2373 | } |
2389 | 2374 | ||
2390 | retval = tty_register_driver(normal); | 2375 | retval = tty_register_driver(normal); |
@@ -2455,7 +2440,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2455 | state->pm_state = -1; | 2440 | state->pm_state = -1; |
2456 | 2441 | ||
2457 | port->cons = drv->cons; | 2442 | port->cons = drv->cons; |
2458 | port->info = state->info; | 2443 | port->info = &state->info; |
2459 | 2444 | ||
2460 | /* | 2445 | /* |
2461 | * If this port is a console, then the spinlock is already | 2446 | * If this port is a console, then the spinlock is already |
@@ -2527,18 +2512,11 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2527 | */ | 2512 | */ |
2528 | tty_unregister_device(drv->tty_driver, port->line); | 2513 | tty_unregister_device(drv->tty_driver, port->line); |
2529 | 2514 | ||
2530 | info = state->info; | 2515 | info = &state->info; |
2531 | if (info && info->port.tty) | 2516 | if (info && info->port.tty) |
2532 | tty_vhangup(info->port.tty); | 2517 | tty_vhangup(info->port.tty); |
2533 | 2518 | ||
2534 | /* | 2519 | /* |
2535 | * All users of this port should now be disconnected from | ||
2536 | * this driver, and the port shut down. We should be the | ||
2537 | * only thread fiddling with this port from now on. | ||
2538 | */ | ||
2539 | state->info = NULL; | ||
2540 | |||
2541 | /* | ||
2542 | * Free the port IO and memory resources, if any. | 2520 | * Free the port IO and memory resources, if any. |
2543 | */ | 2521 | */ |
2544 | if (port->type != PORT_UNKNOWN) | 2522 | if (port->type != PORT_UNKNOWN) |