diff options
Diffstat (limited to 'drivers/serial/mpsc.c')
-rw-r--r-- | drivers/serial/mpsc.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 3d2fcc57b1ce..d09f2097d5b0 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c | |||
@@ -183,6 +183,7 @@ struct mpsc_port_info { | |||
183 | u8 *txb_p; /* Phys addr of txb */ | 183 | u8 *txb_p; /* Phys addr of txb */ |
184 | int txr_head; /* Where new data goes */ | 184 | int txr_head; /* Where new data goes */ |
185 | int txr_tail; /* Where sent data comes off */ | 185 | int txr_tail; /* Where sent data comes off */ |
186 | spinlock_t tx_lock; /* transmit lock */ | ||
186 | 187 | ||
187 | /* Mirrored values of regs we can't read (if 'mirror_regs' set) */ | 188 | /* Mirrored values of regs we can't read (if 'mirror_regs' set) */ |
188 | u32 MPSC_MPCR_m; | 189 | u32 MPSC_MPCR_m; |
@@ -1212,6 +1213,9 @@ mpsc_tx_intr(struct mpsc_port_info *pi) | |||
1212 | { | 1213 | { |
1213 | struct mpsc_tx_desc *txre; | 1214 | struct mpsc_tx_desc *txre; |
1214 | int rc = 0; | 1215 | int rc = 0; |
1216 | unsigned long iflags; | ||
1217 | |||
1218 | spin_lock_irqsave(&pi->tx_lock, iflags); | ||
1215 | 1219 | ||
1216 | if (!mpsc_sdma_tx_active(pi)) { | 1220 | if (!mpsc_sdma_tx_active(pi)) { |
1217 | txre = (struct mpsc_tx_desc *)(pi->txr + | 1221 | txre = (struct mpsc_tx_desc *)(pi->txr + |
@@ -1248,6 +1252,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) | |||
1248 | mpsc_sdma_start_tx(pi); /* start next desc if ready */ | 1252 | mpsc_sdma_start_tx(pi); /* start next desc if ready */ |
1249 | } | 1253 | } |
1250 | 1254 | ||
1255 | spin_unlock_irqrestore(&pi->tx_lock, iflags); | ||
1251 | return rc; | 1256 | return rc; |
1252 | } | 1257 | } |
1253 | 1258 | ||
@@ -1338,11 +1343,16 @@ static void | |||
1338 | mpsc_start_tx(struct uart_port *port) | 1343 | mpsc_start_tx(struct uart_port *port) |
1339 | { | 1344 | { |
1340 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | 1345 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; |
1346 | unsigned long iflags; | ||
1347 | |||
1348 | spin_lock_irqsave(&pi->tx_lock, iflags); | ||
1341 | 1349 | ||
1342 | mpsc_unfreeze(pi); | 1350 | mpsc_unfreeze(pi); |
1343 | mpsc_copy_tx_data(pi); | 1351 | mpsc_copy_tx_data(pi); |
1344 | mpsc_sdma_start_tx(pi); | 1352 | mpsc_sdma_start_tx(pi); |
1345 | 1353 | ||
1354 | spin_unlock_irqrestore(&pi->tx_lock, iflags); | ||
1355 | |||
1346 | pr_debug("mpsc_start_tx[%d]\n", port->line); | 1356 | pr_debug("mpsc_start_tx[%d]\n", port->line); |
1347 | return; | 1357 | return; |
1348 | } | 1358 | } |
@@ -1625,6 +1635,16 @@ mpsc_console_write(struct console *co, const char *s, uint count) | |||
1625 | struct mpsc_port_info *pi = &mpsc_ports[co->index]; | 1635 | struct mpsc_port_info *pi = &mpsc_ports[co->index]; |
1626 | u8 *bp, *dp, add_cr = 0; | 1636 | u8 *bp, *dp, add_cr = 0; |
1627 | int i; | 1637 | int i; |
1638 | unsigned long iflags; | ||
1639 | |||
1640 | spin_lock_irqsave(&pi->tx_lock, iflags); | ||
1641 | |||
1642 | while (pi->txr_head != pi->txr_tail) { | ||
1643 | while (mpsc_sdma_tx_active(pi)) | ||
1644 | udelay(100); | ||
1645 | mpsc_sdma_intr_ack(pi); | ||
1646 | mpsc_tx_intr(pi); | ||
1647 | } | ||
1628 | 1648 | ||
1629 | while (mpsc_sdma_tx_active(pi)) | 1649 | while (mpsc_sdma_tx_active(pi)) |
1630 | udelay(100); | 1650 | udelay(100); |
@@ -1668,6 +1688,7 @@ mpsc_console_write(struct console *co, const char *s, uint count) | |||
1668 | pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1); | 1688 | pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1); |
1669 | } | 1689 | } |
1670 | 1690 | ||
1691 | spin_unlock_irqrestore(&pi->tx_lock, iflags); | ||
1671 | return; | 1692 | return; |
1672 | } | 1693 | } |
1673 | 1694 | ||
@@ -2005,7 +2026,8 @@ mpsc_drv_probe(struct platform_device *dev) | |||
2005 | if (!(rc = mpsc_drv_map_regs(pi, dev))) { | 2026 | if (!(rc = mpsc_drv_map_regs(pi, dev))) { |
2006 | mpsc_drv_get_platform_data(pi, dev, dev->id); | 2027 | mpsc_drv_get_platform_data(pi, dev, dev->id); |
2007 | 2028 | ||
2008 | if (!(rc = mpsc_make_ready(pi))) | 2029 | if (!(rc = mpsc_make_ready(pi))) { |
2030 | spin_lock_init(&pi->tx_lock); | ||
2009 | if (!(rc = uart_add_one_port(&mpsc_reg, | 2031 | if (!(rc = uart_add_one_port(&mpsc_reg, |
2010 | &pi->port))) | 2032 | &pi->port))) |
2011 | rc = 0; | 2033 | rc = 0; |
@@ -2014,6 +2036,7 @@ mpsc_drv_probe(struct platform_device *dev) | |||
2014 | (struct uart_port *)pi); | 2036 | (struct uart_port *)pi); |
2015 | mpsc_drv_unmap_regs(pi); | 2037 | mpsc_drv_unmap_regs(pi); |
2016 | } | 2038 | } |
2039 | } | ||
2017 | else | 2040 | else |
2018 | mpsc_drv_unmap_regs(pi); | 2041 | mpsc_drv_unmap_regs(pi); |
2019 | } | 2042 | } |