[PATCH] serial: make early_uart to use early_prarm instead of console_initcall Make early_uart to use early_param, so uart console can be used earlier. Make it to be bootconsole with CON_BOOT flag, so can use console handover feature. new command line will be earlycon=uart,io,0x3f8,9600n8 console=ttyS0,9600 it will print in very early stage Early serial console at I/O port 0x3f8 (options '9600n8') later for console it will print console handover: boot [uart0] -> real [ttyS0] Signed-off-by: diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 48e259a..2a76618 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2533,39 +2538,6 @@ static int __init serial8250_console_init(void) } console_initcall(serial8250_console_init); -static int __init find_port(struct uart_port *p) -{ - int line; - struct uart_port *port; - - for (line = 0; line < nr_uarts; line++) { - port = &serial8250_ports[line].port; - if (uart_match_port(p, port)) - return line; - } - return -ENODEV; -} - -int __init serial8250_start_console(struct uart_port *port, char *options) -{ - int line; - - line = find_port(port); - if (line < 0) - return -ENODEV; - - add_preferred_console("ttyS", line, options); - printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", - line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port", - port->iotype == UPIO_MEM ? (unsigned long) port->mapbase : - (unsigned long) port->iobase, options); - if (!(serial8250_console.flags & CON_ENABLED)) { - serial8250_console.flags &= ~CON_PRINTBUFFER; - register_console(&serial8250_console); - } - return line; -} - #define SERIAL8250_CONSOLE &serial8250_console #else #define SERIAL8250_CONSOLE NULL diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 7e51119..f320f8f 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -17,13 +17,9 @@ * we locate the device directly by its MMIO or I/O port address. * * The user can specify the device directly, e.g., - * console=uart,io,0x3f8,9600n8 - * console=uart,mmio,0xff5e0000,115200n8 - * or platform code can call early_uart_console_init() to set - * the early UART device. + * earlycon=uart,io,0x3f8,9600n8 + * earlycon=uart,mmio,0xff5e0000,115200n8 * - * After the normal serial driver starts, we try to locate the - * matching ttyS device and start a console there. */ #include @@ -42,7 +38,6 @@ struct early_uart_device { }; static struct early_uart_device early_device __initdata; -static int early_uart_registered __initdata; static unsigned int __init serial_in(struct uart_port *port, int offset) { @@ -175,6 +170,13 @@ static int __init parse_options(struct early_uart_device *device, char *options) return 0; } +static struct console early_uart_console __initdata = { + .name = "uart", + .write = early_uart_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + static int __init early_uart_setup(struct console *console, char *options) { struct early_uart_device *device = &early_device; @@ -190,61 +192,41 @@ static int __init early_uart_setup(struct console *console, char *options) return 0; } -static struct console early_uart_console __initdata = { - .name = "uart", - .write = early_uart_write, - .setup = early_uart_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static int __init early_uart_console_init(void) -{ - if (!early_uart_registered) { - register_console(&early_uart_console); - early_uart_registered = 1; - } - return 0; -} -console_initcall(early_uart_console_init); - -int __init early_serial_console_init(char *cmdline) +static int __init setup_early_serial_console(char *cmdline) { char *options; int err; - options = strstr(cmdline, "console=uart,"); + options = strstr(cmdline, "uart,"); if (!options) return -ENODEV; options = strchr(cmdline, ',') + 1; if ((err = early_uart_setup(NULL, options)) < 0) return err; - return early_uart_console_init(); + + register_console(&early_uart_console); + early_uart_console.flags |= CON_BOOT; + return 0; } -static int __init early_uart_console_switch(void) +early_param("earlycon", setup_early_serial_console); + +static int __init early_uart_console_post(void) { struct early_uart_device *device = &early_device; struct uart_port *port = &device->port; - int mmio, line; + int mmio; if (!(early_uart_console.flags & CON_ENABLED)) return 0; - /* Try to start the normal driver on a matching line. */ mmio = (port->iotype == UPIO_MEM); - line = serial8250_start_console(port, device->options); - if (line < 0) - printk("No ttyS device at %s 0x%lx for console\n", - mmio ? "MMIO" : "I/O port", - mmio ? port->mapbase : - (unsigned long) port->iobase); - - unregister_console(&early_uart_console); + if (mmio) iounmap(port->membase); return 0; } -late_initcall(early_uart_console_switch); + +late_initcall(early_uart_console_post); diff --git a/include/linux/serial.h b/include/linux/serial.h index 33fc8cb..deb7143 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -177,11 +177,5 @@ struct serial_icounter_struct { #ifdef __KERNEL__ #include -/* Allow architectures to override entries in serial8250_ports[] at run time: */ -struct uart_port; /* forward declaration */ -extern int early_serial_setup(struct uart_port *port); -extern int early_serial_console_init(char *options); -extern int serial8250_start_console(struct uart_port *port, char *options); - #endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */