[PATCH 3/3] serial: pl011: allow very high baudrates

Linus Walleij linus.walleij at linaro.org
Fri Sep 21 13:52:04 EDT 2012


On Fri, Sep 21, 2012 at 5:25 PM, Alan Cox <alan at lxorguk.ukuu.org.uk> wrote:

> Untested but I suspect the following may help

Nope it doesn't, it's not this part that goes wrong, it's the call to
tty_termios_encode_baud_rate() that is the problem, not how it
gets called. It's that function that fuzzes and "snaps" the baudrate
to some rough-fit speed and screws things up for me.

But I looked a bit at the patch as such.

It doesn't compile, but when I fix it like this:

> -               if (baud >= min && baud <= max)
> +               if (baud >= min && baud <= max) {
> +                       tty_termios_encode_baud_rate(tty, baud, baud);

s/tty/termios/

Then it compiles, but regresses.

What's going wrong is that the termios encoding of zero does
not happen anymore, for baudrate 0, i.e whereas we used to
encode 0 into termios and then return 9600 this encodes
9600 and returns 9600.

So if I handle baudrate 9600 specially instead like this it works:

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 7d9fbb8..a2442fb 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -351,8 +351,9 @@ uart_get_baud_rate(struct uart_port *port, struct
ktermios *termios,
 	else if (flags == UPF_SPD_WARP)
 		altbaud = 460800;

+	baud = tty_termios_baud_rate(termios);
+
 	for (try = 0; try < 2; try++) {
-		baud = tty_termios_baud_rate(termios);

 		/*
 		 * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
@@ -362,26 +363,27 @@ uart_get_baud_rate(struct uart_port *port,
struct ktermios *termios,
 			baud = altbaud;

 		/*
-		 * Special case: B0 rate.
+		 * Special case: B0 rate. Note: this breaks if the
+		 * device cannot support 9600 baud
 		 */
 		if (baud == 0) {
 			hung_up = 1;
-			baud = 9600;
+			/* Encode zeroes to preserve semantics */
+			tty_termios_encode_baud_rate(termios, 0, 0);
+			return 9600;
 		}

-		if (baud >= min && baud <= max)
+		if (baud >= min && baud <= max) {
+			tty_termios_encode_baud_rate(termios, baud, baud);
 			return baud;
+		}

 		/*
 		 * Oops, the quotient was zero.  Try again with
 		 * the old baud rate if possible.
 		 */
-		termios->c_cflag &= ~CBAUD;
 		if (old) {
 			baud = tty_termios_baud_rate(old);
-			if (!hung_up)
-				tty_termios_encode_baud_rate(termios,
-								baud, baud);
 			old = NULL;
 			continue;
 		}
@@ -392,11 +394,9 @@ uart_get_baud_rate(struct uart_port *port, struct
ktermios *termios,
 		 */
 		if (!hung_up) {
 			if (baud <= min)
-				tty_termios_encode_baud_rate(termios,
-							min + 1, min + 1);
+				baud = min + 1;
 			else
-				tty_termios_encode_baud_rate(termios,
-							max - 1, max - 1);
+				baud = max - 1;
 		}
 	}
 	/* Should never happen */

(FWIW Signed-off-by: Linus Walleij <linus.walleij at linaro.org> for the twoliner)

But as mentioned I get the same errors...

Yours,
Linus Walleij



More information about the linux-arm-kernel mailing list