aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-27 15:52:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-27 15:52:03 -0400
commitc1e7179a38919f02dd950801529176b72f5e5a8a (patch)
tree70b014e6f48768d38b984de3a3fc1cd53201933d /drivers/tty
parent84eda28060f7e7d5f91f81f928532af13b9e44b2 (diff)
parent38bd2a1ac736901d1cf4971c78ef952ba92ef78b (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/tty')
-rw-r--r--drivers/tty/serial/8250/8250.c8
-rw-r--r--drivers/tty/serial/of_serial.c1
-rw-r--r--drivers/tty/serial/pch_uart.c59
-rw-r--r--drivers/tty/serial/samsung.c4
-rw-r--r--drivers/tty/serial/serial_core.c6
-rw-r--r--drivers/tty/tty_ldisc.c2
-rw-r--r--drivers/tty/vt/vt_ioctl.c47
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
760static void pch_dma_tx_complete(void *arg) 764static 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
1391out: 1402out:
1392 spin_unlock_irqrestore(&port->lock, flags); 1403 spin_unlock(&port->lock);
1404 spin_unlock_irqrestore(&priv->lock, flags);
1393} 1405}
1394 1406
1395static const char *pch_uart_type(struct uart_port *port) 1407static 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}
2539EXPORT_SYMBOL_GPL(uart_insert_char); 2541EXPORT_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/** 113static 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
122static 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
125static 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
131static 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
150static 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);