aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sh-sci.c
diff options
context:
space:
mode:
authorShinya Kuribayashi <shinya.kuribayashi.px@renesas.com>2012-11-15 20:54:49 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-15 21:02:51 -0500
commit33b48e1633f738c5ae78234c2dd5e3a9ba115437 (patch)
tree09193c93ad60bdd24e34e382439baa129e2aa02b /drivers/tty/serial/sh-sci.c
parent40f70c03e33a1eed3f3fcd13418e76abad77d117 (diff)
serial: sh-sci: fix possible race cases on SCSCR register accesses
In the previous commit, console write function (serial_console_write) is changed to disable SCI interrupts while printing console strings. This introduces possible race cases in the serial startup / shutdown functions on SMP systems. This patch fixes the sh-sci in the same way as commit 9ec1882df2 (tty: serial: imx: console write routing is unsafe on SMP, from Xinyu Chen <xinyu.chen@freescale.com>, 2012-08-27) did. There could be several consumers of the console, * the kernel printk * the init process using /dev/kmsg to call printk to show log * shell, which opens /dev/console and writes with sys_write() The shell goes into the normal UART open() and write() system calls, while the other two go into the console operations. The open() call invokes serial startup function (sci_startup), which will write to the SCSCR register (to enable or disable SCI interrupts) without any locking. This will conflict with the console serial function. Add spinlock protections in sci_startup() and sci_shutdown() properly. Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r--drivers/tty/serial/sh-sci.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 63a23eadd7e8..d38c0f546032 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1743,6 +1743,7 @@ static inline void sci_free_dma(struct uart_port *port)
1743static int sci_startup(struct uart_port *port) 1743static int sci_startup(struct uart_port *port)
1744{ 1744{
1745 struct sci_port *s = to_sci_port(port); 1745 struct sci_port *s = to_sci_port(port);
1746 unsigned long flags;
1746 int ret; 1747 int ret;
1747 1748
1748 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); 1749 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
@@ -1753,8 +1754,10 @@ static int sci_startup(struct uart_port *port)
1753 1754
1754 sci_request_dma(port); 1755 sci_request_dma(port);
1755 1756
1757 spin_lock_irqsave(&port->lock, flags);
1756 sci_start_tx(port); 1758 sci_start_tx(port);
1757 sci_start_rx(port); 1759 sci_start_rx(port);
1760 spin_unlock_irqrestore(&port->lock, flags);
1758 1761
1759 return 0; 1762 return 0;
1760} 1763}
@@ -1762,11 +1765,14 @@ static int sci_startup(struct uart_port *port)
1762static void sci_shutdown(struct uart_port *port) 1765static void sci_shutdown(struct uart_port *port)
1763{ 1766{
1764 struct sci_port *s = to_sci_port(port); 1767 struct sci_port *s = to_sci_port(port);
1768 unsigned long flags;
1765 1769
1766 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); 1770 dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
1767 1771
1772 spin_lock_irqsave(&port->lock, flags);
1768 sci_stop_rx(port); 1773 sci_stop_rx(port);
1769 sci_stop_tx(port); 1774 sci_stop_tx(port);
1775 spin_unlock_irqrestore(&port->lock, flags);
1770 1776
1771 sci_free_dma(port); 1777 sci_free_dma(port);
1772 sci_free_irq(s); 1778 sci_free_irq(s);