Re: [PATCH v4] earlycon: 8250: Fix command line regression

From: Yinghai Lu
Date: Sun Apr 05 2015 - 16:14:43 EST


On Sun, Apr 5, 2015 at 6:06 AM, Peter Hurley <peter@xxxxxxxxxxxxxxxxxx> wrote:
> On 04/05/2015 03:09 AM, Yinghai Lu wrote:

> On what planet is 27 loc across 4 source files cleaner than
> 6 loc that might be reducible to 2?

loc is not only thing to decide if it is cleaner.

Let's Greg and Andrew to check which one is clean.
Subject: [PATCH -v3] earlycon: Fix earlycon/console handover without options

commit c7cef0a84912 ("console: Add extensible console matching")
broke the earlycon/handover when booting
console=uart8250,io,0x3f8

the bootloader is using 115200, and the earlycon continue
use 115200, but console revert back to 9600.

Before the commit, probed baud rate is passed via console_cmdline
from earlycon to normal console.
That commit remove that and only check boot command line.

This patch use port match to get hold earlycon, and use earlycon
device options to update options for console.

With that we restore the original behavior.

Fixes: commit c7cef0a84912 ("console: Add extensible console matching")
Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>

---
-v2: simplify serial8250_get_earlycon_options and don't update
console_cmdline.
-v3: add earlycon_match to restore original behavior.
---

---
drivers/tty/serial/8250/8250_core.c | 3 +++
drivers/tty/serial/8250/8250_early.c | 7 +++++++
drivers/tty/serial/earlycon.c | 15 +++++++++++++++
include/linux/serial_core.h | 2 ++
4 files changed, 27 insertions(+)

Index: linux-2.6/drivers/tty/serial/8250/8250_core.c
===================================================================
--- linux-2.6.orig/drivers/tty/serial/8250/8250_core.c
+++ linux-2.6/drivers/tty/serial/8250/8250_core.c
@@ -3490,6 +3490,9 @@ static int univ8250_console_match(struct
if (iotype == UPIO_PORT && port->iobase != addr)
continue;

+ if (!earlycon_match(port, &options))
+ return -ENODEV;
+
co->index = i;
return univ8250_console_setup(co, options);
}
Index: linux-2.6/drivers/tty/serial/8250/8250_early.c
===================================================================
--- linux-2.6.orig/drivers/tty/serial/8250/8250_early.c
+++ linux-2.6/drivers/tty/serial/8250/8250_early.c
@@ -105,6 +105,12 @@ static void __init early_serial8250_writ
serial8250_early_out(port, UART_IER, ier);
}

+static int serial8250_earlycon_match(struct earlycon_device *device,
+ struct uart_port *up)
+{
+ return uart_match_port(up, &device->port);
+}
+
static unsigned int __init probe_baud(struct uart_port *port)
{
unsigned char lcr, dll, dlm;
@@ -161,6 +167,7 @@ static int __init early_serial8250_setup
} else
init_port(device);

+ device->match = serial8250_earlycon_match;
device->con->write = early_serial8250_write;
return 0;
}
Index: linux-2.6/drivers/tty/serial/earlycon.c
===================================================================
--- linux-2.6.orig/drivers/tty/serial/earlycon.c
+++ linux-2.6/drivers/tty/serial/earlycon.c
@@ -127,6 +127,21 @@ static int __init register_earlycon(char
return 0;
}

+int earlycon_match(struct uart_port *up, char **options_p)
+{
+ struct earlycon_device *device = &early_console_dev;
+
+ if (!device->con || !(device->con->flags & CON_ENABLED))
+ return 0;
+
+ if (device->match && device->match(device, up)) {
+ *options_p = device->options;
+ return 1;
+ }
+
+ return 0;
+}
+
/**
* setup_earlycon - match and register earlycon console
* @buf: earlycon param string
Index: linux-2.6/include/linux/serial_core.h
===================================================================
--- linux-2.6.orig/include/linux/serial_core.h
+++ linux-2.6/include/linux/serial_core.h
@@ -337,6 +337,7 @@ struct earlycon_device {
struct uart_port port;
char options[16]; /* e.g., 115200n8 */
unsigned int baud;
+ int (*match)(struct earlycon_device *, struct uart_port *);
};

struct earlycon_id {
@@ -344,6 +345,7 @@ struct earlycon_id {
int (*setup)(struct earlycon_device *, const char *options);
};

+extern int earlycon_match(struct uart_port *up, char **options_p);
extern int setup_earlycon(char *buf);
extern int of_setup_earlycon(unsigned long addr,
int (*setup)(struct earlycon_device *, const char *));