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 --- -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 *));