aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/pch_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/pch_uart.c')
-rw-r--r--drivers/tty/serial/pch_uart.c59
1 files changed, 40 insertions, 19 deletions
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;