LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH -next 00/13] Extensible console matching & direct earlycon
@ 2015-02-24 16:36 Peter Hurley
  2015-02-24 16:36 ` [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core Peter Hurley
                   ` (13 more replies)
  0 siblings, 14 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:36 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Hi Greg & Andrew,

This patch series implements:
  1. console-definable (aka extensible) matching
  2. generic earlycon-to-console handoff via extensible matching
  3. arch/prom support for direct earlycon


Extensible console matching

Extensible console matching enables the console itself to define the
conditions for a "command line" match. This mimics the design of
device matching in the driver model. Two important use-cases which this
feature enables are generic earlycon-to-console handoff and support
for driver migration.

Earlycon-to-console handoff was implemented in 2007. Console command
lines of the form:
   console=uart,io,0x3f8,115200n8
start an earlycon and later allow the 8250 driver console to takeover.
Unfortunately this implementation requires direct coupling between
the earlycon and the console and is facilitated by ugly hacks like
editing the console command line in-place.

Extensible console matching allows the 8250 driver to directly match
that console command line instead, and enables other serial drivers
to trivially support console handoff themselves.

In addition, extensible console matching allows a new driver to
provide support for a different driver's console. This requirement
stems from needing to minimize breakage when migrating serial drivers.
Since many devices are based on the original 8250/16550 designs
but sometimes have features incompatible with the existing 8250 driver
support, the initial driver is often standalone. When/if the standalone
driver is migrated to the 8250 driver, the problem of console names in
the command line remains. Extensible console matching enables a simple
migration path.


Direct earlycon

This feature enables arches and proms to start an earlycon directly,
rather than requiring an "earlycon=" command line parameter.
Devicetree can already do this via the 'linux,stdout-path' property,
but arch and prom code requires direct coupling to the serial driver.

This support is implemented by judicious refactoring and the same
construct that devicetree and early_param use: a link table containing
the necessary information (name and setup() function) to find and
bind the appropriate earlycon "driver".


NB: I combined these two features in this series because their
implementations heavily overlap in the same source files.

Regards,

Peter Hurley (13):
  serial: earlycon: Refactor parse_options into serial core
  console: Preserve index after console setup()
  console: Add extensible console matching
  serial: core: Fix kernel doc for uart_console_write()
  serial: 8250_early: Remove early_device variable
  serial: earlycon: Move ->uartclk initialize
  serial: 8250_early: Assume uart already initialized if no baud option
  serial: 8250_early: Fix setup() error code
  serial: earlycon: Ignore parse_options() error code
  serial: earlycon: Allow earlycon params with name only
  serial: earlycon: Refactor earlycon registration
  serial: earlycon: Enable earlycon without command line param
  serial: 8250_early: Remove setup_early_serial8250_console()

 arch/mips/mti-malta/malta-init.c     |   4 +-
 drivers/firmware/pcdp.c              |   4 +-
 drivers/tty/serial/8250/8250_core.c  |  64 ++++++++++++----
 drivers/tty/serial/8250/8250_early.c |  51 +++----------
 drivers/tty/serial/earlycon.c        | 140 ++++++++++++++++++++++++-----------
 drivers/tty/serial/serial_core.c     |  48 +++++++++++-
 include/asm-generic/vmlinux.lds.h    |   9 +++
 include/linux/console.h              |   3 +-
 include/linux/serial_8250.h          |   3 -
 include/linux/serial_core.h          |  21 ++++--
 kernel/printk/printk.c               |  51 +++++--------
 11 files changed, 245 insertions(+), 153 deletions(-)

-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
@ 2015-02-24 16:36 ` Peter Hurley
  2015-02-25 13:03   ` Peter Hurley
  2015-02-24 16:36 ` [PATCH -next 02/13] console: Preserve index after console setup() Peter Hurley
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:36 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Prepare to support console-defined matching; refactor the command
line parameter string processing from parse_options() into a
new core function, uart_parse_earlycon(), which decodes command line
parameters of the form:
   earlycon=<name>,io|mmio|mmio32,<addr>,<options>
   console=<name>,io|mmio|mmio32,<addr>,<options>
   earlycon=<name>,0x<addr>,<options>
   console=<name>,0x<addr>,<options>

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/earlycon.c    | 39 ++++++++++++----------------------
 drivers/tty/serial/serial_core.c | 46 ++++++++++++++++++++++++++++++++++++++++
 include/linux/serial_core.h      |  2 ++
 3 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 64fe25a..58d6bcd 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -54,44 +54,31 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
 	return base;
 }
 
-static int __init parse_options(struct earlycon_device *device,
-				char *options)
+static int __init parse_options(struct earlycon_device *device, char *options)
 {
 	struct uart_port *port = &device->port;
-	int mmio, mmio32, length;
+	int length;
 	unsigned long addr;
 
-	if (!options)
-		return -ENODEV;
+	if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
+		return -EINVAL;
 
-	mmio = !strncmp(options, "mmio,", 5);
-	mmio32 = !strncmp(options, "mmio32,", 7);
-	if (mmio || mmio32) {
-		port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
-		options += mmio ? 5 : 7;
-		addr = simple_strtoul(options, NULL, 0);
+	switch (port->iotype) {
+	case UPIO_MEM32:
+		port->regshift = 2;	/* fall-through */
+	case UPIO_MEM:
 		port->mapbase = addr;
-		if (mmio32)
-			port->regshift = 2;
-	} else if (!strncmp(options, "io,", 3)) {
-		port->iotype = UPIO_PORT;
-		options += 3;
-		addr = simple_strtoul(options, NULL, 0);
+		break;
+	case UPIO_PORT:
 		port->iobase = addr;
-		mmio = 0;
-	} else if (!strncmp(options, "0x", 2)) {
-		port->iotype = UPIO_MEM;
-		addr = simple_strtoul(options, NULL, 0);
-		port->mapbase = addr;
-	} else {
+		break;
+	default:
 		return -EINVAL;
 	}
 
 	port->uartclk = BASE_BAUD * 16;
 
-	options = strchr(options, ',');
 	if (options) {
-		options++;
 		device->baud = simple_strtoul(options, NULL, 0);
 		length = min(strcspn(options, " ") + 1,
 			     (size_t)(sizeof(device->options)));
@@ -100,7 +87,7 @@ static int __init parse_options(struct earlycon_device *device,
 
 	if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
 		pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
-			mmio32 ? "32" : "",
+			(port->iotype == UPIO_MEM32) ? "32" : "",
 			(unsigned long long)port->mapbase,
 			device->options);
 	else
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 6a1055a..3f823c26 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1810,6 +1810,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
 }
 
 /**
+ *	uart_parse_earlycon - Parse earlycon options
+ *	@p:	  ptr to 2nd field (ie., just beyond '<name>,')
+ *	@iotype:  ptr for decoded iotype (out)
+ *	@addr:    ptr for decoded mapbase/iobase (out)
+ *	@options: ptr for <options> field; NULL if not present (out)
+ *
+ *	Decodes earlycon kernel command line parameters of the form
+ *	   earlycon=<name>,io|mmio|mmio32,<addr>,<options>
+ *	   console=<name>,io|mmio|mmio32,<addr>,<options>
+ *
+ *	The optional form
+ *	   earlycon=<name>,0x<addr>,<options>
+ *	   console=<name>,0x<addr>,<options>
+ *	is also accepted; the returned @iotype will be UPIO_MEM.
+ *
+ *	Returns 0 on success or -EINVAL on failure
+ */
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+			char **options)
+{
+	if (strncmp(p, "mmio,", 5) == 0) {
+		*iotype = UPIO_MEM;
+		p += 5;
+	} else if (strncmp(p, "mmio32,", 7) == 0) {
+		*iotype = UPIO_MEM32;
+		p += 7;
+	} else if (strncmp(p, "io,", 3) == 0) {
+		*iotype = UPIO_PORT;
+		p += 3;
+	} else if (strncmp(p, "0x", 2) == 0) {
+		*iotype = UPIO_MEM;
+	} else {
+		return -EINVAL;
+	}
+
+	*addr = simple_strtoul(p, NULL, 0);
+	p = strchr(p, ',');
+	if (p)
+		p++;
+
+	*options = p;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(uart_parse_earlycon);
+
+/**
  *	uart_parse_options - Parse serial port baud/parity/bits/flow control.
  *	@options: pointer to option string
  *	@baud: pointer to an 'int' variable for the baud rate.
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index baf3e1d..cc5c506 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -354,6 +354,8 @@ early_param("earlycon", name ## _setup_earlycon);
 
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
 				   struct console *c);
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+			char **options);
 void uart_parse_options(char *options, int *baud, int *parity, int *bits,
 			int *flow);
 int uart_set_options(struct uart_port *port, struct console *co, int baud,
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 02/13] console: Preserve index after console setup()
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
  2015-02-24 16:36 ` [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core Peter Hurley
@ 2015-02-24 16:36 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 03/13] console: Add extensible console matching Peter Hurley
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:36 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Before register_console() calls the setup() method of the matched
console, the registering console index is already equal to the index
from the console command line; ie. newcon->index == c->index.

This change is also required to support extensible console matching;
(the command line index may have no relation to the console index
assigned by the console-defined match() function).

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 kernel/printk/printk.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 02d6b6d..ce5c297 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2479,7 +2479,6 @@ void register_console(struct console *newcon)
 		    newcon->setup(newcon, console_cmdline[i].options) != 0)
 			break;
 		newcon->flags |= CON_ENABLED;
-		newcon->index = c->index;
 		if (i == selected_console) {
 			newcon->flags |= CON_CONSDEV;
 			preferred_console = selected_console;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 03/13] console: Add extensible console matching
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
  2015-02-24 16:36 ` [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core Peter Hurley
  2015-02-24 16:36 ` [PATCH -next 02/13] console: Preserve index after console setup() Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-28 17:18   ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 04/13] serial: core: Fix kernel doc for uart_console_write() Peter Hurley
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

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.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/8250/8250_core.c  | 64 +++++++++++++++++++++++++++---------
 drivers/tty/serial/8250/8250_early.c | 23 -------------
 include/linux/console.h              |  3 +-
 include/linux/serial_8250.h          |  2 --
 kernel/printk/printk.c               | 50 ++++++++++------------------
 5 files changed, 66 insertions(+), 76 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index e3b9570a..5eb95fd 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -3337,9 +3337,54 @@ static int serial8250_console_setup(struct console *co, char *options)
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-static int serial8250_console_early_setup(void)
+/**
+ *	serial8250_console_match - non-standard console matching
+ *	@co:	  registering console
+ *	@name:	  name from console command line
+ *	@idx:	  index from console command line
+ *	@options: ptr to option string from console command line
+ *
+ *	Only attempts to match console command lines of the form:
+ *	    console=uart<>,io|mmio|mmio32,<addr>,<options>
+ *	    console=uart<>,<addr>,options
+ *	This form is used to register an initial earlycon boot console and
+ *	replace it with the serial8250_console at 8250 driver init.
+ *
+ *	Performs console setup for a match (as required by interface)
+ *
+ *	Returns 0 if console matches; otherwise non-zero to use default matching
+ */
+static int serial8250_console_match(struct console *co, char *name, int idx,
+				    char *options)
 {
-	return serial8250_find_port_for_earlycon();
+	char match[] = "uart";	/* 8250-specific earlycon name */
+	unsigned char iotype;
+	unsigned long addr;
+	int i;
+
+	if (strncmp(name, match, 4) != 0)
+		return -ENODEV;
+
+	if (uart_parse_earlycon(options, &iotype, &addr, &options))
+		return -ENODEV;
+
+	/* try to match the port specified on the command line */
+	for (i = 0; i < nr_uarts; i++) {
+		struct uart_port *port = &serial8250_ports[i].port;
+
+		if (port->iotype != iotype)
+			continue;
+		if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
+		    (port->mapbase != addr))
+			continue;
+		if (iotype == UPIO_PORT && port->iobase != addr)
+			continue;
+
+		co->index = i;
+		return serial8250_console_setup(co, options);
+	}
+
+	return -ENODEV;
 }
 
 static struct console serial8250_console = {
@@ -3347,7 +3392,7 @@ static struct console serial8250_console = {
 	.write		= serial8250_console_write,
 	.device		= uart_console_device,
 	.setup		= serial8250_console_setup,
-	.early_setup	= serial8250_console_early_setup,
+	.match		= serial8250_console_match,
 	.flags		= CON_PRINTBUFFER | CON_ANYTIME,
 	.index		= -1,
 	.data		= &serial8250_reg,
@@ -3361,19 +3406,6 @@ static int __init serial8250_console_init(void)
 }
 console_initcall(serial8250_console_init);
 
-int serial8250_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;
-}
-
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
 #define SERIAL8250_CONSOLE	NULL
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index c31a22b..49bca65 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)
 
 	return setup_earlycon(cmdline, match, early_serial8250_setup);
 }
-
-int serial8250_find_port_for_earlycon(void)
-{
-	struct earlycon_device *device = early_device;
-	struct uart_port *port = device ? &device->port : NULL;
-	int line;
-	int ret;
-
-	if (!port || (!port->membase && !port->iobase))
-		return -ENODEV;
-
-	line = serial8250_find_port(port);
-	if (line < 0)
-		return -ENODEV;
-
-	ret = update_console_cmdline("uart", 8250,
-			     "ttyS", line, device->options);
-	if (ret < 0)
-		ret = update_console_cmdline("uart", 0,
-				     "ttyS", line, device->options);
-
-	return ret;
-}
diff --git a/include/linux/console.h b/include/linux/console.h
index 7571a16..9f50fb4 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -123,7 +123,7 @@ struct console {
 	struct tty_driver *(*device)(struct console *, int *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
-	int	(*early_setup)(void);
+	int	(*match)(struct console *, char *name, int idx, char *options);
 	short	flags;
 	short	index;
 	int	cflag;
@@ -141,7 +141,6 @@ extern int console_set_on_cmdline;
 extern struct console *early_console;
 
 extern int add_preferred_console(char *name, int idx, char *options);
-extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
 extern struct console *console_drivers;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index a8efa23..f26ae7f 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -118,8 +118,6 @@ void serial8250_resume_port(int line);
 
 extern int early_serial_setup(struct uart_port *port);
 
-extern int serial8250_find_port(struct uart_port *p);
-extern int serial8250_find_port_for_earlycon(void);
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
 extern int setup_early_serial8250_console(char *cmdline);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ce5c297..040be39 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)
 	return __add_preferred_console(name, idx, options, NULL);
 }
 
-int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
-{
-	struct console_cmdline *c;
-	int i;
-
-	for (i = 0, c = console_cmdline;
-	     i < MAX_CMDLINECONSOLES && c->name[0];
-	     i++, c++)
-		if (strcmp(c->name, name) == 0 && c->index == idx) {
-			strlcpy(c->name, name_new, sizeof(c->name));
-			c->options = options;
-			c->index = idx_new;
-			return i;
-		}
-	/* not found */
-	return -1;
-}
-
 bool console_suspend_enabled = true;
 EXPORT_SYMBOL(console_suspend_enabled);
 
@@ -2436,9 +2418,6 @@ void register_console(struct console *newcon)
 	if (preferred_console < 0 || bcon || !console_drivers)
 		preferred_console = selected_console;
 
-	if (newcon->early_setup)
-		newcon->early_setup();
-
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one
@@ -2464,20 +2443,25 @@ void register_console(struct console *newcon)
 	for (i = 0, c = console_cmdline;
 	     i < MAX_CMDLINECONSOLES && c->name[0];
 	     i++, c++) {
-		if (strcmp(c->name, newcon->name) != 0)
-			continue;
-		if (newcon->index >= 0 &&
-		    newcon->index != c->index)
-			continue;
-		if (newcon->index < 0)
-			newcon->index = c->index;
+		if (!newcon->match ||
+		    newcon->match(newcon, c->name, c->index, c->options) != 0) {
+			/* default matching */
+			if (strcmp(c->name, newcon->name) != 0)
+				continue;
+			if (newcon->index >= 0 &&
+			    newcon->index != c->index)
+				continue;
+			if (newcon->index < 0)
+				newcon->index = c->index;
 
-		if (_braille_register_console(newcon, c))
-			return;
+			if (_braille_register_console(newcon, c))
+				return;
+
+			if (newcon->setup &&
+			    newcon->setup(newcon, c->options) != 0)
+				break;
+		}
 
-		if (newcon->setup &&
-		    newcon->setup(newcon, console_cmdline[i].options) != 0)
-			break;
 		newcon->flags |= CON_ENABLED;
 		if (i == selected_console) {
 			newcon->flags |= CON_CONSDEV;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 04/13] serial: core: Fix kernel doc for uart_console_write()
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (2 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 03/13] console: Add extensible console matching Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 05/13] serial: 8250_early: Remove early_device variable Peter Hurley
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

'/**' is required to start a kernel-doc comment block.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/serial_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 3f823c26..373cfde 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1766,7 +1766,7 @@ static const struct file_operations uart_proc_fops = {
 #endif
 
 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
-/*
+/**
  *	uart_console_write - write a console message to a serial port
  *	@port: the port to write the message
  *	@s: array of characters
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 05/13] serial: 8250_early: Remove early_device variable
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (3 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 04/13] serial: core: Fix kernel doc for uart_console_write() Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 06/13] serial: earlycon: Move ->uartclk initialize Peter Hurley
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

early_device was only required for serial8250_find_port_for_earlycon(),
which was replaced by extensible console matching.

Fixup early_serial8250_write() to get the earlycon_device * from
console->data (which is initialized by {of_}setup_earlycon()).

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/8250/8250_early.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 49bca65..d7b831b 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -36,8 +36,6 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
-static struct earlycon_device *early_device;
-
 unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
 {
 	switch (port->iotype) {
@@ -90,7 +88,8 @@ static void __init serial_putc(struct uart_port *port, int c)
 static void __init early_serial8250_write(struct console *console,
 					const char *s, unsigned int count)
 {
-	struct uart_port *port = &early_device->port;
+	struct earlycon_device *device = console->data;
+	struct uart_port *port = &device->port;
 	unsigned int ier;
 
 	/* Save the IER and disable interrupts preserving the UUE bit */
@@ -157,7 +156,6 @@ static int __init early_serial8250_setup(struct earlycon_device *device,
 
 	init_port(device);
 
-	early_device = device;
 	device->con->write = early_serial8250_write;
 	return 0;
 }
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 06/13] serial: earlycon: Move ->uartclk initialize
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (4 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 05/13] serial: 8250_early: Remove early_device variable Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 07/13] serial: 8250_early: Assume uart already initialized if no baud option Peter Hurley
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Initializing the ->uartclk field is not related to option parsing;
relocate from parse_options() to setup_earlycon() (which mirrors the
behavior of of_setup_earlycon()).

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/earlycon.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 58d6bcd..0480c8f 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -76,8 +76,6 @@ static int __init parse_options(struct earlycon_device *device, char *options)
 		return -EINVAL;
 	}
 
-	port->uartclk = BASE_BAUD * 16;
-
 	if (options) {
 		device->baud = simple_strtoul(options, NULL, 0);
 		length = min(strcspn(options, " ") + 1,
@@ -121,6 +119,7 @@ int __init setup_earlycon(char *buf, const char *match,
 	if (!err)
 		buf = NULL;
 
+	port->uartclk = BASE_BAUD * 16;
 	if (port->mapbase)
 		port->membase = earlycon_map(port->mapbase, 64);
 
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 07/13] serial: 8250_early: Assume uart already initialized if no baud option
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (5 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 06/13] serial: earlycon: Move ->uartclk initialize Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 08/13] serial: 8250_early: Fix setup() error code Peter Hurley
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

The <baud><parity><bit> option string is not supplied if the earlycon
is started via devicetree and OF_EARLYCON_DECLARE(). The option string
is also not required if started via kernel command line parameters of
the form:
  earlycon=uart,mmio,<addr>
  console=uart,mmio,<addr>

If earlycon_device->baud is 0, then an option string was not supplied.
In this case, assume the uart has already been initialized by the
bootloader or firmware.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/8250/8250_early.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index d7b831b..1701d00 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -149,12 +149,18 @@ static int __init early_serial8250_setup(struct earlycon_device *device,
 		return 0;
 
 	if (!device->baud) {
+		struct uart_port *port = &device->port;
+		unsigned int ier;
+
 		device->baud = probe_baud(&device->port);
 		snprintf(device->options, sizeof(device->options), "%u",
 			 device->baud);
-	}
 
-	init_port(device);
+		/* assume the device was initialized, only mask interrupts */
+		ier = serial8250_early_in(port, UART_IER);
+		serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
+	} else
+		init_port(device);
 
 	device->con->write = early_serial8250_write;
 	return 0;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 08/13] serial: 8250_early: Fix setup() error code
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (6 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 07/13] serial: 8250_early: Assume uart already initialized if no baud option Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 09/13] serial: earlycon: Ignore parse_options() " Peter Hurley
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

If parsing failed to decode a valid uart addr, return -ENODEV instead
of success. Although setup_earlycon() will detect the failure anyway
(because the write() method has not been set), that behavior is not
obvious and should not be relied on.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/8250/8250_early.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 1701d00..b199c10 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -146,7 +146,7 @@ static int __init early_serial8250_setup(struct earlycon_device *device,
 					 const char *options)
 {
 	if (!(device->port.membase || device->port.iobase))
-		return 0;
+		return -ENODEV;
 
 	if (!device->baud) {
 		struct uart_port *port = &device->port;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 09/13] serial: earlycon: Ignore parse_options() error code
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (7 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 08/13] serial: 8250_early: Fix setup() error code Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 10/13] serial: earlycon: Allow earlycon params with name only Peter Hurley
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Because setup_earlycon() continues to attempt console registration
if an error occurred parsing the option string, the actual value of
the error code from parse_options() is ignored.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/earlycon.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 0480c8f..da5e8c8 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -114,9 +114,8 @@ int __init setup_earlycon(char *buf, const char *match,
 
 	buf += len + 1;
 
-	err = parse_options(&early_console_dev, buf);
 	/* On parsing error, pass the options buf to the setup function */
-	if (!err)
+	if (!parse_options(&early_console_dev, buf))
 		buf = NULL;
 
 	port->uartclk = BASE_BAUD * 16;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 10/13] serial: earlycon: Allow earlycon params with name only
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (8 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 09/13] serial: earlycon: Ignore parse_options() " Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 11/13] serial: earlycon: Refactor earlycon registration Peter Hurley
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Allow earlycon param strings of the form
   earlycon=<name>

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/earlycon.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index da5e8c8..025ea01 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -109,13 +109,16 @@ int __init setup_earlycon(char *buf, const char *match,
 	len = strlen(match);
 	if (strncmp(buf, match, len))
 		return 0;
-	if (buf[len] && (buf[len] != ','))
-		return 0;
 
-	buf += len + 1;
+	if (buf[len]) {
+		if (buf[len] != ',')
+			return 0;
+		buf += len + 1;
+	} else
+		buf = NULL;
 
 	/* On parsing error, pass the options buf to the setup function */
-	if (!parse_options(&early_console_dev, buf))
+	if (buf && !parse_options(&early_console_dev, buf))
 		buf = NULL;
 
 	port->uartclk = BASE_BAUD * 16;
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 11/13] serial: earlycon: Refactor earlycon registration
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (9 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 10/13] serial: earlycon: Allow earlycon params with name only Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 12/13] serial: earlycon: Enable earlycon without command line param Peter Hurley
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Separate earlycon matching from registration; add register_earlycon
which initializes and registers the matched earlycon.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/earlycon.c | 42 +++++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 025ea01..9fb76b6 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -96,27 +96,13 @@ static int __init parse_options(struct earlycon_device *device, char *options)
 	return 0;
 }
 
-int __init setup_earlycon(char *buf, const char *match,
-			  int (*setup)(struct earlycon_device *, const char *))
+
+static int __init
+register_earlycon(char *buf, int (*setup)(struct earlycon_device *, const char *))
 {
 	int err;
-	size_t len;
 	struct uart_port *port = &early_console_dev.port;
 
-	if (!buf || !match || !setup)
-		return 0;
-
-	len = strlen(match);
-	if (strncmp(buf, match, len))
-		return 0;
-
-	if (buf[len]) {
-		if (buf[len] != ',')
-			return 0;
-		buf += len + 1;
-	} else
-		buf = NULL;
-
 	/* On parsing error, pass the options buf to the setup function */
 	if (buf && !parse_options(&early_console_dev, buf))
 		buf = NULL;
@@ -136,6 +122,28 @@ int __init setup_earlycon(char *buf, const char *match,
 	return 0;
 }
 
+int __init setup_earlycon(char *buf, const char *match,
+			  int (*setup)(struct earlycon_device *, const char *))
+{
+	size_t len;
+
+	if (!buf || !match || !setup)
+		return 0;
+
+	len = strlen(match);
+	if (strncmp(buf, match, len))
+		return 0;
+
+	if (buf[len]) {
+		if (buf[len] != ',')
+			return 0;
+		buf += len + 1;
+	} else
+		buf = NULL;
+
+	return register_earlycon(buf, setup);
+}
+
 int __init of_setup_earlycon(unsigned long addr,
 			     int (*setup)(struct earlycon_device *, const char *))
 {
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 12/13] serial: earlycon: Enable earlycon without command line param
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (10 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 11/13] serial: earlycon: Refactor earlycon registration Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 16:37 ` [PATCH -next 13/13] serial: 8250_early: Remove setup_early_serial8250_console() Peter Hurley
  2015-02-24 19:27 ` [PATCH -next 00/13] Extensible console matching & direct earlycon Rob Herring
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley

Earlycon matching can only be triggered if 'earlycon=...' has been
specified on the kernel command line. To workaround this limitation
requires tight coupling between arches and specific serial drivers
in order to start an earlycon. Devicetree avoids this limitation
with a link table that contains the required data to match earlycons.

Mirror this approach for earlycon match by name. Re-purpose
EARLYCON_DECLARE to generate a table entry which associates name with
setup() function. Re-purpose setup_earlycon() to scan this table for
an earlycon match, which is registered if found.

Declare one "earlycon" early_param, which calls setup_earlycon().

This design allows setup_earlycon() to be called directly with a
param string (as if 'earlycon=...' had been set on the command line).
Re-registration (either directly or by early_param) is prevented.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 drivers/tty/serial/8250/8250_early.c |  7 +--
 drivers/tty/serial/earlycon.c        | 92 ++++++++++++++++++++++++++++--------
 include/asm-generic/vmlinux.lds.h    |  9 ++++
 include/linux/serial_core.h          | 19 ++++----
 4 files changed, 94 insertions(+), 33 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index b199c10..d272139 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -170,10 +170,5 @@ EARLYCON_DECLARE(uart, early_serial8250_setup);
 
 int __init setup_early_serial8250_console(char *cmdline)
 {
-	char match[] = "uart8250";
-
-	if (cmdline && cmdline[4] == ',')
-		match[4] = '\0';
-
-	return setup_earlycon(cmdline, match, early_serial8250_setup);
+	return setup_earlycon(cmdline);
 }
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 9fb76b6..5fdc9f3 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -10,6 +10,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -34,6 +37,10 @@ static struct earlycon_device early_console_dev = {
 	.con = &early_con,
 };
 
+extern struct earlycon_id __earlycon_table[];
+static const struct earlycon_id __earlycon_table_sentinel
+	__used __section(__earlycon_table_end);
+
 static const struct of_device_id __earlycon_of_table_sentinel
 	__used __section(__earlycon_of_table_end);
 
@@ -96,9 +103,7 @@ static int __init parse_options(struct earlycon_device *device, char *options)
 	return 0;
 }
 
-
-static int __init
-register_earlycon(char *buf, int (*setup)(struct earlycon_device *, const char *))
+static int __init register_earlycon(char *buf, const struct earlycon_id *match)
 {
 	int err;
 	struct uart_port *port = &early_console_dev.port;
@@ -112,7 +117,7 @@ register_earlycon(char *buf, int (*setup)(struct earlycon_device *, const char *
 		port->membase = earlycon_map(port->mapbase, 64);
 
 	early_console_dev.con->data = &early_console_dev;
-	err = setup(&early_console_dev, buf);
+	err = match->setup(&early_console_dev, buf);
 	if (err < 0)
 		return err;
 	if (!early_console_dev.con->write)
@@ -122,27 +127,76 @@ register_earlycon(char *buf, int (*setup)(struct earlycon_device *, const char *
 	return 0;
 }
 
-int __init setup_earlycon(char *buf, const char *match,
-			  int (*setup)(struct earlycon_device *, const char *))
+/**
+ *	setup_earlycon - match and register earlycon console
+ *	@buf:	earlycon param string
+ *
+ *	Registers the earlycon console matching the earlycon specified
+ *	in the param string @buf. Acceptable param strings are of the form
+ *	   <name>,io|mmio|mmio32,<addr>,<options>
+ *	   <name>,0x<addr>,<options>
+ *	   <name>,<options>
+ *	   <name>
+ *
+ *	Only for the third form does the earlycon setup() method receive the
+ *	<options> string in the 'options' parameter; all other forms set
+ *	the parameter to NULL.
+ *
+ *	Returns 0 if an attempt to register the earlycon was made,
+ *	otherwise negative error code
+ */
+int __init setup_earlycon(char *buf)
 {
-	size_t len;
+	const struct earlycon_id *match;
 
-	if (!buf || !match || !setup)
-		return 0;
+	if (!buf || !buf[0])
+		return -EINVAL;
 
-	len = strlen(match);
-	if (strncmp(buf, match, len))
-		return 0;
+	if (early_con.flags & CON_ENABLED)
+		return -EALREADY;
 
-	if (buf[len]) {
-		if (buf[len] != ',')
-			return 0;
-		buf += len + 1;
-	} else
-		buf = NULL;
+	for (match = __earlycon_table; match->name[0]; match++) {
+		size_t len = strlen(match->name);
 
-	return register_earlycon(buf, setup);
+		if (strncmp(buf, match->name, len))
+			continue;
+
+		if (buf[len]) {
+			if (buf[len] != ',')
+				continue;
+			buf += len + 1;
+		} else
+			buf = NULL;
+
+		return register_earlycon(buf, match);
+	}
+
+	return -ENOENT;
+}
+
+/* early_param wrapper for setup_earlycon() */
+static int __init param_setup_earlycon(char *buf)
+{
+	int err;
+
+	/*
+	 * Just 'earlycon' is a valid param for devicetree earlycons;
+	 * don't generate a warning from parse_early_params() in that case
+	 */
+	if (!buf || !buf[0])
+		return 0;
+
+	err = setup_earlycon(buf);
+	if (err == -ENOENT) {
+		pr_warn("no match for %s\n", buf);
+		err = 0;
+	} else if (err == -EALREADY) {
+		pr_warn("already registered\n");
+		err = 0;
+	}
+	return err;
 }
+early_param("earlycon", param_setup_earlycon);
 
 int __init of_setup_earlycon(unsigned long addr,
 			     int (*setup)(struct earlycon_device *, const char *))
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bee5d68..006c1f7 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -150,6 +150,14 @@
 #define TRACE_SYSCALLS()
 #endif
 
+#ifdef CONFIG_SERIAL_EARLYCON
+#define EARLYCON_TABLE() . = ALIGN(8);				\
+			 VMLINUX_SYMBOL(__earlycon_table) = .;	\
+			 *(__earlycon_table)			\
+			 *(__earlycon_table_end)
+#else
+#define EARLYCON_TABLE()
+#endif
 
 #define ___OF_TABLE(cfg, name)	_OF_TABLE_##cfg(name)
 #define __OF_TABLE(cfg, name)	___OF_TABLE(cfg, name)
@@ -502,6 +510,7 @@
 	CPU_METHOD_OF_TABLES()						\
 	KERNEL_DTB()							\
 	IRQCHIP_OF_MATCH_TABLE()					\
+	EARLYCON_TABLE()						\
 	EARLYCON_OF_TABLES()
 
 #define INIT_TEXT							\
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index cc5c506..a3fd182 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -336,18 +336,21 @@ struct earlycon_device {
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
 };
-int setup_earlycon(char *buf, const char *match,
-		   int (*setup)(struct earlycon_device *, const char *));
 
+struct earlycon_id {
+	char	name[16];
+	int	(*setup)(struct earlycon_device *, const char *options);
+};
+
+extern int setup_earlycon(char *buf);
 extern int of_setup_earlycon(unsigned long addr,
 			     int (*setup)(struct earlycon_device *, const char *));
 
-#define EARLYCON_DECLARE(name, func) \
-static int __init name ## _setup_earlycon(char *buf) \
-{ \
-	return setup_earlycon(buf, __stringify(name), func); \
-} \
-early_param("earlycon", name ## _setup_earlycon);
+#define EARLYCON_DECLARE(_name, func)					\
+	static const struct earlycon_id __earlycon_##_name		\
+		__used __section(__earlycon_table)			\
+		 = { .name  = __stringify(_name),			\
+		     .setup = func  }
 
 #define OF_EARLYCON_DECLARE(name, compat, fn)				\
 	_OF_DECLARE(earlycon, name, compat, fn, void *)
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH -next 13/13] serial: 8250_early: Remove setup_early_serial8250_console()
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (11 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 12/13] serial: earlycon: Enable earlycon without command line param Peter Hurley
@ 2015-02-24 16:37 ` Peter Hurley
  2015-02-24 19:27 ` [PATCH -next 00/13] Extensible console matching & direct earlycon Rob Herring
  13 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial,
	linux-kernel, Peter Hurley, Khalid Aziz, Tony Luck, Fenghua Yu,
	Ralf Baechle

setup_earlycon() will now match and register the desired earlycon
from the param string (as if 'earlycon=...' had been set on the
command line). Use setup_earlycon() from existing arch call sites
which start an earlycon directly.

Cc: Khalid Aziz <khalid@gonehiking.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
 arch/mips/mti-malta/malta-init.c     | 4 ++--
 drivers/firmware/pcdp.c              | 4 ++--
 drivers/tty/serial/8250/8250_early.c | 5 -----
 include/linux/serial_8250.h          | 1 -
 4 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index 6849f53..cec3e18 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp-ops.h>
@@ -75,7 +75,7 @@ static void __init console_config(void)
 	if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
 		sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
 			parity, bits);
-		setup_early_serial8250_console(console_string);
+		setup_earlycon(console_string);
 	}
 
 	if ((strstr(fw_getcmdline(), "console=")) == NULL) {
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index a330492..75273a25 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,7 +15,7 @@
 #include <linux/console.h>
 #include <linux/efi.h>
 #include <linux/serial.h>
-#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
 #include <asm/vga.h>
 #include "pcdp.h"
 
@@ -43,7 +43,7 @@ setup_serial_console(struct pcdp_uart *uart)
 	}
 
 	add_preferred_console("uart", 8250, &options[9]);
-	return setup_early_serial8250_console(options);
+	return setup_earlycon(options);
 #else
 	return -ENODEV;
 #endif
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index d272139..a2b4e58 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -167,8 +167,3 @@ static int __init early_serial8250_setup(struct earlycon_device *device,
 }
 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 EARLYCON_DECLARE(uart, early_serial8250_setup);
-
-int __init setup_early_serial8250_console(char *cmdline)
-{
-	return setup_earlycon(cmdline);
-}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index f26ae7f..ca9f87b 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -120,7 +120,6 @@ extern int early_serial_setup(struct uart_port *port);
 
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
-extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
 extern int serial8250_do_startup(struct uart_port *port);
-- 
2.3.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
                   ` (12 preceding siblings ...)
  2015-02-24 16:37 ` [PATCH -next 13/13] serial: 8250_early: Remove setup_early_serial8250_console() Peter Hurley
@ 2015-02-24 19:27 ` Rob Herring
  2015-02-24 19:53   ` Peter Hurley
  13 siblings, 1 reply; 24+ messages in thread
From: Rob Herring @ 2015-02-24 19:27 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

On Tue, Feb 24, 2015 at 10:36 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
> Hi Greg & Andrew,
>
> This patch series implements:
>   1. console-definable (aka extensible) matching
>   2. generic earlycon-to-console handoff via extensible matching
>   3. arch/prom support for direct earlycon
>
>
> Extensible console matching
>
> Extensible console matching enables the console itself to define the
> conditions for a "command line" match. This mimics the design of
> device matching in the driver model. Two important use-cases which this
> feature enables are generic earlycon-to-console handoff and support
> for driver migration.
>
> Earlycon-to-console handoff was implemented in 2007. Console command
> lines of the form:
>    console=uart,io,0x3f8,115200n8
> start an earlycon and later allow the 8250 driver console to takeover.
> Unfortunately this implementation requires direct coupling between
> the earlycon and the console and is facilitated by ugly hacks like
> editing the console command line in-place.
>
> Extensible console matching allows the 8250 driver to directly match
> that console command line instead, and enables other serial drivers
> to trivially support console handoff themselves.
>
> In addition, extensible console matching allows a new driver to
> provide support for a different driver's console. This requirement
> stems from needing to minimize breakage when migrating serial drivers.
> Since many devices are based on the original 8250/16550 designs
> but sometimes have features incompatible with the existing 8250 driver
> support, the initial driver is often standalone. When/if the standalone
> driver is migrated to the 8250 driver, the problem of console names in
> the command line remains. Extensible console matching enables a simple
> migration path.
>
>
> Direct earlycon
>
> This feature enables arches and proms to start an earlycon directly,
> rather than requiring an "earlycon=" command line parameter.
> Devicetree can already do this via the 'linux,stdout-path' property,
> but arch and prom code requires direct coupling to the serial driver.
>
> This support is implemented by judicious refactoring and the same
> construct that devicetree and early_param use: a link table containing
> the necessary information (name and setup() function) to find and
> bind the appropriate earlycon "driver".

I've skimmed thru this and it looks like a great improvement.

One problem we have currently with DT stdout-path and earlycon is a
preferred console does not get registered, so the console will get
switched to tty0 and you lose your console. The problem is DT does not
know the console name to register a preferred console. It looks like
this series may help this problem, but I'm not sure and wanted your
thoughts.

Rob

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-24 19:27 ` [PATCH -next 00/13] Extensible console matching & direct earlycon Rob Herring
@ 2015-02-24 19:53   ` Peter Hurley
  2015-02-24 20:20     ` Rob Herring
  0 siblings, 1 reply; 24+ messages in thread
From: Peter Hurley @ 2015-02-24 19:53 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

Hi Rob,

On 02/24/2015 02:27 PM, Rob Herring wrote:
> On Tue, Feb 24, 2015 at 10:36 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
>> Hi Greg & Andrew,
>>
>> This patch series implements:
>>   1. console-definable (aka extensible) matching
>>   2. generic earlycon-to-console handoff via extensible matching
>>   3. arch/prom support for direct earlycon
>>
>>
>> Extensible console matching
>>
>> Extensible console matching enables the console itself to define the
>> conditions for a "command line" match. This mimics the design of
>> device matching in the driver model. Two important use-cases which this
>> feature enables are generic earlycon-to-console handoff and support
>> for driver migration.
>>
>> Earlycon-to-console handoff was implemented in 2007. Console command
>> lines of the form:
>>    console=uart,io,0x3f8,115200n8
>> start an earlycon and later allow the 8250 driver console to takeover.
>> Unfortunately this implementation requires direct coupling between
>> the earlycon and the console and is facilitated by ugly hacks like
>> editing the console command line in-place.
>>
>> Extensible console matching allows the 8250 driver to directly match
>> that console command line instead, and enables other serial drivers
>> to trivially support console handoff themselves.
>>
>> In addition, extensible console matching allows a new driver to
>> provide support for a different driver's console. This requirement
>> stems from needing to minimize breakage when migrating serial drivers.
>> Since many devices are based on the original 8250/16550 designs
>> but sometimes have features incompatible with the existing 8250 driver
>> support, the initial driver is often standalone. When/if the standalone
>> driver is migrated to the 8250 driver, the problem of console names in
>> the command line remains. Extensible console matching enables a simple
>> migration path.
>>
>>
>> Direct earlycon
>>
>> This feature enables arches and proms to start an earlycon directly,
>> rather than requiring an "earlycon=" command line parameter.
>> Devicetree can already do this via the 'linux,stdout-path' property,
>> but arch and prom code requires direct coupling to the serial driver.
>>
>> This support is implemented by judicious refactoring and the same
>> construct that devicetree and early_param use: a link table containing
>> the necessary information (name and setup() function) to find and
>> bind the appropriate earlycon "driver".
> 
> I've skimmed thru this and it looks like a great improvement.
> 
> One problem we have currently with DT stdout-path and earlycon is a
> preferred console does not get registered, so the console will get
> switched to tty0 and you lose your console. The problem is DT does not
> know the console name to register a preferred console. It looks like
> this series may help this problem, but I'm not sure and wanted your
> thoughts.

I thought that of_alias_scan() + of_console_check() caused DT stdout-path
to add_preferred_console() the driver console @ port registration time
via uart_add_one_port() -> of_console_check().

Is that not how that works?

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-24 19:53   ` Peter Hurley
@ 2015-02-24 20:20     ` Rob Herring
  2015-02-26 14:48       ` Peter Hurley
  0 siblings, 1 reply; 24+ messages in thread
From: Rob Herring @ 2015-02-24 20:20 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:
> Hi Rob,
>
> On 02/24/2015 02:27 PM, Rob Herring wrote:
>> On Tue, Feb 24, 2015 at 10:36 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
>>> Hi Greg & Andrew,
>>>
>>> This patch series implements:
>>>   1. console-definable (aka extensible) matching
>>>   2. generic earlycon-to-console handoff via extensible matching
>>>   3. arch/prom support for direct earlycon
>>>
>>>
>>> Extensible console matching
>>>
>>> Extensible console matching enables the console itself to define the
>>> conditions for a "command line" match. This mimics the design of
>>> device matching in the driver model. Two important use-cases which this
>>> feature enables are generic earlycon-to-console handoff and support
>>> for driver migration.
>>>
>>> Earlycon-to-console handoff was implemented in 2007. Console command
>>> lines of the form:
>>>    console=uart,io,0x3f8,115200n8
>>> start an earlycon and later allow the 8250 driver console to takeover.
>>> Unfortunately this implementation requires direct coupling between
>>> the earlycon and the console and is facilitated by ugly hacks like
>>> editing the console command line in-place.
>>>
>>> Extensible console matching allows the 8250 driver to directly match
>>> that console command line instead, and enables other serial drivers
>>> to trivially support console handoff themselves.
>>>
>>> In addition, extensible console matching allows a new driver to
>>> provide support for a different driver's console. This requirement
>>> stems from needing to minimize breakage when migrating serial drivers.
>>> Since many devices are based on the original 8250/16550 designs
>>> but sometimes have features incompatible with the existing 8250 driver
>>> support, the initial driver is often standalone. When/if the standalone
>>> driver is migrated to the 8250 driver, the problem of console names in
>>> the command line remains. Extensible console matching enables a simple
>>> migration path.
>>>
>>>
>>> Direct earlycon
>>>
>>> This feature enables arches and proms to start an earlycon directly,
>>> rather than requiring an "earlycon=" command line parameter.
>>> Devicetree can already do this via the 'linux,stdout-path' property,
>>> but arch and prom code requires direct coupling to the serial driver.
>>>
>>> This support is implemented by judicious refactoring and the same
>>> construct that devicetree and early_param use: a link table containing
>>> the necessary information (name and setup() function) to find and
>>> bind the appropriate earlycon "driver".
>>
>> I've skimmed thru this and it looks like a great improvement.
>>
>> One problem we have currently with DT stdout-path and earlycon is a
>> preferred console does not get registered, so the console will get
>> switched to tty0 and you lose your console. The problem is DT does not
>> know the console name to register a preferred console. It looks like
>> this series may help this problem, but I'm not sure and wanted your
>> thoughts.
>
> I thought that of_alias_scan() + of_console_check() caused DT stdout-path
> to add_preferred_console() the driver console @ port registration time
> via uart_add_one_port() -> of_console_check().
>
> Is that not how that works?

Yes, I believe that is how it works with earlycon not enabled. This
doesn't work when earlycon is enabled with just "earlycon" on the
command line. The fix I have is here[1], but I don't like putting DT
specifics into the console code.

Rob

[1] https://lkml.org/lkml/2014/7/25/333

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core
  2015-02-24 16:36 ` [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core Peter Hurley
@ 2015-02-25 13:03   ` Peter Hurley
  0 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-25 13:03 UTC (permalink / raw)
  To: Joe Perches
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Rob Herring,
	Jiri Slaby, linux-serial, Linux kernel, Eldad Zack

Hi Joe,

checkpatch warns on the line below:

On 02/24/2015 11:36 AM, Peter Hurley wrote:
> Prepare to support console-defined matching; refactor the command
> line parameter string processing from parse_options() into a
> new core function, uart_parse_earlycon(), which decodes command line
> parameters of the form:
>    earlycon=<name>,io|mmio|mmio32,<addr>,<options>
>    console=<name>,io|mmio|mmio32,<addr>,<options>
>    earlycon=<name>,0x<addr>,<options>
>    console=<name>,0x<addr>,<options>
> 
> Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
> ---
>  drivers/tty/serial/earlycon.c    | 39 ++++++++++++----------------------
>  drivers/tty/serial/serial_core.c | 46 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/serial_core.h      |  2 ++
>  3 files changed, 61 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
> index 64fe25a..58d6bcd 100644
> --- a/drivers/tty/serial/earlycon.c
> +++ b/drivers/tty/serial/earlycon.c
> @@ -54,44 +54,31 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
>  	return base;
>  }
>  
> -static int __init parse_options(struct earlycon_device *device,
> -				char *options)
> +static int __init parse_options(struct earlycon_device *device, char *options)
>  {
>  	struct uart_port *port = &device->port;
> -	int mmio, mmio32, length;
> +	int length;
>  	unsigned long addr;
>  
> -	if (!options)
> -		return -ENODEV;
> +	if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
> +		return -EINVAL;
>  
> -	mmio = !strncmp(options, "mmio,", 5);
> -	mmio32 = !strncmp(options, "mmio32,", 7);
> -	if (mmio || mmio32) {
> -		port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
> -		options += mmio ? 5 : 7;
> -		addr = simple_strtoul(options, NULL, 0);
> +	switch (port->iotype) {
> +	case UPIO_MEM32:
> +		port->regshift = 2;	/* fall-through */
> +	case UPIO_MEM:
>  		port->mapbase = addr;
> -		if (mmio32)
> -			port->regshift = 2;
> -	} else if (!strncmp(options, "io,", 3)) {
> -		port->iotype = UPIO_PORT;
> -		options += 3;
> -		addr = simple_strtoul(options, NULL, 0);
> +		break;
> +	case UPIO_PORT:
>  		port->iobase = addr;
> -		mmio = 0;
> -	} else if (!strncmp(options, "0x", 2)) {
> -		port->iotype = UPIO_MEM;
> -		addr = simple_strtoul(options, NULL, 0);
> -		port->mapbase = addr;
> -	} else {
> +		break;
> +	default:
>  		return -EINVAL;
>  	}
>  
>  	port->uartclk = BASE_BAUD * 16;
>  
> -	options = strchr(options, ',');
>  	if (options) {
> -		options++;
>  		device->baud = simple_strtoul(options, NULL, 0);
>  		length = min(strcspn(options, " ") + 1,
>  			     (size_t)(sizeof(device->options)));
> @@ -100,7 +87,7 @@ static int __init parse_options(struct earlycon_device *device,
>  
>  	if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
>  		pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
> -			mmio32 ? "32" : "",
> +			(port->iotype == UPIO_MEM32) ? "32" : "",
>  			(unsigned long long)port->mapbase,
>  			device->options);
>  	else
> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
> index 6a1055a..3f823c26 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -1810,6 +1810,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
>  }
>  
>  /**
> + *	uart_parse_earlycon - Parse earlycon options
> + *	@p:	  ptr to 2nd field (ie., just beyond '<name>,')
> + *	@iotype:  ptr for decoded iotype (out)
> + *	@addr:    ptr for decoded mapbase/iobase (out)
> + *	@options: ptr for <options> field; NULL if not present (out)
> + *
> + *	Decodes earlycon kernel command line parameters of the form
> + *	   earlycon=<name>,io|mmio|mmio32,<addr>,<options>
> + *	   console=<name>,io|mmio|mmio32,<addr>,<options>
> + *
> + *	The optional form
> + *	   earlycon=<name>,0x<addr>,<options>
> + *	   console=<name>,0x<addr>,<options>
> + *	is also accepted; the returned @iotype will be UPIO_MEM.
> + *
> + *	Returns 0 on success or -EINVAL on failure
> + */
> +int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
> +			char **options)
> +{
> +	if (strncmp(p, "mmio,", 5) == 0) {
> +		*iotype = UPIO_MEM;
> +		p += 5;
> +	} else if (strncmp(p, "mmio32,", 7) == 0) {
> +		*iotype = UPIO_MEM32;
> +		p += 7;
> +	} else if (strncmp(p, "io,", 3) == 0) {
> +		*iotype = UPIO_PORT;
> +		p += 3;
> +	} else if (strncmp(p, "0x", 2) == 0) {
> +		*iotype = UPIO_MEM;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	*addr = simple_strtoul(p, NULL, 0);

WARNING: simple_strtoul is obsolete, use kstrtoul instead
#136: FILE: drivers/tty/serial/serial_core.c:1848:
+	*addr = simple_strtoul(p, NULL, 0);


simple_strtoul() is _not_ obsolete.
kstrtoul() cannot parse the <addr> field in a string of the form:

	console=<name>,io|mmio|mmio32,<addr>,<options>

kstrtoul() returns EINVAL without the result.

It was pretty fun debugging that without a console :/

Regards,
Peter Hurley

> +	p = strchr(p, ',');
> +	if (p)
> +		p++;
> +
> +	*options = p;
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(uart_parse_earlycon);
> +
> +/**
>   *	uart_parse_options - Parse serial port baud/parity/bits/flow control.
>   *	@options: pointer to option string
>   *	@baud: pointer to an 'int' variable for the baud rate.
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index baf3e1d..cc5c506 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -354,6 +354,8 @@ early_param("earlycon", name ## _setup_earlycon);
>  
>  struct uart_port *uart_get_console(struct uart_port *ports, int nr,
>  				   struct console *c);
> +int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
> +			char **options);
>  void uart_parse_options(char *options, int *baud, int *parity, int *bits,
>  			int *flow);
>  int uart_set_options(struct uart_port *port, struct console *co, int baud,
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-24 20:20     ` Rob Herring
@ 2015-02-26 14:48       ` Peter Hurley
  2015-02-26 14:58         ` Rob Herring
  0 siblings, 1 reply; 24+ messages in thread
From: Peter Hurley @ 2015-02-26 14:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

Hi Rob,

On 02/24/2015 03:20 PM, Rob Herring wrote:
> On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:

[...]

>>>> Direct earlycon
>>>>
>>>> This feature enables arches and proms to start an earlycon directly,
>>>> rather than requiring an "earlycon=" command line parameter.
>>>> Devicetree can already do this via the 'linux,stdout-path' property,
>>>> but arch and prom code requires direct coupling to the serial driver.
>>>>
>>>> This support is implemented by judicious refactoring and the same
>>>> construct that devicetree and early_param use: a link table containing
>>>> the necessary information (name and setup() function) to find and
>>>> bind the appropriate earlycon "driver".
>>>
>>> I've skimmed thru this and it looks like a great improvement.
>>>
>>> One problem we have currently with DT stdout-path and earlycon is a
>>> preferred console does not get registered, so the console will get
>>> switched to tty0 and you lose your console. The problem is DT does not
>>> know the console name to register a preferred console. It looks like
>>> this series may help this problem, but I'm not sure and wanted your
>>> thoughts.
>>
>> I thought that of_alias_scan() + of_console_check() caused DT stdout-path
>> to add_preferred_console() the driver console @ port registration time
>> via uart_add_one_port() -> of_console_check().
>>
>> Is that not how that works?
> 
> Yes, I believe that is how it works with earlycon not enabled. This
> doesn't work when earlycon is enabled with just "earlycon" on the
> command line. The fix I have is here[1], but I don't like putting DT
> specifics into the console code.

After much gnashing of teeth and pulling of hair yesterday, I managed
to mock up the situation you describe, but I need to study it in more
detail. Some things I did learn:

1. The serial console _does_ come back up when using stdout-path but the
   line settings don't match, because the serial core sets them to the
   default of 9600n8 if unspecified.

2. The line settings can now be set with stdout-path like,
     stdout-path = "serial0:115200n8"
   but this breaks DT earlycon (as I wrote in the other email you were
   cc'd on).

3. omap doesn't support ioremap() at early param parsing :(

4. the ARM arch doesn't support fixmap hacking at early param parsing :(

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-26 14:48       ` Peter Hurley
@ 2015-02-26 14:58         ` Rob Herring
  2015-02-26 15:54           ` Peter Hurley
  2015-03-01 17:40           ` Peter Hurley
  0 siblings, 2 replies; 24+ messages in thread
From: Rob Herring @ 2015-02-26 14:58 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

On Thu, Feb 26, 2015 at 8:48 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
> Hi Rob,
>
> On 02/24/2015 03:20 PM, Rob Herring wrote:
>> On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:
>
> [...]
>
>>>>> Direct earlycon
>>>>>
>>>>> This feature enables arches and proms to start an earlycon directly,
>>>>> rather than requiring an "earlycon=" command line parameter.
>>>>> Devicetree can already do this via the 'linux,stdout-path' property,
>>>>> but arch and prom code requires direct coupling to the serial driver.
>>>>>
>>>>> This support is implemented by judicious refactoring and the same
>>>>> construct that devicetree and early_param use: a link table containing
>>>>> the necessary information (name and setup() function) to find and
>>>>> bind the appropriate earlycon "driver".
>>>>
>>>> I've skimmed thru this and it looks like a great improvement.
>>>>
>>>> One problem we have currently with DT stdout-path and earlycon is a
>>>> preferred console does not get registered, so the console will get
>>>> switched to tty0 and you lose your console. The problem is DT does not
>>>> know the console name to register a preferred console. It looks like
>>>> this series may help this problem, but I'm not sure and wanted your
>>>> thoughts.
>>>
>>> I thought that of_alias_scan() + of_console_check() caused DT stdout-path
>>> to add_preferred_console() the driver console @ port registration time
>>> via uart_add_one_port() -> of_console_check().
>>>
>>> Is that not how that works?
>>
>> Yes, I believe that is how it works with earlycon not enabled. This
>> doesn't work when earlycon is enabled with just "earlycon" on the
>> command line. The fix I have is here[1], but I don't like putting DT
>> specifics into the console code.
>
> After much gnashing of teeth and pulling of hair yesterday, I managed
> to mock up the situation you describe, but I need to study it in more
> detail. Some things I did learn:
>
> 1. The serial console _does_ come back up when using stdout-path but the
>    line settings don't match, because the serial core sets them to the
>    default of 9600n8 if unspecified.

That may have been what I saw as I tested on QEMU which ignores the
baud rate. But it does stop between the time tty0 is enabled and the
"real" serial console which is a time period we really want the
console.

> 2. The line settings can now be set with stdout-path like,
>      stdout-path = "serial0:115200n8"
>    but this breaks DT earlycon (as I wrote in the other email you were
>    cc'd on).

Right. We should fix libfdt.

> 3. omap doesn't support ioremap() at early param parsing :(

ARM in general does not.

> 4. the ARM arch doesn't support fixmap hacking at early param parsing :(

There's a patch on the list to enable it. It's been slow as fixmap has
been a moving target.

Rob

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-26 14:58         ` Rob Herring
@ 2015-02-26 15:54           ` Peter Hurley
  2015-02-26 16:09             ` Rob Herring
  2015-03-01 17:40           ` Peter Hurley
  1 sibling, 1 reply; 24+ messages in thread
From: Peter Hurley @ 2015-02-26 15:54 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

On 02/26/2015 09:58 AM, Rob Herring wrote:
> On Thu, Feb 26, 2015 at 8:48 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
>> Hi Rob,
>>
>> On 02/24/2015 03:20 PM, Rob Herring wrote:
>>> On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:
>>
>> [...]
>>
>>>>>> Direct earlycon
>>>>>>
>>>>>> This feature enables arches and proms to start an earlycon directly,
>>>>>> rather than requiring an "earlycon=" command line parameter.
>>>>>> Devicetree can already do this via the 'linux,stdout-path' property,
>>>>>> but arch and prom code requires direct coupling to the serial driver.
>>>>>>
>>>>>> This support is implemented by judicious refactoring and the same
>>>>>> construct that devicetree and early_param use: a link table containing
>>>>>> the necessary information (name and setup() function) to find and
>>>>>> bind the appropriate earlycon "driver".
>>>>>
>>>>> I've skimmed thru this and it looks like a great improvement.
>>>>>
>>>>> One problem we have currently with DT stdout-path and earlycon is a
>>>>> preferred console does not get registered, so the console will get
>>>>> switched to tty0 and you lose your console. The problem is DT does not
>>>>> know the console name to register a preferred console. It looks like
>>>>> this series may help this problem, but I'm not sure and wanted your
>>>>> thoughts.
>>>>
>>>> I thought that of_alias_scan() + of_console_check() caused DT stdout-path
>>>> to add_preferred_console() the driver console @ port registration time
>>>> via uart_add_one_port() -> of_console_check().
>>>>
>>>> Is that not how that works?
>>>
>>> Yes, I believe that is how it works with earlycon not enabled. This
>>> doesn't work when earlycon is enabled with just "earlycon" on the
>>> command line. The fix I have is here[1], but I don't like putting DT
>>> specifics into the console code.
>>
>> After much gnashing of teeth and pulling of hair yesterday, I managed
>> to mock up the situation you describe, but I need to study it in more
>> detail. Some things I did learn:
>>
>> 1. The serial console _does_ come back up when using stdout-path but the
>>    line settings don't match, because the serial core sets them to the
>>    default of 9600n8 if unspecified.
> 
> That may have been what I saw as I tested on QEMU which ignores the
> baud rate. But it does stop between the time tty0 is enabled and the
> "real" serial console which is a time period we really want the
> console.

Yeah, that's what my mock-up showed as well:

[    0.000000] Machine model: TI AM335x BeagleBone Black
[    0.000000] earlycon:serial0 options:115200
[    0.000000] early_omap8250_setup: uart @ 44e09000
[    0.000000] bootconsole [uart0] enabled
....
[    0.000349] Console: colour dummy device 80x30
[    0.000367] console [tty0] enabled
[    0.000395] bootconsole [uart0] disabled
[    0.000441] Calibrating delay loop... 995.32 BogoMIPS (lpj=1990656)
....
[    1.097762] Serial: 8250/16550 driver, 32 ports, IRQ sharing disabled
[    1.107659] 44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 154, base_baud = 3000000) is a 8250
[    1.888536] console [ttyS0] enabled
[    1.893036] 481a8000.serial: ttyS4 at MMIO 0x481a8000 (irq = 155, base_baud = 3000000) is a 8250
[    1.902810] 481aa000.serial: ttyS5 at MMIO 0x481aa000 (irq = 156, base_baud = 3000000) is a 8250


>> 2. The line settings can now be set with stdout-path like,
>>      stdout-path = "serial0:115200n8"
>>    but this breaks DT earlycon (as I wrote in the other email you were
>>    cc'd on).
> 
> Right. We should fix libfdt.
> 
>> 3. omap doesn't support ioremap() at early param parsing :(
> 
> ARM in general does not.

I was looking at mach-bcm to see how it was that the iotable_init() didn't
blow up, but maybe it does?

>> 4. the ARM arch doesn't support fixmap hacking at early param parsing :(
> 
> There's a patch on the list to enable it. It's been slow as fixmap has
> been a moving target.

Thanks. That's similar to what I cribbed from ARM64 arch last night.

Regards,
Peter Hurley


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-26 15:54           ` Peter Hurley
@ 2015-02-26 16:09             ` Rob Herring
  0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2015-02-26 16:09 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel

On Thu, Feb 26, 2015 at 9:54 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
> On 02/26/2015 09:58 AM, Rob Herring wrote:
>> On Thu, Feb 26, 2015 at 8:48 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
>>> Hi Rob,
>>>
>>> On 02/24/2015 03:20 PM, Rob Herring wrote:
>>>> On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:

[...]

>>> 3. omap doesn't support ioremap() at early param parsing :(
>>
>> ARM in general does not.
>
> I was looking at mach-bcm to see how it was that the iotable_init() didn't
> blow up, but maybe it does?

iotable_init is basically just a list of page table entries to create
and uses the early page table setup code.

Rob

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 03/13] console: Add extensible console matching
  2015-02-24 16:37 ` [PATCH -next 03/13] console: Add extensible console matching Peter Hurley
@ 2015-02-28 17:18   ` Peter Hurley
  0 siblings, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-02-28 17:18 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andrew Morton
  Cc: Arnd Bergmann, Rob Herring, Jiri Slaby, linux-serial, linux-kernel

On 02/24/2015 11:37 AM, Peter Hurley wrote:
> 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.
> 
> Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
> ---
>  drivers/tty/serial/8250/8250_core.c  | 64 +++++++++++++++++++++++++++---------
>  drivers/tty/serial/8250/8250_early.c | 23 -------------
>  include/linux/console.h              |  3 +-
>  include/linux/serial_8250.h          |  2 --
>  kernel/printk/printk.c               | 50 ++++++++++------------------
>  5 files changed, 66 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index e3b9570a..5eb95fd 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -3337,9 +3337,54 @@ static int serial8250_console_setup(struct console *co, char *options)
>  	return uart_set_options(port, co, baud, parity, bits, flow);
>  }
>  
> -static int serial8250_console_early_setup(void)
> +/**
> + *	serial8250_console_match - non-standard console matching
> + *	@co:	  registering console
> + *	@name:	  name from console command line
> + *	@idx:	  index from console command line
> + *	@options: ptr to option string from console command line
> + *
> + *	Only attempts to match console command lines of the form:
> + *	    console=uart<>,io|mmio|mmio32,<addr>,<options>
> + *	    console=uart<>,<addr>,options
> + *	This form is used to register an initial earlycon boot console and
> + *	replace it with the serial8250_console at 8250 driver init.
> + *
> + *	Performs console setup for a match (as required by interface)
> + *
> + *	Returns 0 if console matches; otherwise non-zero to use default matching
> + */
> +static int serial8250_console_match(struct console *co, char *name, int idx,
> +				    char *options)
>  {
> -	return serial8250_find_port_for_earlycon();
> +	char match[] = "uart";	/* 8250-specific earlycon name */
> +	unsigned char iotype;
> +	unsigned long addr;
> +	int i;
> +
> +	if (strncmp(name, match, 4) != 0)
> +		return -ENODEV;
> +
> +	if (uart_parse_earlycon(options, &iotype, &addr, &options))
> +		return -ENODEV;
> +
> +	/* try to match the port specified on the command line */
> +	for (i = 0; i < nr_uarts; i++) {
> +		struct uart_port *port = &serial8250_ports[i].port;
> +
> +		if (port->iotype != iotype)
> +			continue;
> +		if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
> +		    (port->mapbase != addr))
> +			continue;
> +		if (iotype == UPIO_PORT && port->iobase != addr)
> +			continue;
> +
> +		co->index = i;
> +		return serial8250_console_setup(co, options);
> +	}
> +
> +	return -ENODEV;
>  }
>  
>  static struct console serial8250_console = {
> @@ -3347,7 +3392,7 @@ static struct console serial8250_console = {
>  	.write		= serial8250_console_write,
>  	.device		= uart_console_device,
>  	.setup		= serial8250_console_setup,
> -	.early_setup	= serial8250_console_early_setup,
> +	.match		= serial8250_console_match,
>  	.flags		= CON_PRINTBUFFER | CON_ANYTIME,
>  	.index		= -1,
>  	.data		= &serial8250_reg,
> @@ -3361,19 +3406,6 @@ static int __init serial8250_console_init(void)
>  }
>  console_initcall(serial8250_console_init);
>  
> -int serial8250_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;
> -}
> -
>  #define SERIAL8250_CONSOLE	&serial8250_console
>  #else
>  #define SERIAL8250_CONSOLE	NULL
> diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
> index c31a22b..49bca65 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)
>  
>  	return setup_earlycon(cmdline, match, early_serial8250_setup);
>  }
> -
> -int serial8250_find_port_for_earlycon(void)
> -{
> -	struct earlycon_device *device = early_device;
> -	struct uart_port *port = device ? &device->port : NULL;
> -	int line;
> -	int ret;
> -
> -	if (!port || (!port->membase && !port->iobase))
> -		return -ENODEV;
> -
> -	line = serial8250_find_port(port);
> -	if (line < 0)
> -		return -ENODEV;
> -
> -	ret = update_console_cmdline("uart", 8250,
> -			     "ttyS", line, device->options);
> -	if (ret < 0)
> -		ret = update_console_cmdline("uart", 0,
> -				     "ttyS", line, device->options);
> -
> -	return ret;
> -}
> diff --git a/include/linux/console.h b/include/linux/console.h
> index 7571a16..9f50fb4 100644
> --- a/include/linux/console.h
> +++ b/include/linux/console.h
> @@ -123,7 +123,7 @@ struct console {
>  	struct tty_driver *(*device)(struct console *, int *);
>  	void	(*unblank)(void);
>  	int	(*setup)(struct console *, char *);
> -	int	(*early_setup)(void);
> +	int	(*match)(struct console *, char *name, int idx, char *options);
>  	short	flags;
>  	short	index;
>  	int	cflag;
> @@ -141,7 +141,6 @@ extern int console_set_on_cmdline;
>  extern struct console *early_console;
>  
>  extern int add_preferred_console(char *name, int idx, char *options);
> -extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
>  extern void register_console(struct console *);
>  extern int unregister_console(struct console *);
>  extern struct console *console_drivers;
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index a8efa23..f26ae7f 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -118,8 +118,6 @@ void serial8250_resume_port(int line);
>  
>  extern int early_serial_setup(struct uart_port *port);
>  
> -extern int serial8250_find_port(struct uart_port *p);
> -extern int serial8250_find_port_for_earlycon(void);
>  extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
>  extern void serial8250_early_out(struct uart_port *port, int offset, int value);
>  extern int setup_early_serial8250_console(char *cmdline);
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index ce5c297..040be39 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)
>  	return __add_preferred_console(name, idx, options, NULL);
>  }
>  
> -int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
> -{
> -	struct console_cmdline *c;
> -	int i;
> -
> -	for (i = 0, c = console_cmdline;
> -	     i < MAX_CMDLINECONSOLES && c->name[0];
> -	     i++, c++)
> -		if (strcmp(c->name, name) == 0 && c->index == idx) {
> -			strlcpy(c->name, name_new, sizeof(c->name));
> -			c->options = options;
> -			c->index = idx_new;
> -			return i;
> -		}
> -	/* not found */
> -	return -1;
> -}
> -
>  bool console_suspend_enabled = true;
>  EXPORT_SYMBOL(console_suspend_enabled);
>  
> @@ -2436,9 +2418,6 @@ void register_console(struct console *newcon)
>  	if (preferred_console < 0 || bcon || !console_drivers)
>  		preferred_console = selected_console;
>  
> -	if (newcon->early_setup)
> -		newcon->early_setup();
> -
>  	/*
>  	 *	See if we want to use this console driver. If we
>  	 *	didn't select a console we take the first one
> @@ -2464,20 +2443,25 @@ void register_console(struct console *newcon)
>  	for (i = 0, c = console_cmdline;
>  	     i < MAX_CMDLINECONSOLES && c->name[0];
>  	     i++, c++) {
> -		if (strcmp(c->name, newcon->name) != 0)
> -			continue;

Andrew,

I just discovered that struct console_cmdline::name[] and
struct console::name[] are not the same size, which is a bug that
should probably go into -stable.

I'll respin a v2 of this series on top of that bug fix, which I'll
send shortly.

Regards,
Peter Hurley

> -		if (newcon->index >= 0 &&
> -		    newcon->index != c->index)
> -			continue;
> -		if (newcon->index < 0)
> -			newcon->index = c->index;
> +		if (!newcon->match ||
> +		    newcon->match(newcon, c->name, c->index, c->options) != 0) {
> +			/* default matching */
> +			if (strcmp(c->name, newcon->name) != 0)
> +				continue;
> +			if (newcon->index >= 0 &&
> +			    newcon->index != c->index)
> +				continue;
> +			if (newcon->index < 0)
> +				newcon->index = c->index;
>  
> -		if (_braille_register_console(newcon, c))
> -			return;
> +			if (_braille_register_console(newcon, c))
> +				return;
> +
> +			if (newcon->setup &&
> +			    newcon->setup(newcon, c->options) != 0)
> +				break;
> +		}
>  
> -		if (newcon->setup &&
> -		    newcon->setup(newcon, console_cmdline[i].options) != 0)
> -			break;
>  		newcon->flags |= CON_ENABLED;
>  		if (i == selected_console) {
>  			newcon->flags |= CON_CONSDEV;
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH -next 00/13] Extensible console matching & direct earlycon
  2015-02-26 14:58         ` Rob Herring
  2015-02-26 15:54           ` Peter Hurley
@ 2015-03-01 17:40           ` Peter Hurley
  1 sibling, 0 replies; 24+ messages in thread
From: Peter Hurley @ 2015-03-01 17:40 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Andrew Morton, Arnd Bergmann, Jiri Slaby,
	linux-serial, linux-kernel, devicetree, mark.rutland,
	grant.likely@linaro.org >> Grant Likely

[ +cc devicetree, Mark Rutland, Grant Likely ]

On 02/26/2015 09:58 AM, Rob Herring wrote:
> On Thu, Feb 26, 2015 at 8:48 AM, Peter Hurley <peter@hurleysoftware.com> wrote:
>> Hi Rob,
>>
>> On 02/24/2015 03:20 PM, Rob Herring wrote:
>>> On Tue, Feb 24, 2015 at 1:53 PM, Peter Hurley <peter@hurleysoftware.com> wrote:
>>
>> [...]
>>
>>>>>> Direct earlycon
>>>>>>
>>>>>> This feature enables arches and proms to start an earlycon directly,
>>>>>> rather than requiring an "earlycon=" command line parameter.
>>>>>> Devicetree can already do this via the 'linux,stdout-path' property,
>>>>>> but arch and prom code requires direct coupling to the serial driver.
>>>>>>
>>>>>> This support is implemented by judicious refactoring and the same
>>>>>> construct that devicetree and early_param use: a link table containing
>>>>>> the necessary information (name and setup() function) to find and
>>>>>> bind the appropriate earlycon "driver".
>>>>>
>>>>> I've skimmed thru this and it looks like a great improvement.
>>>>>
>>>>> One problem we have currently with DT stdout-path and earlycon is a
>>>>> preferred console does not get registered, so the console will get
>>>>> switched to tty0 and you lose your console. The problem is DT does not
>>>>> know the console name to register a preferred console. It looks like
>>>>> this series may help this problem, but I'm not sure and wanted your
>>>>> thoughts.
>>>>
>>>> I thought that of_alias_scan() + of_console_check() caused DT stdout-path
>>>> to add_preferred_console() the driver console @ port registration time
>>>> via uart_add_one_port() -> of_console_check().
>>>>
>>>> Is that not how that works?
>>>
>>> Yes, I believe that is how it works with earlycon not enabled. This
>>> doesn't work when earlycon is enabled with just "earlycon" on the
>>> command line. The fix I have is here[1], but I don't like putting DT
>>> specifics into the console code.
>>
>> After much gnashing of teeth and pulling of hair yesterday, I managed
>> to mock up the situation you describe, but I need to study it in more
>> detail. Some things I did learn:
>>
>> 1. The serial console _does_ come back up when using stdout-path but the
>>    line settings don't match, because the serial core sets them to the
>>    default of 9600n8 if unspecified.
> 
> That may have been what I saw as I tested on QEMU which ignores the
> baud rate. But it does stop between the time tty0 is enabled and the
> "real" serial console which is a time period we really want the
> console.

The bug is that of_alias_scan() does not emit a preferred console, but
rather defers it until of_console_check().

In many setups, this means there is no preferred console. So when the
dummy vt console loads (which happens via console_init()), all the boot
consoles are disabled.

The trivial fix is to emit a preferred console from of_alias_scan(), even
if that console is never matched. I've sent you a patch to do just that.


>> 2. The line settings can now be set with stdout-path like,
>>      stdout-path = "serial0:115200n8"
>>    but this breaks DT earlycon (as I wrote in the other email you were
>>    cc'd on).
> 
> Right. We should fix libfdt.

Ok.

Regards,
Peter Hurley


^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2015-03-01 17:40 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-24 16:36 [PATCH -next 00/13] Extensible console matching & direct earlycon Peter Hurley
2015-02-24 16:36 ` [PATCH -next 01/13] serial: earlycon: Refactor parse_options into serial core Peter Hurley
2015-02-25 13:03   ` Peter Hurley
2015-02-24 16:36 ` [PATCH -next 02/13] console: Preserve index after console setup() Peter Hurley
2015-02-24 16:37 ` [PATCH -next 03/13] console: Add extensible console matching Peter Hurley
2015-02-28 17:18   ` Peter Hurley
2015-02-24 16:37 ` [PATCH -next 04/13] serial: core: Fix kernel doc for uart_console_write() Peter Hurley
2015-02-24 16:37 ` [PATCH -next 05/13] serial: 8250_early: Remove early_device variable Peter Hurley
2015-02-24 16:37 ` [PATCH -next 06/13] serial: earlycon: Move ->uartclk initialize Peter Hurley
2015-02-24 16:37 ` [PATCH -next 07/13] serial: 8250_early: Assume uart already initialized if no baud option Peter Hurley
2015-02-24 16:37 ` [PATCH -next 08/13] serial: 8250_early: Fix setup() error code Peter Hurley
2015-02-24 16:37 ` [PATCH -next 09/13] serial: earlycon: Ignore parse_options() " Peter Hurley
2015-02-24 16:37 ` [PATCH -next 10/13] serial: earlycon: Allow earlycon params with name only Peter Hurley
2015-02-24 16:37 ` [PATCH -next 11/13] serial: earlycon: Refactor earlycon registration Peter Hurley
2015-02-24 16:37 ` [PATCH -next 12/13] serial: earlycon: Enable earlycon without command line param Peter Hurley
2015-02-24 16:37 ` [PATCH -next 13/13] serial: 8250_early: Remove setup_early_serial8250_console() Peter Hurley
2015-02-24 19:27 ` [PATCH -next 00/13] Extensible console matching & direct earlycon Rob Herring
2015-02-24 19:53   ` Peter Hurley
2015-02-24 20:20     ` Rob Herring
2015-02-26 14:48       ` Peter Hurley
2015-02-26 14:58         ` Rob Herring
2015-02-26 15:54           ` Peter Hurley
2015-02-26 16:09             ` Rob Herring
2015-03-01 17:40           ` Peter Hurley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).