diff options
author | Alan Cox <alan@redhat.com> | 2008-07-16 16:53:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-20 20:12:35 -0400 |
commit | df4f4dd429870f435f8d5d9d561db029a29f063b (patch) | |
tree | 5e33106f5e5fc4c530170087d3151c13659fad1f /drivers/serial/serial_core.c | |
parent | 6f67048cd010afe19d79d821f16055d9c704c6f0 (diff) |
serial: use tty_port
Switch the serial_core based drivers to use the new tty_port structure.
We can't quite use all of it yet because of the dynamically allocated
extras in the serial_core layer.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/serial/serial_core.c')
-rw-r--r-- | drivers/serial/serial_core.c | 80 |
1 files changed, 42 insertions, 38 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9884bc9eecb..0bce1fe2c62 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->blocked_open : 0)) | 53 | #define uart_users(state) ((state)->count + ((state)->info ? (state)->info->port.blocked_open : 0)) |
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) |
@@ -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->tty); | 116 | tty_wakeup(state->info->port.tty); |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void | 119 | static inline void |
@@ -135,7 +135,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
135 | 135 | ||
136 | /* | 136 | /* |
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 semaphore. | 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 uart_state *state, int init_hw) |
141 | { | 141 | { |
@@ -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, &info->tty->flags); | 155 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); |
156 | 156 | ||
157 | if (port->type == PORT_UNKNOWN) | 157 | if (port->type == PORT_UNKNOWN) |
158 | return 0; | 158 | return 0; |
@@ -162,6 +162,7 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
162 | * buffer. | 162 | * buffer. |
163 | */ | 163 | */ |
164 | if (!info->xmit.buf) { | 164 | if (!info->xmit.buf) { |
165 | /* This is protected by the per port mutex */ | ||
165 | page = get_zeroed_page(GFP_KERNEL); | 166 | page = get_zeroed_page(GFP_KERNEL); |
166 | if (!page) | 167 | if (!page) |
167 | return -ENOMEM; | 168 | return -ENOMEM; |
@@ -182,20 +183,20 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
182 | * Setup the RTS and DTR signals once the | 183 | * Setup the RTS and DTR signals once the |
183 | * port is open and ready to respond. | 184 | * port is open and ready to respond. |
184 | */ | 185 | */ |
185 | if (info->tty->termios->c_cflag & CBAUD) | 186 | if (info->port.tty->termios->c_cflag & CBAUD) |
186 | uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 187 | uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); |
187 | } | 188 | } |
188 | 189 | ||
189 | if (info->flags & UIF_CTS_FLOW) { | 190 | if (info->flags & UIF_CTS_FLOW) { |
190 | spin_lock_irq(&port->lock); | 191 | spin_lock_irq(&port->lock); |
191 | if (!(port->ops->get_mctrl(port) & TIOCM_CTS)) | 192 | if (!(port->ops->get_mctrl(port) & TIOCM_CTS)) |
192 | info->tty->hw_stopped = 1; | 193 | info->port.tty->hw_stopped = 1; |
193 | spin_unlock_irq(&port->lock); | 194 | spin_unlock_irq(&port->lock); |
194 | } | 195 | } |
195 | 196 | ||
196 | info->flags |= UIF_INITIALIZED; | 197 | info->flags |= UIF_INITIALIZED; |
197 | 198 | ||
198 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 199 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); |
199 | } | 200 | } |
200 | 201 | ||
201 | if (retval && capable(CAP_SYS_ADMIN)) | 202 | if (retval && capable(CAP_SYS_ADMIN)) |
@@ -217,8 +218,8 @@ static void uart_shutdown(struct uart_state *state) | |||
217 | /* | 218 | /* |
218 | * Set the TTY IO error marker | 219 | * Set the TTY IO error marker |
219 | */ | 220 | */ |
220 | if (info->tty) | 221 | if (info->port.tty) |
221 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 222 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); |
222 | 223 | ||
223 | if (info->flags & UIF_INITIALIZED) { | 224 | if (info->flags & UIF_INITIALIZED) { |
224 | info->flags &= ~UIF_INITIALIZED; | 225 | info->flags &= ~UIF_INITIALIZED; |
@@ -226,7 +227,7 @@ static void uart_shutdown(struct uart_state *state) | |||
226 | /* | 227 | /* |
227 | * Turn off DTR and RTS early. | 228 | * Turn off DTR and RTS early. |
228 | */ | 229 | */ |
229 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | 230 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) |
230 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 231 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
231 | 232 | ||
232 | /* | 233 | /* |
@@ -426,7 +427,7 @@ EXPORT_SYMBOL(uart_get_divisor); | |||
426 | static void | 427 | static void |
427 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 428 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) |
428 | { | 429 | { |
429 | struct tty_struct *tty = state->info->tty; | 430 | struct tty_struct *tty = state->info->port.tty; |
430 | struct uart_port *port = state->port; | 431 | struct uart_port *port = state->port; |
431 | struct ktermios *termios; | 432 | struct ktermios *termios; |
432 | 433 | ||
@@ -836,8 +837,8 @@ static int uart_set_info(struct uart_state *state, | |||
836 | state->closing_wait = closing_wait; | 837 | state->closing_wait = closing_wait; |
837 | if (new_serial.xmit_fifo_size) | 838 | if (new_serial.xmit_fifo_size) |
838 | port->fifosize = new_serial.xmit_fifo_size; | 839 | port->fifosize = new_serial.xmit_fifo_size; |
839 | if (state->info->tty) | 840 | if (state->info->port.tty) |
840 | state->info->tty->low_latency = | 841 | state->info->port.tty->low_latency = |
841 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 842 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
842 | 843 | ||
843 | check_and_exit: | 844 | check_and_exit: |
@@ -857,7 +858,7 @@ static int uart_set_info(struct uart_state *state, | |||
857 | printk(KERN_NOTICE | 858 | printk(KERN_NOTICE |
858 | "%s sets custom speed on %s. This " | 859 | "%s sets custom speed on %s. This " |
859 | "is deprecated.\n", current->comm, | 860 | "is deprecated.\n", current->comm, |
860 | tty_name(state->info->tty, buf)); | 861 | tty_name(state->info->port.tty, buf)); |
861 | } | 862 | } |
862 | uart_change_speed(state, NULL); | 863 | uart_change_speed(state, NULL); |
863 | } | 864 | } |
@@ -889,7 +890,7 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
889 | */ | 890 | */ |
890 | if (port->x_char || | 891 | if (port->x_char || |
891 | ((uart_circ_chars_pending(&state->info->xmit) > 0) && | 892 | ((uart_circ_chars_pending(&state->info->xmit) > 0) && |
892 | !state->info->tty->stopped && !state->info->tty->hw_stopped)) | 893 | !state->info->port.tty->stopped && !state->info->port.tty->hw_stopped)) |
893 | result &= ~TIOCSER_TEMT; | 894 | result &= ~TIOCSER_TEMT; |
894 | 895 | ||
895 | return put_user(result, value); | 896 | return put_user(result, value); |
@@ -1239,7 +1240,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1239 | */ | 1240 | */ |
1240 | if (!(old_termios->c_cflag & CLOCAL) && | 1241 | if (!(old_termios->c_cflag & CLOCAL) && |
1241 | (tty->termios->c_cflag & CLOCAL)) | 1242 | (tty->termios->c_cflag & CLOCAL)) |
1242 | wake_up_interruptible(&state->info->open_wait); | 1243 | wake_up_interruptible(&state->info->port.open_wait); |
1243 | #endif | 1244 | #endif |
1244 | } | 1245 | } |
1245 | 1246 | ||
@@ -1320,9 +1321,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1320 | tty_ldisc_flush(tty); | 1321 | tty_ldisc_flush(tty); |
1321 | 1322 | ||
1322 | tty->closing = 0; | 1323 | tty->closing = 0; |
1323 | state->info->tty = NULL; | 1324 | state->info->port.tty = NULL; |
1324 | 1325 | ||
1325 | if (state->info->blocked_open) { | 1326 | if (state->info->port.blocked_open) { |
1326 | if (state->close_delay) | 1327 | if (state->close_delay) |
1327 | msleep_interruptible(state->close_delay); | 1328 | msleep_interruptible(state->close_delay); |
1328 | } else if (!uart_console(port)) { | 1329 | } else if (!uart_console(port)) { |
@@ -1333,7 +1334,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1333 | * Wake up anyone trying to open this port. | 1334 | * Wake up anyone trying to open this port. |
1334 | */ | 1335 | */ |
1335 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1336 | state->info->flags &= ~UIF_NORMAL_ACTIVE; |
1336 | wake_up_interruptible(&state->info->open_wait); | 1337 | wake_up_interruptible(&state->info->port.open_wait); |
1337 | 1338 | ||
1338 | done: | 1339 | done: |
1339 | mutex_unlock(&state->mutex); | 1340 | mutex_unlock(&state->mutex); |
@@ -1417,8 +1418,8 @@ static void uart_hangup(struct tty_struct *tty) | |||
1417 | uart_shutdown(state); | 1418 | uart_shutdown(state); |
1418 | state->count = 0; | 1419 | state->count = 0; |
1419 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1420 | state->info->flags &= ~UIF_NORMAL_ACTIVE; |
1420 | state->info->tty = NULL; | 1421 | state->info->port.tty = NULL; |
1421 | wake_up_interruptible(&state->info->open_wait); | 1422 | wake_up_interruptible(&state->info->port.open_wait); |
1422 | wake_up_interruptible(&state->info->delta_msr_wait); | 1423 | wake_up_interruptible(&state->info->delta_msr_wait); |
1423 | } | 1424 | } |
1424 | mutex_unlock(&state->mutex); | 1425 | mutex_unlock(&state->mutex); |
@@ -1432,7 +1433,7 @@ static void uart_hangup(struct tty_struct *tty) | |||
1432 | */ | 1433 | */ |
1433 | static void uart_update_termios(struct uart_state *state) | 1434 | static void uart_update_termios(struct uart_state *state) |
1434 | { | 1435 | { |
1435 | struct tty_struct *tty = state->info->tty; | 1436 | struct tty_struct *tty = state->info->port.tty; |
1436 | struct uart_port *port = state->port; | 1437 | struct uart_port *port = state->port; |
1437 | 1438 | ||
1438 | if (uart_console(port) && port->cons->cflag) { | 1439 | if (uart_console(port) && port->cons->cflag) { |
@@ -1471,17 +1472,17 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1471 | struct uart_port *port = state->port; | 1472 | struct uart_port *port = state->port; |
1472 | unsigned int mctrl; | 1473 | unsigned int mctrl; |
1473 | 1474 | ||
1474 | info->blocked_open++; | 1475 | info->port.blocked_open++; |
1475 | state->count--; | 1476 | state->count--; |
1476 | 1477 | ||
1477 | add_wait_queue(&info->open_wait, &wait); | 1478 | add_wait_queue(&info->port.open_wait, &wait); |
1478 | while (1) { | 1479 | while (1) { |
1479 | set_current_state(TASK_INTERRUPTIBLE); | 1480 | set_current_state(TASK_INTERRUPTIBLE); |
1480 | 1481 | ||
1481 | /* | 1482 | /* |
1482 | * If we have been hung up, tell userspace/restart open. | 1483 | * If we have been hung up, tell userspace/restart open. |
1483 | */ | 1484 | */ |
1484 | if (tty_hung_up_p(filp) || info->tty == NULL) | 1485 | if (tty_hung_up_p(filp) || info->port.tty == NULL) |
1485 | break; | 1486 | break; |
1486 | 1487 | ||
1487 | /* | 1488 | /* |
@@ -1500,8 +1501,8 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1500 | * have set TTY_IO_ERROR for a non-existant port. | 1501 | * have set TTY_IO_ERROR for a non-existant port. |
1501 | */ | 1502 | */ |
1502 | if ((filp->f_flags & O_NONBLOCK) || | 1503 | if ((filp->f_flags & O_NONBLOCK) || |
1503 | (info->tty->termios->c_cflag & CLOCAL) || | 1504 | (info->port.tty->termios->c_cflag & CLOCAL) || |
1504 | (info->tty->flags & (1 << TTY_IO_ERROR))) | 1505 | (info->port.tty->flags & (1 << TTY_IO_ERROR))) |
1505 | break; | 1506 | break; |
1506 | 1507 | ||
1507 | /* | 1508 | /* |
@@ -1509,7 +1510,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1509 | * not set RTS here - we want to make sure we catch | 1510 | * not set RTS here - we want to make sure we catch |
1510 | * the data from the modem. | 1511 | * the data from the modem. |
1511 | */ | 1512 | */ |
1512 | if (info->tty->termios->c_cflag & CBAUD) | 1513 | if (info->port.tty->termios->c_cflag & CBAUD) |
1513 | uart_set_mctrl(port, TIOCM_DTR); | 1514 | uart_set_mctrl(port, TIOCM_DTR); |
1514 | 1515 | ||
1515 | /* | 1516 | /* |
@@ -1531,15 +1532,15 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) | |||
1531 | break; | 1532 | break; |
1532 | } | 1533 | } |
1533 | set_current_state(TASK_RUNNING); | 1534 | set_current_state(TASK_RUNNING); |
1534 | remove_wait_queue(&info->open_wait, &wait); | 1535 | remove_wait_queue(&info->port.open_wait, &wait); |
1535 | 1536 | ||
1536 | state->count++; | 1537 | state->count++; |
1537 | info->blocked_open--; | 1538 | info->port.blocked_open--; |
1538 | 1539 | ||
1539 | if (signal_pending(current)) | 1540 | if (signal_pending(current)) |
1540 | return -ERESTARTSYS; | 1541 | return -ERESTARTSYS; |
1541 | 1542 | ||
1542 | if (!info->tty || tty_hung_up_p(filp)) | 1543 | if (!info->port.tty || tty_hung_up_p(filp)) |
1543 | return -EAGAIN; | 1544 | return -EAGAIN; |
1544 | 1545 | ||
1545 | return 0; | 1546 | return 0; |
@@ -1562,10 +1563,13 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1562 | goto err_unlock; | 1563 | goto err_unlock; |
1563 | } | 1564 | } |
1564 | 1565 | ||
1566 | /* BKL: RACE HERE - LEAK */ | ||
1567 | /* We should move this into the uart_state structure and kill off | ||
1568 | this whole complexity */ | ||
1565 | if (!state->info) { | 1569 | if (!state->info) { |
1566 | state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL); | 1570 | state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL); |
1567 | if (state->info) { | 1571 | if (state->info) { |
1568 | init_waitqueue_head(&state->info->open_wait); | 1572 | init_waitqueue_head(&state->info->port.open_wait); |
1569 | init_waitqueue_head(&state->info->delta_msr_wait); | 1573 | init_waitqueue_head(&state->info->delta_msr_wait); |
1570 | 1574 | ||
1571 | /* | 1575 | /* |
@@ -1622,7 +1626,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1622 | * be re-entered while allocating the info structure, or while we | 1626 | * be re-entered while allocating the info structure, or while we |
1623 | * request any IRQs that the driver may need. This also has the nice | 1627 | * request any IRQs that the driver may need. This also has the nice |
1624 | * side-effect that it delays the action of uart_hangup, so we can | 1628 | * side-effect that it delays the action of uart_hangup, so we can |
1625 | * guarantee that info->tty will always contain something reasonable. | 1629 | * guarantee that info->port.tty will always contain something reasonable. |
1626 | */ | 1630 | */ |
1627 | state = uart_get(drv, line); | 1631 | state = uart_get(drv, line); |
1628 | if (IS_ERR(state)) { | 1632 | if (IS_ERR(state)) { |
@@ -1638,7 +1642,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1638 | tty->driver_data = state; | 1642 | tty->driver_data = state; |
1639 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 1643 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
1640 | tty->alt_speed = 0; | 1644 | tty->alt_speed = 0; |
1641 | state->info->tty = tty; | 1645 | state->info->port.tty = tty; |
1642 | 1646 | ||
1643 | /* | 1647 | /* |
1644 | * If the port is in the middle of closing, bail out now. | 1648 | * If the port is in the middle of closing, bail out now. |
@@ -2101,8 +2105,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2101 | /* | 2105 | /* |
2102 | * If that's unset, use the tty termios setting. | 2106 | * If that's unset, use the tty termios setting. |
2103 | */ | 2107 | */ |
2104 | if (state->info && state->info->tty && termios.c_cflag == 0) | 2108 | if (state->info && state->info->port.tty && termios.c_cflag == 0) |
2105 | termios = *state->info->tty->termios; | 2109 | termios = *state->info->port.tty->termios; |
2106 | 2110 | ||
2107 | uart_change_pm(state, 0); | 2111 | uart_change_pm(state, 0); |
2108 | port->ops->set_termios(port, &termios, NULL); | 2112 | port->ops->set_termios(port, &termios, NULL); |
@@ -2521,8 +2525,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2521 | tty_unregister_device(drv->tty_driver, port->line); | 2525 | tty_unregister_device(drv->tty_driver, port->line); |
2522 | 2526 | ||
2523 | info = state->info; | 2527 | info = state->info; |
2524 | if (info && info->tty) | 2528 | if (info && info->port.tty) |
2525 | tty_vhangup(info->tty); | 2529 | tty_vhangup(info->port.tty); |
2526 | 2530 | ||
2527 | /* | 2531 | /* |
2528 | * All users of this port should now be disconnected from | 2532 | * All users of this port should now be disconnected from |