aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2012-01-17 05:52:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-24 19:09:55 -0500
commitef605fdb33883d687cff5ba75095a91b313b4966 (patch)
tree7eea2b5b397d0b5373ec76035bf924d3885b2489 /drivers/tty/serial/amba-pl011.c
parentd8d8ffa477831b713ddfa2ad4d0ca545f3b567e5 (diff)
serial: amba-pl011: lock console writes against interrupts
Protect against pl011_console_write() and the interrupt for the console UART running concurrently on different CPUs. Otherwise the console_write could spin for a long time waiting for the UART to become not busy, while the other CPU continuously services UART interrupts and keeps the UART busy. The checks for sysrq and oops_in_progress are taken from 8250.c. Cc: stable <stable@vger.kernel.org> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Reviewed-by: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> Reviewed-by: Bibek Basu <bibek.basu@stericsson.com> Reviewed-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r--drivers/tty/serial/amba-pl011.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index ce843d058e02..6800f5f26241 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1751,9 +1751,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
1751{ 1751{
1752 struct uart_amba_port *uap = amba_ports[co->index]; 1752 struct uart_amba_port *uap = amba_ports[co->index];
1753 unsigned int status, old_cr, new_cr; 1753 unsigned int status, old_cr, new_cr;
1754 unsigned long flags;
1755 int locked = 1;
1754 1756
1755 clk_enable(uap->clk); 1757 clk_enable(uap->clk);
1756 1758
1759 local_irq_save(flags);
1760 if (uap->port.sysrq)
1761 locked = 0;
1762 else if (oops_in_progress)
1763 locked = spin_trylock(&uap->port.lock);
1764 else
1765 spin_lock(&uap->port.lock);
1766
1757 /* 1767 /*
1758 * First save the CR then disable the interrupts 1768 * First save the CR then disable the interrupts
1759 */ 1769 */
@@ -1773,6 +1783,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
1773 } while (status & UART01x_FR_BUSY); 1783 } while (status & UART01x_FR_BUSY);
1774 writew(old_cr, uap->port.membase + UART011_CR); 1784 writew(old_cr, uap->port.membase + UART011_CR);
1775 1785
1786 if (locked)
1787 spin_unlock(&uap->port.lock);
1788 local_irq_restore(flags);
1789
1776 clk_disable(uap->clk); 1790 clk_disable(uap->clk);
1777} 1791}
1778 1792