[PATCH 1/3] serial: pl011: safeguard against impossible baudrates

Linus Walleij linus.walleij at stericsson.com
Thu Sep 20 05:45:46 EDT 2012


From: Linus Walleij <linus.walleij at linaro.org>

The PL011 generates it's bitrate from the clock to the block,
and this in turn will be divided by a minimum of 16 (ARM PL011)
or 8 (ST Micro PL011 derivate). Safeguard against illegal
rates exceeding that of what the port clock can be divided
down to.

Since the clkdiv variable is only ever used for calculating the
maximum baud rate, let's skip that variable and add a new
max_baud variable instead, then use this to check limits and
as parameter for getting the baud rate.

Cc: Par-Gunnar Hjalmdahl <par-gunnar.hjalmdahl at stericsson.com>
Cc: Guillaume Jaunet <guillaume.jaunet at stericsson.com>
Cc: Christophe Arnal <christophe.arnal at stericsson.com>
Cc: Matthias Locher <matthias.locher at stericsson.com>
Cc: Rajanikanth H.V <rajanikanth.hv at stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/tty/serial/amba-pl011.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d626d84..9e16ea6 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1492,18 +1492,25 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int lcr_h, old_cr;
 	unsigned long flags;
-	unsigned int baud, quot, clkdiv;
+	unsigned int max_baud, baud, quot;
 
 	if (uap->vendor->oversampling)
-		clkdiv = 8;
+		max_baud = port->uartclk / 8;
 	else
-		clkdiv = 16;
+		max_baud = port->uartclk / 16;
+
+	if ((termios->c_ispeed > max_baud) ||
+	    (termios->c_ospeed > max_baud)) {
+		dev_err(port->dev,
+			"requested a baud rate > clock/mindivisor\n");
+		return;
+	}
 
 	/*
 	 * Ask the core to calculate the divisor for us.
 	 */
 	baud = uart_get_baud_rate(port, termios, old, 0,
-				  port->uartclk / clkdiv);
+				  max_baud);
 
 	if (baud > port->uartclk/16)
 		quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
-- 
1.7.11.3




More information about the linux-arm-kernel mailing list