Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b48e16 authored by Shinya Kuribayashi's avatar Shinya Kuribayashi Committed by Greg Kroah-Hartman
Browse files

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 9ec1882d
(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: default avatarShinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 40f70c03
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1743,6 +1743,7 @@ static inline void sci_free_dma(struct uart_port *port)
static int sci_startup(struct uart_port *port)
{
	struct sci_port *s = to_sci_port(port);
	unsigned long flags;
	int ret;

	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
@@ -1753,8 +1754,10 @@ static int sci_startup(struct uart_port *port)

	sci_request_dma(port);

	spin_lock_irqsave(&port->lock, flags);
	sci_start_tx(port);
	sci_start_rx(port);
	spin_unlock_irqrestore(&port->lock, flags);

	return 0;
}
@@ -1762,11 +1765,14 @@ static int sci_startup(struct uart_port *port)
static void sci_shutdown(struct uart_port *port)
{
	struct sci_port *s = to_sci_port(port);
	unsigned long flags;

	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);

	spin_lock_irqsave(&port->lock, flags);
	sci_stop_rx(port);
	sci_stop_tx(port);
	spin_unlock_irqrestore(&port->lock, flags);

	sci_free_dma(port);
	sci_free_irq(s);