aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2015-03-09 16:27:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-26 11:16:20 -0400
commitc7cef0a84912cab3c9df8949b034e4aa62982ec9 (patch)
tree5e3d7761af96a243ac7460cbbd4e6b20f4eb00c2
parente13cb72beeada6f6ac12058b9129334e3bb5ce85 (diff)
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>
-rw-r--r--drivers/tty/serial/8250/8250_core.c64
-rw-r--r--drivers/tty/serial/8250/8250_early.c23
-rw-r--r--include/linux/console.h3
-rw-r--r--include/linux/serial_8250.h2
-rw-r--r--kernel/printk/printk.c52
5 files changed, 67 insertions, 77 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index bd06ab790c64..924ee1e13828 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3322,9 +3322,54 @@ static int serial8250_console_setup(struct console *co, char *options)
3322 return uart_set_options(port, co, baud, parity, bits, flow); 3322 return uart_set_options(port, co, baud, parity, bits, flow);
3323} 3323}
3324 3324
3325static 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 */
3342static 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
3330static struct console serial8250_console = { 3375static struct console serial8250_console = {
@@ -3332,7 +3377,7 @@ static struct console serial8250_console = {
3332 .write = serial8250_console_write, 3377 .write = serial8250_console_write,
3333 .device = uart_console_device, 3378 .device = uart_console_device,
3334 .setup = serial8250_console_setup, 3379 .setup = serial8250_console_setup,
3335 .early_setup = serial8250_console_early_setup, 3380 .match = serial8250_console_match,
3336 .flags = CON_PRINTBUFFER | CON_ANYTIME, 3381 .flags = CON_PRINTBUFFER | CON_ANYTIME,
3337 .index = -1, 3382 .index = -1,
3338 .data = &serial8250_reg, 3383 .data = &serial8250_reg,
@@ -3346,19 +3391,6 @@ static int __init serial8250_console_init(void)
3346} 3391}
3347console_initcall(serial8250_console_init); 3392console_initcall(serial8250_console_init);
3348 3393
3349int serial8250_find_port(struct uart_port *p)
3350{
3351 int line;
3352 struct uart_port *port;
3353
3354 for (line = 0; line < nr_uarts; line++) {
3355 port = &serial8250_ports[line].port;
3356 if (uart_match_port(p, port))
3357 return line;
3358 }
3359 return -ENODEV;
3360}
3361
3362#define SERIAL8250_CONSOLE &serial8250_console 3394#define SERIAL8250_CONSOLE &serial8250_console
3363#else 3395#else
3364#define SERIAL8250_CONSOLE NULL 3396#define SERIAL8250_CONSOLE NULL
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index c31a22b4f845..49bca65057e6 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -173,26 +173,3 @@ int __init setup_early_serial8250_console(char *cmdline)
173 173
174 return setup_earlycon(cmdline, match, early_serial8250_setup); 174 return setup_earlycon(cmdline, match, early_serial8250_setup);
175} 175}
176
177int 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}
diff --git a/include/linux/console.h b/include/linux/console.h
index 7571a16bd653..9f50fb413c11 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -123,7 +123,7 @@ struct console {
123 struct tty_driver *(*device)(struct console *, int *); 123 struct tty_driver *(*device)(struct console *, int *);
124 void (*unblank)(void); 124 void (*unblank)(void);
125 int (*setup)(struct console *, char *); 125 int (*setup)(struct console *, char *);
126 int (*early_setup)(void); 126 int (*match)(struct console *, char *name, int idx, char *options);
127 short flags; 127 short flags;
128 short index; 128 short index;
129 int cflag; 129 int cflag;
@@ -141,7 +141,6 @@ extern int console_set_on_cmdline;
141extern struct console *early_console; 141extern struct console *early_console;
142 142
143extern int add_preferred_console(char *name, int idx, char *options); 143extern int add_preferred_console(char *name, int idx, char *options);
144extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
145extern void register_console(struct console *); 144extern void register_console(struct console *);
146extern int unregister_console(struct console *); 145extern int unregister_console(struct console *);
147extern struct console *console_drivers; 146extern struct console *console_drivers;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index a8efa235b7c1..f26ae7fa30ae 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -118,8 +118,6 @@ void serial8250_resume_port(int line);
118 118
119extern int early_serial_setup(struct uart_port *port); 119extern int early_serial_setup(struct uart_port *port);
120 120
121extern int serial8250_find_port(struct uart_port *p);
122extern int serial8250_find_port_for_earlycon(void);
123extern unsigned int serial8250_early_in(struct uart_port *port, int offset); 121extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
124extern void serial8250_early_out(struct uart_port *port, int offset, int value); 122extern void serial8250_early_out(struct uart_port *port, int offset, int value);
125extern int setup_early_serial8250_console(char *cmdline); 123extern int setup_early_serial8250_console(char *cmdline);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 26f899809539..dda959221086 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2017,24 +2017,6 @@ int add_preferred_console(char *name, int idx, char *options)
2017 return __add_preferred_console(name, idx, options, NULL); 2017 return __add_preferred_console(name, idx, options, NULL);
2018} 2018}
2019 2019
2020int 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
2038bool console_suspend_enabled = true; 2020bool console_suspend_enabled = true;
2039EXPORT_SYMBOL(console_suspend_enabled); 2021EXPORT_SYMBOL(console_suspend_enabled);
2040 2022
@@ -2436,9 +2418,6 @@ void register_console(struct console *newcon)
2436 if (preferred_console < 0 || bcon || !console_drivers) 2418 if (preferred_console < 0 || bcon || !console_drivers)
2437 preferred_console = selected_console; 2419 preferred_console = selected_console;
2438 2420
2439 if (newcon->early_setup)
2440 newcon->early_setup();
2441
2442 /* 2421 /*
2443 * See if we want to use this console driver. If we 2422 * See if we want to use this console driver. If we
2444 * didn't select a console we take the first one 2423 * didn't select a console we take the first one
@@ -2464,21 +2443,26 @@ void register_console(struct console *newcon)
2464 for (i = 0, c = console_cmdline; 2443 for (i = 0, c = console_cmdline;
2465 i < MAX_CMDLINECONSOLES && c->name[0]; 2444 i < MAX_CMDLINECONSOLES && c->name[0];
2466 i++, c++) { 2445 i++, c++) {
2467 BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); 2446 if (!newcon->match ||
2468 if (strcmp(c->name, newcon->name) != 0) 2447 newcon->match(newcon, c->name, c->index, c->options) != 0) {
2469 continue; 2448 /* default matching */
2470 if (newcon->index >= 0 && 2449 BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
2471 newcon->index != c->index) 2450 if (strcmp(c->name, newcon->name) != 0)
2472 continue; 2451 continue;
2473 if (newcon->index < 0) 2452 if (newcon->index >= 0 &&
2474 newcon->index = c->index; 2453 newcon->index != c->index)
2454 continue;
2455 if (newcon->index < 0)
2456 newcon->index = c->index;
2475 2457
2476 if (_braille_register_console(newcon, c)) 2458 if (_braille_register_console(newcon, c))
2477 return; 2459 return;
2460
2461 if (newcon->setup &&
2462 newcon->setup(newcon, c->options) != 0)
2463 break;
2464 }
2478 2465
2479 if (newcon->setup &&
2480 newcon->setup(newcon, console_cmdline[i].options) != 0)
2481 break;
2482 newcon->flags |= CON_ENABLED; 2466 newcon->flags |= CON_ENABLED;
2483 if (i == selected_console) { 2467 if (i == selected_console) {
2484 newcon->flags |= CON_CONSDEV; 2468 newcon->flags |= CON_CONSDEV;