diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-27 15:52:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-27 15:52:03 -0400 |
commit | c1e7179a38919f02dd950801529176b72f5e5a8a (patch) | |
tree | 70b014e6f48768d38b984de3a3fc1cd53201933d /drivers | |
parent | 84eda28060f7e7d5f91f81f928532af13b9e44b2 (diff) | |
parent | 38bd2a1ac736901d1cf4971c78ef952ba92ef78b (diff) |
Merge tag 'tty-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY/Serial patches from Greg Kroah-Hartman:
"Here's the "tiny" set of patches for 3.6-rc1 for the tty layer and
serial drivers. They were cherry-picked from the tty-next branch of
the tty git tree, as they are small and "obvious" fixes. The larger
changes, as mentioned before, will be saved for the 3.7-rc1 merge
window.
All of these changes have been in the linux-next releases for quite a
while.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'tty-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
pch_uart: Fix parity setting issue
pch_uart: Fix rx error interrupt setting issue
pch_uart: Fix missing break for 16 byte fifo
tty ldisc: Close/Reopen race prevention should check the proper flag
pch_uart: Add eg20t_port lock field, avoid recursive spinlocks
vt: fix race in vt_waitactive()
serial/of-serial: Add LPC3220 standard UART compatible string
serial/8250: Add LPC3220 standard UART type
serial_core: Update buffer overrun statistics.
serial: samsung: Fixed wrong comparison for baudclk_rate
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/8250/8250.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/of_serial.c | 1 | ||||
-rw-r--r-- | drivers/tty/serial/pch_uart.c | 59 | ||||
-rw-r--r-- | drivers/tty/serial/samsung.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 6 | ||||
-rw-r--r-- | drivers/tty/tty_ldisc.c | 2 | ||||
-rw-r--r-- | drivers/tty/vt/vt_ioctl.c | 47 |
7 files changed, 90 insertions, 37 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 6e1958a325bd..8123f784bcda 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -282,6 +282,14 @@ static const struct serial8250_config uart_config[] = { | |||
282 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 282 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
283 | .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, | 283 | .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, |
284 | }, | 284 | }, |
285 | [PORT_LPC3220] = { | ||
286 | .name = "LPC3220", | ||
287 | .fifo_size = 64, | ||
288 | .tx_loadsz = 32, | ||
289 | .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | | ||
290 | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, | ||
291 | .flags = UART_CAP_FIFO, | ||
292 | }, | ||
285 | }; | 293 | }; |
286 | 294 | ||
287 | /* Uart divisor latch read */ | 295 | /* Uart divisor latch read */ |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 5410c0637266..34e71874a892 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -208,6 +208,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { | |||
208 | { .compatible = "ns16750", .data = (void *)PORT_16750, }, | 208 | { .compatible = "ns16750", .data = (void *)PORT_16750, }, |
209 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, | 209 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, |
210 | { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, | 210 | { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, |
211 | { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, | ||
211 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | 212 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL |
212 | { .compatible = "ibm,qpace-nwp-serial", | 213 | { .compatible = "ibm,qpace-nwp-serial", |
213 | .data = (void *)PORT_NWPSERIAL, }, | 214 | .data = (void *)PORT_NWPSERIAL, }, |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 4fdec6a6b758..558ce8509a9a 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -253,6 +253,9 @@ struct eg20t_port { | |||
253 | dma_addr_t rx_buf_dma; | 253 | dma_addr_t rx_buf_dma; |
254 | 254 | ||
255 | struct dentry *debugfs; | 255 | struct dentry *debugfs; |
256 | |||
257 | /* protect the eg20t_port private structure and io access to membase */ | ||
258 | spinlock_t lock; | ||
256 | }; | 259 | }; |
257 | 260 | ||
258 | /** | 261 | /** |
@@ -754,7 +757,8 @@ static void pch_dma_rx_complete(void *arg) | |||
754 | tty_flip_buffer_push(tty); | 757 | tty_flip_buffer_push(tty); |
755 | tty_kref_put(tty); | 758 | tty_kref_put(tty); |
756 | async_tx_ack(priv->desc_rx); | 759 | async_tx_ack(priv->desc_rx); |
757 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); | 760 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | |
761 | PCH_UART_HAL_RX_ERR_INT); | ||
758 | } | 762 | } |
759 | 763 | ||
760 | static void pch_dma_tx_complete(void *arg) | 764 | static void pch_dma_tx_complete(void *arg) |
@@ -809,7 +813,8 @@ static int handle_rx_to(struct eg20t_port *priv) | |||
809 | int rx_size; | 813 | int rx_size; |
810 | int ret; | 814 | int ret; |
811 | if (!priv->start_rx) { | 815 | if (!priv->start_rx) { |
812 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); | 816 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | |
817 | PCH_UART_HAL_RX_ERR_INT); | ||
813 | return 0; | 818 | return 0; |
814 | } | 819 | } |
815 | buf = &priv->rxbuf; | 820 | buf = &priv->rxbuf; |
@@ -1058,7 +1063,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
1058 | int next = 1; | 1063 | int next = 1; |
1059 | u8 msr; | 1064 | u8 msr; |
1060 | 1065 | ||
1061 | spin_lock_irqsave(&priv->port.lock, flags); | 1066 | spin_lock_irqsave(&priv->lock, flags); |
1062 | handled = 0; | 1067 | handled = 0; |
1063 | while (next) { | 1068 | while (next) { |
1064 | iid = pch_uart_hal_get_iid(priv); | 1069 | iid = pch_uart_hal_get_iid(priv); |
@@ -1078,11 +1083,13 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
1078 | case PCH_UART_IID_RDR: /* Received Data Ready */ | 1083 | case PCH_UART_IID_RDR: /* Received Data Ready */ |
1079 | if (priv->use_dma) { | 1084 | if (priv->use_dma) { |
1080 | pch_uart_hal_disable_interrupt(priv, | 1085 | pch_uart_hal_disable_interrupt(priv, |
1081 | PCH_UART_HAL_RX_INT); | 1086 | PCH_UART_HAL_RX_INT | |
1087 | PCH_UART_HAL_RX_ERR_INT); | ||
1082 | ret = dma_handle_rx(priv); | 1088 | ret = dma_handle_rx(priv); |
1083 | if (!ret) | 1089 | if (!ret) |
1084 | pch_uart_hal_enable_interrupt(priv, | 1090 | pch_uart_hal_enable_interrupt(priv, |
1085 | PCH_UART_HAL_RX_INT); | 1091 | PCH_UART_HAL_RX_INT | |
1092 | PCH_UART_HAL_RX_ERR_INT); | ||
1086 | } else { | 1093 | } else { |
1087 | ret = handle_rx(priv); | 1094 | ret = handle_rx(priv); |
1088 | } | 1095 | } |
@@ -1116,7 +1123,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
1116 | handled |= (unsigned int)ret; | 1123 | handled |= (unsigned int)ret; |
1117 | } | 1124 | } |
1118 | 1125 | ||
1119 | spin_unlock_irqrestore(&priv->port.lock, flags); | 1126 | spin_unlock_irqrestore(&priv->lock, flags); |
1120 | return IRQ_RETVAL(handled); | 1127 | return IRQ_RETVAL(handled); |
1121 | } | 1128 | } |
1122 | 1129 | ||
@@ -1208,7 +1215,8 @@ static void pch_uart_stop_rx(struct uart_port *port) | |||
1208 | struct eg20t_port *priv; | 1215 | struct eg20t_port *priv; |
1209 | priv = container_of(port, struct eg20t_port, port); | 1216 | priv = container_of(port, struct eg20t_port, port); |
1210 | priv->start_rx = 0; | 1217 | priv->start_rx = 0; |
1211 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); | 1218 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | |
1219 | PCH_UART_HAL_RX_ERR_INT); | ||
1212 | } | 1220 | } |
1213 | 1221 | ||
1214 | /* Enable the modem status interrupts. */ | 1222 | /* Enable the modem status interrupts. */ |
@@ -1226,9 +1234,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl) | |||
1226 | unsigned long flags; | 1234 | unsigned long flags; |
1227 | 1235 | ||
1228 | priv = container_of(port, struct eg20t_port, port); | 1236 | priv = container_of(port, struct eg20t_port, port); |
1229 | spin_lock_irqsave(&port->lock, flags); | 1237 | spin_lock_irqsave(&priv->lock, flags); |
1230 | pch_uart_hal_set_break(priv, ctl); | 1238 | pch_uart_hal_set_break(priv, ctl); |
1231 | spin_unlock_irqrestore(&port->lock, flags); | 1239 | spin_unlock_irqrestore(&priv->lock, flags); |
1232 | } | 1240 | } |
1233 | 1241 | ||
1234 | /* Grab any interrupt resources and initialise any low level driver state. */ | 1242 | /* Grab any interrupt resources and initialise any low level driver state. */ |
@@ -1263,6 +1271,7 @@ static int pch_uart_startup(struct uart_port *port) | |||
1263 | break; | 1271 | break; |
1264 | case 16: | 1272 | case 16: |
1265 | fifo_size = PCH_UART_HAL_FIFO16; | 1273 | fifo_size = PCH_UART_HAL_FIFO16; |
1274 | break; | ||
1266 | case 1: | 1275 | case 1: |
1267 | default: | 1276 | default: |
1268 | fifo_size = PCH_UART_HAL_FIFO_DIS; | 1277 | fifo_size = PCH_UART_HAL_FIFO_DIS; |
@@ -1300,7 +1309,8 @@ static int pch_uart_startup(struct uart_port *port) | |||
1300 | pch_request_dma(port); | 1309 | pch_request_dma(port); |
1301 | 1310 | ||
1302 | priv->start_rx = 1; | 1311 | priv->start_rx = 1; |
1303 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); | 1312 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | |
1313 | PCH_UART_HAL_RX_ERR_INT); | ||
1304 | uart_update_timeout(port, CS8, default_baud); | 1314 | uart_update_timeout(port, CS8, default_baud); |
1305 | 1315 | ||
1306 | return 0; | 1316 | return 0; |
@@ -1358,7 +1368,7 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
1358 | stb = PCH_UART_HAL_STB1; | 1368 | stb = PCH_UART_HAL_STB1; |
1359 | 1369 | ||
1360 | if (termios->c_cflag & PARENB) { | 1370 | if (termios->c_cflag & PARENB) { |
1361 | if (!(termios->c_cflag & PARODD)) | 1371 | if (termios->c_cflag & PARODD) |
1362 | parity = PCH_UART_HAL_PARITY_ODD; | 1372 | parity = PCH_UART_HAL_PARITY_ODD; |
1363 | else | 1373 | else |
1364 | parity = PCH_UART_HAL_PARITY_EVEN; | 1374 | parity = PCH_UART_HAL_PARITY_EVEN; |
@@ -1376,7 +1386,8 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
1376 | 1386 | ||
1377 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | 1387 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); |
1378 | 1388 | ||
1379 | spin_lock_irqsave(&port->lock, flags); | 1389 | spin_lock_irqsave(&priv->lock, flags); |
1390 | spin_lock(&port->lock); | ||
1380 | 1391 | ||
1381 | uart_update_timeout(port, termios->c_cflag, baud); | 1392 | uart_update_timeout(port, termios->c_cflag, baud); |
1382 | rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); | 1393 | rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); |
@@ -1389,7 +1400,8 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
1389 | tty_termios_encode_baud_rate(termios, baud, baud); | 1400 | tty_termios_encode_baud_rate(termios, baud, baud); |
1390 | 1401 | ||
1391 | out: | 1402 | out: |
1392 | spin_unlock_irqrestore(&port->lock, flags); | 1403 | spin_unlock(&port->lock); |
1404 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1393 | } | 1405 | } |
1394 | 1406 | ||
1395 | static const char *pch_uart_type(struct uart_port *port) | 1407 | static const char *pch_uart_type(struct uart_port *port) |
@@ -1538,8 +1550,9 @@ pch_console_write(struct console *co, const char *s, unsigned int count) | |||
1538 | { | 1550 | { |
1539 | struct eg20t_port *priv; | 1551 | struct eg20t_port *priv; |
1540 | unsigned long flags; | 1552 | unsigned long flags; |
1553 | int priv_locked = 1; | ||
1554 | int port_locked = 1; | ||
1541 | u8 ier; | 1555 | u8 ier; |
1542 | int locked = 1; | ||
1543 | 1556 | ||
1544 | priv = pch_uart_ports[co->index]; | 1557 | priv = pch_uart_ports[co->index]; |
1545 | 1558 | ||
@@ -1547,12 +1560,16 @@ pch_console_write(struct console *co, const char *s, unsigned int count) | |||
1547 | 1560 | ||
1548 | local_irq_save(flags); | 1561 | local_irq_save(flags); |
1549 | if (priv->port.sysrq) { | 1562 | if (priv->port.sysrq) { |
1550 | /* serial8250_handle_port() already took the lock */ | 1563 | spin_lock(&priv->lock); |
1551 | locked = 0; | 1564 | /* serial8250_handle_port() already took the port lock */ |
1565 | port_locked = 0; | ||
1552 | } else if (oops_in_progress) { | 1566 | } else if (oops_in_progress) { |
1553 | locked = spin_trylock(&priv->port.lock); | 1567 | priv_locked = spin_trylock(&priv->lock); |
1554 | } else | 1568 | port_locked = spin_trylock(&priv->port.lock); |
1569 | } else { | ||
1570 | spin_lock(&priv->lock); | ||
1555 | spin_lock(&priv->port.lock); | 1571 | spin_lock(&priv->port.lock); |
1572 | } | ||
1556 | 1573 | ||
1557 | /* | 1574 | /* |
1558 | * First save the IER then disable the interrupts | 1575 | * First save the IER then disable the interrupts |
@@ -1570,8 +1587,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count) | |||
1570 | wait_for_xmitr(priv, BOTH_EMPTY); | 1587 | wait_for_xmitr(priv, BOTH_EMPTY); |
1571 | iowrite8(ier, priv->membase + UART_IER); | 1588 | iowrite8(ier, priv->membase + UART_IER); |
1572 | 1589 | ||
1573 | if (locked) | 1590 | if (port_locked) |
1574 | spin_unlock(&priv->port.lock); | 1591 | spin_unlock(&priv->port.lock); |
1592 | if (priv_locked) | ||
1593 | spin_unlock(&priv->lock); | ||
1575 | local_irq_restore(flags); | 1594 | local_irq_restore(flags); |
1576 | } | 1595 | } |
1577 | 1596 | ||
@@ -1669,6 +1688,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1669 | pci_enable_msi(pdev); | 1688 | pci_enable_msi(pdev); |
1670 | pci_set_master(pdev); | 1689 | pci_set_master(pdev); |
1671 | 1690 | ||
1691 | spin_lock_init(&priv->lock); | ||
1692 | |||
1672 | iobase = pci_resource_start(pdev, 0); | 1693 | iobase = pci_resource_start(pdev, 0); |
1673 | mapbase = pci_resource_start(pdev, 1); | 1694 | mapbase = pci_resource_start(pdev, 1); |
1674 | priv->mapbase = mapbase; | 1695 | priv->mapbase = mapbase; |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index d8b0aee35632..02d07bfcfa8a 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1014,10 +1014,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, | |||
1014 | * a disturbance in the clock-rate over the change. | 1014 | * a disturbance in the clock-rate over the change. |
1015 | */ | 1015 | */ |
1016 | 1016 | ||
1017 | if (IS_ERR(port->clk)) | 1017 | if (IS_ERR(port->baudclk)) |
1018 | goto exit; | 1018 | goto exit; |
1019 | 1019 | ||
1020 | if (port->baudclk_rate == clk_get_rate(port->clk)) | 1020 | if (port->baudclk_rate == clk_get_rate(port->baudclk)) |
1021 | goto exit; | 1021 | goto exit; |
1022 | 1022 | ||
1023 | if (val == CPUFREQ_PRECHANGE) { | 1023 | if (val == CPUFREQ_PRECHANGE) { |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 246b823c1b27..a21dc8e3b7c0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -2527,14 +2527,16 @@ void uart_insert_char(struct uart_port *port, unsigned int status, | |||
2527 | struct tty_struct *tty = port->state->port.tty; | 2527 | struct tty_struct *tty = port->state->port.tty; |
2528 | 2528 | ||
2529 | if ((status & port->ignore_status_mask & ~overrun) == 0) | 2529 | if ((status & port->ignore_status_mask & ~overrun) == 0) |
2530 | tty_insert_flip_char(tty, ch, flag); | 2530 | if (tty_insert_flip_char(tty, ch, flag) == 0) |
2531 | ++port->icount.buf_overrun; | ||
2531 | 2532 | ||
2532 | /* | 2533 | /* |
2533 | * Overrun is special. Since it's reported immediately, | 2534 | * Overrun is special. Since it's reported immediately, |
2534 | * it doesn't affect the current character. | 2535 | * it doesn't affect the current character. |
2535 | */ | 2536 | */ |
2536 | if (status & ~port->ignore_status_mask & overrun) | 2537 | if (status & ~port->ignore_status_mask & overrun) |
2537 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 2538 | if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0) |
2539 | ++port->icount.buf_overrun; | ||
2538 | } | 2540 | } |
2539 | EXPORT_SYMBOL_GPL(uart_insert_char); | 2541 | EXPORT_SYMBOL_GPL(uart_insert_char); |
2540 | 2542 | ||
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 9911eb6b34cd..6f99c9959f0c 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -659,7 +659,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
659 | goto enable; | 659 | goto enable; |
660 | } | 660 | } |
661 | 661 | ||
662 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 662 | if (test_bit(TTY_HUPPING, &tty->flags)) { |
663 | /* We were raced by the hangup method. It will have stomped | 663 | /* We were raced by the hangup method. It will have stomped |
664 | the ldisc data and closed the ldisc down */ | 664 | the ldisc data and closed the ldisc down */ |
665 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 665 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 64618547be11..b841f56d2e66 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
@@ -110,16 +110,7 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new) | |||
110 | wake_up_interruptible(&vt_event_waitqueue); | 110 | wake_up_interruptible(&vt_event_waitqueue); |
111 | } | 111 | } |
112 | 112 | ||
113 | /** | 113 | static void __vt_event_queue(struct vt_event_wait *vw) |
114 | * vt_event_wait - wait for an event | ||
115 | * @vw: our event | ||
116 | * | ||
117 | * Waits for an event to occur which completes our vt_event_wait | ||
118 | * structure. On return the structure has wv->done set to 1 for success | ||
119 | * or 0 if some event such as a signal ended the wait. | ||
120 | */ | ||
121 | |||
122 | static void vt_event_wait(struct vt_event_wait *vw) | ||
123 | { | 114 | { |
124 | unsigned long flags; | 115 | unsigned long flags; |
125 | /* Prepare the event */ | 116 | /* Prepare the event */ |
@@ -129,8 +120,18 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
129 | spin_lock_irqsave(&vt_event_lock, flags); | 120 | spin_lock_irqsave(&vt_event_lock, flags); |
130 | list_add(&vw->list, &vt_events); | 121 | list_add(&vw->list, &vt_events); |
131 | spin_unlock_irqrestore(&vt_event_lock, flags); | 122 | spin_unlock_irqrestore(&vt_event_lock, flags); |
123 | } | ||
124 | |||
125 | static void __vt_event_wait(struct vt_event_wait *vw) | ||
126 | { | ||
132 | /* Wait for it to pass */ | 127 | /* Wait for it to pass */ |
133 | wait_event_interruptible(vt_event_waitqueue, vw->done); | 128 | wait_event_interruptible(vt_event_waitqueue, vw->done); |
129 | } | ||
130 | |||
131 | static void __vt_event_dequeue(struct vt_event_wait *vw) | ||
132 | { | ||
133 | unsigned long flags; | ||
134 | |||
134 | /* Dequeue it */ | 135 | /* Dequeue it */ |
135 | spin_lock_irqsave(&vt_event_lock, flags); | 136 | spin_lock_irqsave(&vt_event_lock, flags); |
136 | list_del(&vw->list); | 137 | list_del(&vw->list); |
@@ -138,6 +139,22 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
138 | } | 139 | } |
139 | 140 | ||
140 | /** | 141 | /** |
142 | * vt_event_wait - wait for an event | ||
143 | * @vw: our event | ||
144 | * | ||
145 | * Waits for an event to occur which completes our vt_event_wait | ||
146 | * structure. On return the structure has wv->done set to 1 for success | ||
147 | * or 0 if some event such as a signal ended the wait. | ||
148 | */ | ||
149 | |||
150 | static void vt_event_wait(struct vt_event_wait *vw) | ||
151 | { | ||
152 | __vt_event_queue(vw); | ||
153 | __vt_event_wait(vw); | ||
154 | __vt_event_dequeue(vw); | ||
155 | } | ||
156 | |||
157 | /** | ||
141 | * vt_event_wait_ioctl - event ioctl handler | 158 | * vt_event_wait_ioctl - event ioctl handler |
142 | * @arg: argument to ioctl | 159 | * @arg: argument to ioctl |
143 | * | 160 | * |
@@ -177,10 +194,14 @@ int vt_waitactive(int n) | |||
177 | { | 194 | { |
178 | struct vt_event_wait vw; | 195 | struct vt_event_wait vw; |
179 | do { | 196 | do { |
180 | if (n == fg_console + 1) | ||
181 | break; | ||
182 | vw.event.event = VT_EVENT_SWITCH; | 197 | vw.event.event = VT_EVENT_SWITCH; |
183 | vt_event_wait(&vw); | 198 | __vt_event_queue(&vw); |
199 | if (n == fg_console + 1) { | ||
200 | __vt_event_dequeue(&vw); | ||
201 | break; | ||
202 | } | ||
203 | __vt_event_wait(&vw); | ||
204 | __vt_event_dequeue(&vw); | ||
184 | if (vw.done == 0) | 205 | if (vw.done == 0) |
185 | return -EINTR; | 206 | return -EINTR; |
186 | } while (vw.event.newev != n); | 207 | } while (vw.event.newev != n); |