Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

console: Add extensible console matching

Add match() method to struct console which allows the console to
perform console command line matching instead of (or in addition to)
default console matching (ie., by fixed name and index).

The match() method returns 0 to indicate a successful match; normal
console matching occurs if no match() method is defined or the
match() method returns non-zero. The match() method is expected to set
the console index if required.

Re-implement earlycon-to-console-handoff with direct matching of
"console=uart|uart8250,..." to the 8250 ttyS console.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Peter Hurley and committed by
Greg Kroah-Hartman
c7cef0a8 e13cb72b

+67 -77
+48 -16
drivers/tty/serial/8250/8250_core.c
··· 3322 3322 return uart_set_options(port, co, baud, parity, bits, flow); 3323 3323 } 3324 3324 3325 - static int serial8250_console_early_setup(void) 3325 + /** 3326 + * serial8250_console_match - non-standard console matching 3327 + * @co: registering console 3328 + * @name: name from console command line 3329 + * @idx: index from console command line 3330 + * @options: ptr to option string from console command line 3331 + * 3332 + * Only attempts to match console command lines of the form: 3333 + * console=uart<>,io|mmio|mmio32,<addr>,<options> 3334 + * console=uart<>,<addr>,options 3335 + * This form is used to register an initial earlycon boot console and 3336 + * replace it with the serial8250_console at 8250 driver init. 3337 + * 3338 + * Performs console setup for a match (as required by interface) 3339 + * 3340 + * Returns 0 if console matches; otherwise non-zero to use default matching 3341 + */ 3342 + static int serial8250_console_match(struct console *co, char *name, int idx, 3343 + char *options) 3326 3344 { 3327 - return serial8250_find_port_for_earlycon(); 3345 + char match[] = "uart"; /* 8250-specific earlycon name */ 3346 + unsigned char iotype; 3347 + unsigned long addr; 3348 + int i; 3349 + 3350 + if (strncmp(name, match, 4) != 0) 3351 + return -ENODEV; 3352 + 3353 + if (uart_parse_earlycon(options, &iotype, &addr, &options)) 3354 + return -ENODEV; 3355 + 3356 + /* try to match the port specified on the command line */ 3357 + for (i = 0; i < nr_uarts; i++) { 3358 + struct uart_port *port = &serial8250_ports[i].port; 3359 + 3360 + if (port->iotype != iotype) 3361 + continue; 3362 + if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) && 3363 + (port->mapbase != addr)) 3364 + continue; 3365 + if (iotype == UPIO_PORT && port->iobase != addr) 3366 + continue; 3367 + 3368 + co->index = i; 3369 + return serial8250_console_setup(co, options); 3370 + } 3371 + 3372 + return -ENODEV; 3328 3373 } 3329 3374 3330 3375 static struct console serial8250_console = { ··· 3377 3332 .write = serial8250_console_write, 3378 3333 .device = uart_console_device, 3379 3334 .setup = serial8250_console_setup, 3380 - .early_setup = serial8250_console_early_setup, 3335 + .match = serial8250_console_match, 3381 3336 .flags = CON_PRINTBUFFER | CON_ANYTIME, 3382 3337 .index = -1, 3383 3338 .data = &serial8250_reg, ··· 3390 3345 return 0; 3391 3346 } 3392 3347 console_initcall(serial8250_console_init); 3393 - 3394 - int serial8250_find_port(struct uart_port *p) 3395 - { 3396 - int line; 3397 - struct uart_port *port; 3398 - 3399 - for (line = 0; line < nr_uarts; line++) { 3400 - port = &serial8250_ports[line].port; 3401 - if (uart_match_port(p, port)) 3402 - return line; 3403 - } 3404 - return -ENODEV; 3405 - } 3406 3348 3407 3349 #define SERIAL8250_CONSOLE &serial8250_console 3408 3350 #else
-23
drivers/tty/serial/8250/8250_early.c
··· 173 173 174 174 return setup_earlycon(cmdline, match, early_serial8250_setup); 175 175 } 176 - 177 - int serial8250_find_port_for_earlycon(void) 178 - { 179 - struct earlycon_device *device = early_device; 180 - struct uart_port *port = device ? &device->port : NULL; 181 - int line; 182 - int ret; 183 - 184 - if (!port || (!port->membase && !port->iobase)) 185 - return -ENODEV; 186 - 187 - line = serial8250_find_port(port); 188 - if (line < 0) 189 - return -ENODEV; 190 - 191 - ret = update_console_cmdline("uart", 8250, 192 - "ttyS", line, device->options); 193 - if (ret < 0) 194 - ret = update_console_cmdline("uart", 0, 195 - "ttyS", line, device->options); 196 - 197 - return ret; 198 - }
+1 -2
include/linux/console.h
··· 123 123 struct tty_driver *(*device)(struct console *, int *); 124 124 void (*unblank)(void); 125 125 int (*setup)(struct console *, char *); 126 - int (*early_setup)(void); 126 + int (*match)(struct console *, char *name, int idx, char *options); 127 127 short flags; 128 128 short index; 129 129 int cflag; ··· 141 141 extern struct console *early_console; 142 142 143 143 extern int add_preferred_console(char *name, int idx, char *options); 144 - extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options); 145 144 extern void register_console(struct console *); 146 145 extern int unregister_console(struct console *); 147 146 extern struct console *console_drivers;
-2
include/linux/serial_8250.h
··· 118 118 119 119 extern int early_serial_setup(struct uart_port *port); 120 120 121 - extern int serial8250_find_port(struct uart_port *p); 122 - extern int serial8250_find_port_for_earlycon(void); 123 121 extern unsigned int serial8250_early_in(struct uart_port *port, int offset); 124 122 extern void serial8250_early_out(struct uart_port *port, int offset, int value); 125 123 extern int setup_early_serial8250_console(char *cmdline);
+18 -34
kernel/printk/printk.c
··· 2017 2017 return __add_preferred_console(name, idx, options, NULL); 2018 2018 } 2019 2019 2020 - int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options) 2021 - { 2022 - struct console_cmdline *c; 2023 - int i; 2024 - 2025 - for (i = 0, c = console_cmdline; 2026 - i < MAX_CMDLINECONSOLES && c->name[0]; 2027 - i++, c++) 2028 - if (strcmp(c->name, name) == 0 && c->index == idx) { 2029 - strlcpy(c->name, name_new, sizeof(c->name)); 2030 - c->options = options; 2031 - c->index = idx_new; 2032 - return i; 2033 - } 2034 - /* not found */ 2035 - return -1; 2036 - } 2037 - 2038 2020 bool console_suspend_enabled = true; 2039 2021 EXPORT_SYMBOL(console_suspend_enabled); 2040 2022 ··· 2418 2436 if (preferred_console < 0 || bcon || !console_drivers) 2419 2437 preferred_console = selected_console; 2420 2438 2421 - if (newcon->early_setup) 2422 - newcon->early_setup(); 2423 - 2424 2439 /* 2425 2440 * See if we want to use this console driver. If we 2426 2441 * didn't select a console we take the first one ··· 2443 2464 for (i = 0, c = console_cmdline; 2444 2465 i < MAX_CMDLINECONSOLES && c->name[0]; 2445 2466 i++, c++) { 2446 - BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); 2447 - if (strcmp(c->name, newcon->name) != 0) 2448 - continue; 2449 - if (newcon->index >= 0 && 2450 - newcon->index != c->index) 2451 - continue; 2452 - if (newcon->index < 0) 2453 - newcon->index = c->index; 2467 + if (!newcon->match || 2468 + newcon->match(newcon, c->name, c->index, c->options) != 0) { 2469 + /* default matching */ 2470 + BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); 2471 + if (strcmp(c->name, newcon->name) != 0) 2472 + continue; 2473 + if (newcon->index >= 0 && 2474 + newcon->index != c->index) 2475 + continue; 2476 + if (newcon->index < 0) 2477 + newcon->index = c->index; 2454 2478 2455 - if (_braille_register_console(newcon, c)) 2456 - return; 2479 + if (_braille_register_console(newcon, c)) 2480 + return; 2457 2481 2458 - if (newcon->setup && 2459 - newcon->setup(newcon, console_cmdline[i].options) != 0) 2460 - break; 2482 + if (newcon->setup && 2483 + newcon->setup(newcon, c->options) != 0) 2484 + break; 2485 + } 2486 + 2461 2487 newcon->flags |= CON_ENABLED; 2462 2488 if (i == selected_console) { 2463 2489 newcon->flags |= CON_CONSDEV;