[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1391773652-25214-42-git-send-email-luis.henriques@canonical.com>
Date: Fri, 7 Feb 2014 11:44:20 +0000
From: Luis Henriques <luis.henriques@...onical.com>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org,
kernel-team@...ts.ubuntu.com
Cc: Jon Medhurst <tixy@...aro.org>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Luis Henriques <luis.henriques@...onical.com>
Subject: [PATCH 3.11 041/233] serial: amba-pl011: use port lock to guard control register access
3.11.10.4 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jon Medhurst <tixy@...aro.org>
commit fe43390702a1b5741fdf217063b05c7612b38303 upstream.
When the pl011 is being used for a console, pl011_console_write forces
the control register (CR) to enable the UART for transmission and then
restores this to the original value afterwards. It does this while
holding the port lock.
Unfortunately, when the uart is started or shutdown - say in response to
userland using the serial device for a terminal - then this updates the
control register without any locking.
This means we can have
pl011_console_write Save CR
pl011_startup Initialise CR, e.g. enable receive
pl011_console_write Restore old CR with receive not enabled
this result is a serial port which doesn't respond to any input.
A similar race in reverse could happen when the device is shutdown.
We can fix these problems by taking the port lock when updating CR.
Signed-off-by: Jon Medhurst <tixy@...aro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Signed-off-by: Luis Henriques <luis.henriques@...onical.com>
---
drivers/tty/serial/amba-pl011.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 28b35ad..7324301 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1533,6 +1533,8 @@ static int pl011_startup(struct uart_port *port)
/*
* Provoke TX FIFO interrupt into asserting.
*/
+ spin_lock_irq(&uap->port.lock);
+
cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
writew(cr, uap->port.membase + UART011_CR);
writew(0, uap->port.membase + UART011_FBRD);
@@ -1557,6 +1559,8 @@ static int pl011_startup(struct uart_port *port)
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
+ spin_unlock_irq(&uap->port.lock);
+
/*
* initialise the old status of the modem signals
*/
@@ -1625,11 +1629,13 @@ static void pl011_shutdown(struct uart_port *port)
* it during startup().
*/
uap->autorts = false;
+ spin_lock_irq(&uap->port.lock);
cr = readw(uap->port.membase + UART011_CR);
uap->old_cr = cr;
cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
+ spin_unlock_irq(&uap->port.lock);
/*
* disable break condition and fifos
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists