public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] serial: convert early_uart to earlycon for 8250
@ 2007-05-30  1:43 Yinghai Lu
  2007-05-30 18:57 ` Andrew Morton
  2007-05-31  3:13 ` Andrew Morton
  0 siblings, 2 replies; 20+ messages in thread
From: Yinghai Lu @ 2007-05-30  1:43 UTC (permalink / raw)
  To: Andrew Morton, Andi Kleen, Russell King, Bjorn Helgaas
  Cc: Linux Kernel Mailing List

[PATCH 4/5] serial: convert early_uart to earlycon for 8250

Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
include/asm-x86_64/serial.h. the serial8250_ports need to be probed late
in serial initializing stage. the console_init=>serial8250_console_init=>
register_console=>serial8250_console_setup will return -ENDEV, and console
ttyS0 can not be enabled at that time.
need to wait till uart_add_one_port in drivers/serial/serial_core.c to call
register_console to get console ttyS0. that is too late.

Make early_uart to use early_param, so uart console can be used earlier.
Make it to be bootconsole with CON_BOOT flag, so can use console handover
feature. and it will switch to corresponding normal serial console
automatically.

new command line will be:
	console=uart8250,io,0x3f8,9600n8
	console=uart8250,mmio,0xff5e0000,115200n8
or
	earlycon=uart8250,io,0x3f8,9600n8
	earlycon=uart8250,mmio,0xff5e0000,115200n8

it will print in very early stage:
	Early serial console at I/O port 0x3f8 (options '9600n8')
	console [uart0] enabled
later for console it will print:
	console handover: boot [uart0] -> real [ttyS0]

Signed-off-by: <yinghai.lu@sun.com>

 Documentation/kernel-parameters.txt |   11 +++
 arch/ia64/kernel/setup.c            |    4 -
 drivers/serial/8250.c               |   28 ++-------
 drivers/serial/8250_early.c         |  104 ++++++++++++++----------------------
 drivers/serial/Kconfig              |   10 +++
 include/asm-i386/fixmap.h           |    2 
 include/asm-i386/io.h               |   13 ++++
 include/asm-ia64/io.h               |    4 +
 include/asm-x86_64/fixmap.h         |    4 +
 include/asm-x86_64/io.h             |   13 ++++
 include/linux/console.h             |    2 
 include/linux/serial.h              |    6 --
 include/linux/serial_8250.h         |    3 +
 init/main.c                         |    5 +
 kernel/printk.c                     |   22 +++++++
 15 files changed, 133 insertions(+), 98 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aae2282..b51fbac 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -464,13 +464,20 @@ and is between 256 and 4096 characters. It is defined in the file
 			Documentation/networking/netconsole.txt for an
 			alternative.
 
-		uart,io,<addr>[,options]
-		uart,mmio,<addr>[,options]
+		uart8250,io,<addr>[,options]
+		uart8250,mmio,<addr>[,options]
 			Start an early, polled-mode console on the 8250/16550
 			UART at the specified I/O port or MMIO address,
 			switching to the matching ttyS device later.  The
 			options are the same as for ttyS, above.
 
+	earlycon=	[KNL] Output early console device and options.
+		uart8250,io,<addr>[,options]
+		uart8250,mmio,<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address.
+			The options are the same as for ttyS, above.
+
 	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
 			Format:
 			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24..dd7f95b 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@ early_console_setup (char *cmdline)
 	if (!efi_setup_pcdp_console(cmdline))
 		earlycons++;
 #endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	if (!early_serial_console_init(cmdline))
-		earlycons++;
-#endif
 
 	return (earlycons) ? 0 : -1;
 }
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab0..0b3ec38 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options)
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
+static int __init serial8250_console_early_setup(void)
+{
+	return serial8250_find_port_for_earlycon();
+}
+
 static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
 	.name		= "ttyS",
 	.write		= serial8250_console_write,
 	.device		= uart_console_device,
 	.setup		= serial8250_console_setup,
+	.early_setup	= serial8250_console_early_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.data		= &serial8250_reg,
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void)
 }
 console_initcall(serial8250_console_init);
 
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
 {
 	int line;
 	struct uart_port *port;
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p)
 	return -ENODEV;
 }
 
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
-	int line;
-
-	line = find_port(port);
-	if (line < 0)
-		return -ENODEV;
-
-	add_preferred_console("ttyS", line, options);
-	printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
-		line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
-		port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
-		    (unsigned long) port->iobase, options);
-	if (!(serial8250_console.flags & CON_ENABLED)) {
-		serial8250_console.flags &= ~CON_PRINTBUFFER;
-		register_console(&serial8250_console);
-	}
-	return line;
-}
-
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
 #define SERIAL8250_CONSOLE	NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e51119..820d164 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
  * we locate the device directly by its MMIO or I/O port address.
  *
  * The user can specify the device directly, e.g.,
- *	console=uart,io,0x3f8,9600n8
- *	console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ *	earlycon=uart8250,io,0x3f8,9600n8
+ *	earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ *	console=uart8250,io,0x3f8,9600n8
+ *	console=uart8250,mmio,0xff5e0000,115200n8
  */
 
 #include <linux/tty.h>
@@ -32,17 +30,17 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/io.h>
 #include <asm/serial.h>
 
-struct early_uart_device {
+struct early_serial8250_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
 };
 
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
 
 static unsigned int __init serial_in(struct uart_port *port, int offset)
 {
@@ -80,7 +78,7 @@ static void __init putc(struct uart_port *port, int c)
 	serial_out(port, UART_TX, c);
 }
 
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
 {
 	struct uart_port *port = &early_device.port;
 	unsigned int ier;
@@ -111,7 +109,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
 	return (port->uartclk / 16) / quot;
 }
 
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
 {
 	struct uart_port *port = &device->port;
 	unsigned int divisor;
@@ -130,10 +128,9 @@ static void __init init_port(struct early_uart_device *device)
 	serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
 {
 	struct uart_port *port = &device->port;
-	int mapsize = 64;
 	int mmio, length;
 
 	if (!options)
@@ -143,12 +140,7 @@ static int __init parse_options(struct early_uart_device *device, char *options)
 	if (!strncmp(options, "mmio,", 5)) {
 		port->iotype = UPIO_MEM;
 		port->mapbase = simple_strtoul(options + 5, &options, 0);
-		port->membase = ioremap(port->mapbase, mapsize);
-		if (!port->membase) {
-			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
-				__FUNCTION__, port->mapbase);
-			return -ENOMEM;
-		}
+		port->membase = fix_ioremap(FIX_EARLYCON_MEM_BASE, port->mapbase);
 		mmio = 1;
 	} else if (!strncmp(options, "io,", 3)) {
 		port->iotype = UPIO_PORT;
@@ -175,9 +167,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
 	return 0;
 }
 
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+	.name	= "uart",
+	.write	= early_serial8250_write,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+static int __init early_serial8250_setup(char *options)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	int err;
 
 	if (device->port.membase || device->port.iobase)
@@ -190,61 +189,40 @@ static int __init early_uart_setup(struct console *console, char *options)
 	return 0;
 }
 
-static struct console early_uart_console __initdata = {
-	.name	= "uart",
-	.write	= early_uart_write,
-	.setup	= early_uart_setup,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-static int __init early_uart_console_init(void)
-{
-	if (!early_uart_registered) {
-		register_console(&early_uart_console);
-		early_uart_registered = 1;
-	}
-	return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+static int __init setup_early_serial8250_console(char *cmdline)
 {
 	char *options;
 	int err;
 
-	options = strstr(cmdline, "console=uart,");
+	options = strstr(cmdline, "uart8250,");
 	if (!options)
-		return -ENODEV;
+		return 0;
 
 	options = strchr(cmdline, ',') + 1;
-	if ((err = early_uart_setup(NULL, options)) < 0)
+	if ((err = early_serial8250_setup(options)) < 0)
 		return err;
-	return early_uart_console_init();
+
+	early_serial8250_console.flags |= CON_BOOT;
+	register_console(&early_serial8250_console);
+
+	return 0;
 }
 
-static int __init early_uart_console_switch(void)
+int serial8250_find_port_for_earlycon(void)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	struct uart_port *port = &device->port;
-	int mmio, line;
+	int line;
 
-	if (!(early_uart_console.flags & CON_ENABLED))
-		return 0;
+	if (!device->port.membase && !device->port.iobase)
+		return -ENODEV;
 
-	/* Try to start the normal driver on a matching line.  */
-	mmio = (port->iotype == UPIO_MEM);
-	line = serial8250_start_console(port, device->options);
+	line = serial8250_find_port(port);
 	if (line < 0)
-		printk("No ttyS device at %s 0x%lx for console\n",
-			mmio ? "MMIO" : "I/O port",
-			mmio ? port->mapbase :
-			    (unsigned long) port->iobase);
-
-	unregister_console(&early_uart_console);
-	if (mmio)
-		iounmap(port->membase);
+		return -ENODEV;
 
-	return 0;
+	return update_console_cmdline("uart", 8250,
+				     "ttyS", line, device->options);
 }
-late_initcall(early_uart_console_switch);
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 315ea99..4a43fd6 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,6 +62,16 @@ config SERIAL_8250_CONSOLE
 	  kernel will automatically use the first serial line, /dev/ttyS0, as
 	  system console.
 
+	  you can set that using a kernel command line option such as
+	  "console=uart8250,io,0x3f8,9600n8"
+	  "console=uart8250,mmio,0xff5e0000,115200n8".
+	  and it will switch to normal serial console when correponding port is
+	  ready.
+	  "earlycon=uart8250,io,0x3f8,9600n8"
+	  "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+	  it will not only setup early console.
+
+
 	  If unsure, say N.
 
 config SERIAL_8250_GSC
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052..249e753 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@ extern unsigned long __FIXADDR_TOP;
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VDSO,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586..6c8748d 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -130,6 +130,19 @@ extern void iounmap(volatile void __iomem *addr);
 extern void *bt_ioremap(unsigned long offset, unsigned long size);
 extern void bt_iounmap(void *addr, unsigned long size);
 
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+
+static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
+{
+	void __iomem * vaddr;
+	set_fixmap_nocache(idx, phys & PAGE_MASK);
+	vaddr = (void __iomem *)__fix_to_virt(idx);
+	vaddr += phys & ~PAGE_MASK;
+
+	return vaddr;
+}
+
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_ioremap bt_ioremap
 #define dmi_iounmap bt_iounmap
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index eb17a86..e29eaf8 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -423,6 +423,10 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
 
+/* for console=uart8250,mmio,0xffe5000,9600n8 */
+#define FIX_EARLYCON_MEM_BASE 1
+#define fix_ioremap(idx, phys) ioremap(phys, 64)
+
 /* Use normal IO mappings for DMI */
 #define dmi_ioremap ioremap
 #define dmi_iounmap(x,l) iounmap(x)
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e167..2acb9b7 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@ enum fixed_addresses {
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
 	VSYSCALL_HPET,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 	FIX_HPET_BASE,
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 	if (idx >= __end_of_fixed_addresses)
 		__this_fixmap_does_not_exist();
 
-        return __fix_to_virt(idx);
+	return __fix_to_virt(idx);
 }
 
 #endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a..e2d66de 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap(volatile void __iomem *addr);
 
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+
+static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
+{
+	void __iomem * vaddr;
+	set_fixmap_nocache(idx, phys & PAGE_MASK);
+	vaddr = (void __iomem *)__fix_to_virt(idx);
+	vaddr += phys & ~PAGE_MASK;
+
+	return vaddr;
+}
+
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
diff --git a/include/linux/console.h b/include/linux/console.h
index 62ef6e1..c44d3df 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -99,6 +99,7 @@ struct console {
 	struct tty_driver *(*device)(struct console *, int *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
+	int	(*early_setup)(void);
 	short	flags;
 	short	index;
 	int	cflag;
@@ -107,6 +108,7 @@ struct 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.h b/include/linux/serial.h
index 33fc8cb..deb7143 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@ struct serial_icounter_struct {
 #ifdef __KERNEL__
 #include <linux/compiler.h>
 
-/* Allow architectures to override entries in serial8250_ports[] at run time: */
-struct uart_port;	/* forward declaration */
-extern int early_serial_setup(struct uart_port *port);
-extern int early_serial_console_init(char *options);
-extern int serial8250_start_console(struct uart_port *port, char *options);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d8..23519fb 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,7 @@ void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
 
+extern int serial8250_find_port(struct uart_port *p);
+extern int serial8250_find_port_for_earlycon(void);
+
 #endif
diff --git a/init/main.c b/init/main.c
index eb8bdba..58dbe75 100644
--- a/init/main.c
+++ b/init/main.c
@@ -452,7 +452,10 @@ static int __init do_early_param(char *param, char *val)
 	struct obs_kernel_param *p;
 
 	for (p = __setup_start; p < __setup_end; p++) {
-		if (p->early && strcmp(param, p->str) == 0) {
+		if ((p->early && strcmp(param, p->str) == 0) ||
+		    (strcmp(param, "console") == 0 &&
+		     strcmp(p->str, "earlycon") == 0)
+		) {
 			if (p->setup_func(val) != 0)
 				printk(KERN_WARNING
 				       "Malformed early option '%s'\n", param);
diff --git a/kernel/printk.c b/kernel/printk.c
index 0bbdeac..7b96cae 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -726,6 +726,25 @@ int __init add_preferred_console(char *name, int idx, char *options)
 	return 0;
 }
 
+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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+		if (strcmp(console_cmdline[i].name, name) == 0 &&
+			  console_cmdline[i].index == idx) {
+				c = &console_cmdline[i];
+				memcpy(c->name, name_new, sizeof(c->name));
+				c->name[sizeof(c->name) - 1] = 0;
+				c->options = options;
+				c->index = idx_new;
+				return i;
+		}
+	/* not found */
+	return -1;
+}
+
 #ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
 /**
  * suspend_console - suspend the console subsystem
@@ -942,6 +961,9 @@ void register_console(struct console *console)
 	if (preferred_console < 0 || bootconsole || !console_drivers)
 		preferred_console = selected_console;
 
+	if (console->early_setup)
+		console->early_setup();
+
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30  1:43 [PATCH 4/5] serial: convert early_uart to earlycon for 8250 Yinghai Lu
@ 2007-05-30 18:57 ` Andrew Morton
  2007-05-30 19:58   ` Yinghai Lu
  2007-05-31  3:13 ` Andrew Morton
  1 sibling, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-30 18:57 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List, Gerd Hoffmann, David Gibson

On Tue, 29 May 2007 18:43:59 -0700
Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:

> [PATCH 4/5] serial: convert early_uart to earlycon for 8250
> 
> Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
> include/asm-x86_64/serial.h. the serial8250_ports need to be probed late
> in serial initializing stage. the console_init=>serial8250_console_init=>
> register_console=>serial8250_console_setup will return -ENDEV, and console
> ttyS0 can not be enabled at that time.
> need to wait till uart_add_one_port in drivers/serial/serial_core.c to call
> register_console to get console ttyS0. that is too late.
> 
> Make early_uart to use early_param, so uart console can be used earlier.
> Make it to be bootconsole with CON_BOOT flag, so can use console handover
> feature. and it will switch to corresponding normal serial console
> automatically.
> 
> new command line will be:
> 	console=uart8250,io,0x3f8,9600n8
> 	console=uart8250,mmio,0xff5e0000,115200n8
> or
> 	earlycon=uart8250,io,0x3f8,9600n8
> 	earlycon=uart8250,mmio,0xff5e0000,115200n8
> 
> it will print in very early stage:
> 	Early serial console at I/O port 0x3f8 (options '9600n8')
> 	console [uart0] enabled
> later for console it will print:
> 	console handover: boot [uart0] -> real [ttyS0]
> 
> 
>  Documentation/kernel-parameters.txt |   11 +++
>  arch/ia64/kernel/setup.c            |    4 -
>  drivers/serial/8250.c               |   28 ++-------
>  drivers/serial/8250_early.c         |  104 ++++++++++++++----------------------
>  drivers/serial/Kconfig              |   10 +++
>  include/asm-i386/fixmap.h           |    2 
>  include/asm-i386/io.h               |   13 ++++
>  include/asm-ia64/io.h               |    4 +
>  include/asm-x86_64/fixmap.h         |    4 +
>  include/asm-x86_64/io.h             |   13 ++++
>  include/linux/console.h             |    2 
>  include/linux/serial.h              |    6 --
>  include/linux/serial_8250.h         |    3 +
>  init/main.c                         |    5 +
>  kernel/printk.c                     |   22 +++++++
>  15 files changed, 133 insertions(+), 98 deletions(-)

This is a lot of tricky stuff in areas which I'm not very familar with. 
Need help, am not getting it.

> @@ -143,12 +140,7 @@ static int __init parse_options(struct early_uart_device *device, char *options)
>  	if (!strncmp(options, "mmio,", 5)) {
>  		port->iotype = UPIO_MEM;
>  		port->mapbase = simple_strtoul(options + 5, &options, 0);
> -		port->membase = ioremap(port->mapbase, mapsize);
> -		if (!port->membase) {
> -			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
> -				__FUNCTION__, port->mapbase);
> -			return -ENOMEM;
> -		}
> +		port->membase = fix_ioremap(FIX_EARLYCON_MEM_BASE, port->mapbase);

A number of useful-looking warnigns such as the above got removed.  How come?

>  		mmio = 1;
>  	} else if (!strncmp(options, "io,", 3)) {
>  		port->iotype = UPIO_PORT;
> @@ -175,9 +167,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
>  	return 0;
>  }
>  
> -static int __init early_uart_setup(struct console *console, char *options)
> +static struct console early_serial8250_console __initdata = {
> +	.name	= "uart",
> +	.write	= early_serial8250_write,
> +	.flags	= CON_PRINTBUFFER,

Should this have CON_BOOT set as well?

See
ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.21-rc7/2.6.21-rc7-mm2/broken-out/fixes-and-cleanups-for-earlyprintk-aka-boot-console.patch,
which is now in mainline.

> +	.index	= -1,
> +};
> +
> +static int __init early_serial8250_setup(char *options)
>  {
> -	struct early_uart_device *device = &early_device;
> +	struct early_serial8250_device *device = &early_device;
>  	int err;
>  
>  	if (device->port.membase || device->port.iobase)
> @@ -190,61 +189,40 @@ static int __init early_uart_setup(struct console *console, char *options)
>  	return 0;
>  }
>  
> -static struct console early_uart_console __initdata = {
> -	.name	= "uart",
> -	.write	= early_uart_write,
> -	.setup	= early_uart_setup,
> -	.flags	= CON_PRINTBUFFER,
> -	.index	= -1,
> -};

hm, that didn't have CON_BOOT.

> +static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)

I don't suppose it'd help much if I were to complain about the coding style
(no space after the * or after the function name, please).

> +{
> +	void __iomem * vaddr;
> +	set_fixmap_nocache(idx, phys & PAGE_MASK);
> +	vaddr = (void __iomem *)__fix_to_virt(idx);
> +	vaddr += phys & ~PAGE_MASK;
> +
> +	return vaddr;
> +}

Probably this was a bit too large for inlining.

>  /* Use early IO mappings for DMI because it's initialized early */
>  #define dmi_ioremap bt_ioremap
>  #define dmi_iounmap bt_iounmap
> diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
> index eb17a86..e29eaf8 100644
> --- a/include/asm-ia64/io.h
> +++ b/include/asm-ia64/io.h
> @@ -423,6 +423,10 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size);
>  extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
>  extern void iounmap (volatile void __iomem *addr);
>  
> +/* for console=uart8250,mmio,0xffe5000,9600n8 */
> +#define FIX_EARLYCON_MEM_BASE 1
> +#define fix_ioremap(idx, phys) ioremap(phys, 64)
> +
>  /* Use normal IO mappings for DMI */
>  #define dmi_ioremap ioremap
>  #define dmi_iounmap(x,l) iounmap(x)

So we touch ia64 as well?

>  
> +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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
> +		if (strcmp(console_cmdline[i].name, name) == 0 &&
> +			  console_cmdline[i].index == idx) {
> +				c = &console_cmdline[i];
> +				memcpy(c->name, name_new, sizeof(c->name));
> +				c->name[sizeof(c->name) - 1] = 0;
> +				c->options = options;
> +				c->index = idx_new;
> +				return i;
> +		}
> +	/* not found */
> +	return -1;
> +}

Shouldn't this be __init?

serial8250_find_port_for_earlycon() had its __init removed.  Why?


This patch conflicts with David's
serial-use-resource_size_t-for-port-io-addresses.patch in minor ways, but
there may be functional conflicts as well.  David's patch seems to be a bit
stuck, so I'll drop it and I'll merge these instead.  But I don't know what
I'm doing.

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30 18:57 ` Andrew Morton
@ 2007-05-30 19:58   ` Yinghai Lu
  2007-05-30 20:18     ` Andrew Morton
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-30 19:58 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List, Gerd Hoffmann, David Gibson

Andrew Morton wrote:
> On Tue, 29 May 2007 18:43:59 -0700
> Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> 
>> [PATCH 4/5] serial: convert early_uart to earlycon for 8250
>>
>> Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
>> include/asm-x86_64/serial.h. the serial8250_ports need to be probed late
>> in serial initializing stage. the console_init=>serial8250_console_init=>
>> register_console=>serial8250_console_setup will return -ENDEV, and console
>> ttyS0 can not be enabled at that time.
>> need to wait till uart_add_one_port in drivers/serial/serial_core.c to call
>> register_console to get console ttyS0. that is too late.
>>
>> Make early_uart to use early_param, so uart console can be used earlier.
>> Make it to be bootconsole with CON_BOOT flag, so can use console handover
>> feature. and it will switch to corresponding normal serial console
>> automatically.
>>
>> new command line will be:
>> 	console=uart8250,io,0x3f8,9600n8
>> 	console=uart8250,mmio,0xff5e0000,115200n8
>> or
>> 	earlycon=uart8250,io,0x3f8,9600n8
>> 	earlycon=uart8250,mmio,0xff5e0000,115200n8
>>
>> it will print in very early stage:
>> 	Early serial console at I/O port 0x3f8 (options '9600n8')
>> 	console [uart0] enabled
>> later for console it will print:
>> 	console handover: boot [uart0] -> real [ttyS0]
>>
>>
>>  Documentation/kernel-parameters.txt |   11 +++
>>  arch/ia64/kernel/setup.c            |    4 -
>>  drivers/serial/8250.c               |   28 ++-------
>>  drivers/serial/8250_early.c         |  104 ++++++++++++++----------------------
>>  drivers/serial/Kconfig              |   10 +++
>>  include/asm-i386/fixmap.h           |    2 
>>  include/asm-i386/io.h               |   13 ++++
>>  include/asm-ia64/io.h               |    4 +
>>  include/asm-x86_64/fixmap.h         |    4 +
>>  include/asm-x86_64/io.h             |   13 ++++
>>  include/linux/console.h             |    2 
>>  include/linux/serial.h              |    6 --
>>  include/linux/serial_8250.h         |    3 +
>>  init/main.c                         |    5 +
>>  kernel/printk.c                     |   22 +++++++
>>  15 files changed, 133 insertions(+), 98 deletions(-)
> 
> This is a lot of tricky stuff in areas which I'm not very familar with. 
> Need help, am not getting it.
> 
>> @@ -143,12 +140,7 @@ static int __init parse_options(struct early_uart_device *device, char *options)
>>  	if (!strncmp(options, "mmio,", 5)) {
>>  		port->iotype = UPIO_MEM;
>>  		port->mapbase = simple_strtoul(options + 5, &options, 0);
>> -		port->membase = ioremap(port->mapbase, mapsize);
>> -		if (!port->membase) {
>> -			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
>> -				__FUNCTION__, port->mapbase);
>> -			return -ENOMEM;
>> -		}
>> +		port->membase = fix_ioremap(FIX_EARLYCON_MEM_BASE, port->mapbase);
> 
> A number of useful-looking warnigns such as the above got removed.  How come?
earycon, when you can not get fix_ioremap work, you can not get anything from boot.
> 
>>  		mmio = 1;
>>  	} else if (!strncmp(options, "io,", 3)) {
>>  		port->iotype = UPIO_PORT;
>> @@ -175,9 +167,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
>>  	return 0;
>>  }
>>  
>> -static int __init early_uart_setup(struct console *console, char *options)
>> +static struct console early_serial8250_console __initdata = {
>> +	.name	= "uart",
>> +	.write	= early_serial8250_write,
>> +	.flags	= CON_PRINTBUFFER,
> 
> Should this have CON_BOOT set as well?
> 
> See
> ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.21-rc7/2.6.21-rc7-mm2/broken-out/fixes-and-cleanups-for-earlyprintk-aka-boot-console.patch,
> which is now in mainline.
> 

I put that into setup_early_serial8250_console.

-int __init early_serial_console_init(char *cmdline)
+static int __init setup_early_serial8250_console(char *cmdline)
  {
         char *options;
         int err;

-       options = strstr(cmdline, "console=uart,");
+       options = strstr(cmdline, "uart8250,");
         if (!options)
-               return -ENODEV;
+               return 0;

         options = strchr(cmdline, ',') + 1;
-       if ((err = early_uart_setup(NULL, options)) < 0)
+       if ((err = early_serial8250_setup(options)) < 0)
                 return err;
-       return early_uart_console_init();
+
+       early_serial8250_console.flags |= CON_BOOT;
+       register_console(&early_serial8250_console);
+
+       return 0;
  }

we may use
 >> +	.flags	= CON_PRINTBUFFER | CAN_BOOT;

instead that line.


>> +	.index	= -1,
>> +};
>> +
>> +static int __init early_serial8250_setup(char *options)
>>  {
>> -	struct early_uart_device *device = &early_device;
>> +	struct early_serial8250_device *device = &early_device;
>>  	int err;
>>  
>>  	if (device->port.membase || device->port.iobase)
>> @@ -190,61 +189,40 @@ static int __init early_uart_setup(struct console *console, char *options)
>>  	return 0;
>>  }
>>  
>> -static struct console early_uart_console __initdata = {
>> -	.name	= "uart",
>> -	.write	= early_uart_write,
>> -	.setup	= early_uart_setup,
>> -	.flags	= CON_PRINTBUFFER,
>> -	.index	= -1,
>> -};
> 
> hm, that didn't have CON_BOOT.
> 
>> +static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
> 
> I don't suppose it'd help much if I were to complain about the coding style
> (no space after the * or after the function name, please).
> 
>> +{
>> +	void __iomem * vaddr;
>> +	set_fixmap_nocache(idx, phys & PAGE_MASK);
>> +	vaddr = (void __iomem *)__fix_to_virt(idx);
>> +	vaddr += phys & ~PAGE_MASK;
>> +
>> +	return vaddr;
>> +}
> 
> Probably this was a bit too large for inlining.

current only one calling, later will use that for usb debug cable.

> 
>>  /* Use early IO mappings for DMI because it's initialized early */
>>  #define dmi_ioremap bt_ioremap
>>  #define dmi_iounmap bt_iounmap
>> diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
>> index eb17a86..e29eaf8 100644
>> --- a/include/asm-ia64/io.h
>> +++ b/include/asm-ia64/io.h
>> @@ -423,6 +423,10 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size);
>>  extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
>>  extern void iounmap (volatile void __iomem *addr);
>>  
>> +/* for console=uart8250,mmio,0xffe5000,9600n8 */
>> +#define FIX_EARLYCON_MEM_BASE 1
>> +#define fix_ioremap(idx, phys) ioremap(phys, 64)
>> +
>>  /* Use normal IO mappings for DMI */
>>  #define dmi_ioremap ioremap
>>  #define dmi_iounmap(x,l) iounmap(x)
> 
> So we touch ia64 as well?
> 
>>  
>> +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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
>> +		if (strcmp(console_cmdline[i].name, name) == 0 &&
>> +			  console_cmdline[i].index == idx) {
>> +				c = &console_cmdline[i];
>> +				memcpy(c->name, name_new, sizeof(c->name));
>> +				c->name[sizeof(c->name) - 1] = 0;
>> +				c->options = options;
>> +				c->index = idx_new;
>> +				return i;
>> +		}
>> +	/* not found */
>> +	return -1;
>> +}
> 
> Shouldn't this be __init?
> 
> serial8250_find_port_for_earlycon() had its __init removed.  Why?
with __init, the compiler will cry about .init.text and .text missection.

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30 19:58   ` Yinghai Lu
@ 2007-05-30 20:18     ` Andrew Morton
  2007-05-30 20:58       ` Yinghai Lu
  0 siblings, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-30 20:18 UTC (permalink / raw)
  To: Yinghai.Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List, Gerd Hoffmann, David Gibson

On Wed, 30 May 2007 12:58:11 -0700
Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:

> >> +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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
> >> +		if (strcmp(console_cmdline[i].name, name) == 0 &&
> >> +			  console_cmdline[i].index == idx) {
> >> +				c = &console_cmdline[i];
> >> +				memcpy(c->name, name_new, sizeof(c->name));
> >> +				c->name[sizeof(c->name) - 1] = 0;
> >> +				c->options = options;
> >> +				c->index = idx_new;
> >> +				return i;
> >> +		}
> >> +	/* not found */
> >> +	return -1;
> >> +}
> > 
> > Shouldn't this be __init?
> > 
> > serial8250_find_port_for_earlycon() had its __init removed.  Why?
> with __init, the compiler will cry about .init.text and .text missection.

But was this the correct fix for that?  afaict the only caller of
this function is __init anyway.

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30 20:18     ` Andrew Morton
@ 2007-05-30 20:58       ` Yinghai Lu
  2007-05-30 21:48         ` Andrew Morton
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-30 20:58 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List, Gerd Hoffmann, David Gibson

On Wednesday 30 May 2007 13:18, Andrew Morton wrote:
> On Wed, 30 May 2007 12:58:11 -0700
> Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> 
> > >> +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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
> > >> +		if (strcmp(console_cmdline[i].name, name) == 0 &&
> > >> +			  console_cmdline[i].index == idx) {
> > >> +				c = &console_cmdline[i];
> > >> +				memcpy(c->name, name_new, sizeof(c->name));
> > >> +				c->name[sizeof(c->name) - 1] = 0;
> > >> +				c->options = options;
> > >> +				c->index = idx_new;
> > >> +				return i;
> > >> +		}
> > >> +	/* not found */
> > >> +	return -1;
> > >> +}
> > > 
> > > Shouldn't this be __init?
> > > 
> > > serial8250_find_port_for_earlycon() had its __init removed.  Why?
> > with __init, the compiler will cry about .init.text and .text missection.
> 
> But was this the correct fix for that?  afaict the only caller of
> this function is __init anyway.
> 
You are right.
serial8250_find_port_for_earlycon and
update_console_cmdline in kernel/printk.c
could be __init

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30 20:58       ` Yinghai Lu
@ 2007-05-30 21:48         ` Andrew Morton
  0 siblings, 0 replies; 20+ messages in thread
From: Andrew Morton @ 2007-05-30 21:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List, Gerd Hoffmann, David Gibson

On Wed, 30 May 2007 13:58:52 -0700
Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:

> On Wednesday 30 May 2007 13:18, Andrew Morton wrote:
> > On Wed, 30 May 2007 12:58:11 -0700
> > Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> > 
> > > >> +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; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
> > > >> +		if (strcmp(console_cmdline[i].name, name) == 0 &&
> > > >> +			  console_cmdline[i].index == idx) {
> > > >> +				c = &console_cmdline[i];
> > > >> +				memcpy(c->name, name_new, sizeof(c->name));
> > > >> +				c->name[sizeof(c->name) - 1] = 0;
> > > >> +				c->options = options;
> > > >> +				c->index = idx_new;
> > > >> +				return i;
> > > >> +		}
> > > >> +	/* not found */
> > > >> +	return -1;
> > > >> +}
> > > > 
> > > > Shouldn't this be __init?
> > > > 
> > > > serial8250_find_port_for_earlycon() had its __init removed.  Why?
> > > with __init, the compiler will cry about .init.text and .text missection.
> > 
> > But was this the correct fix for that?  afaict the only caller of
> > this function is __init anyway.
> > 
> You are right.
> serial8250_find_port_for_earlycon and
> update_console_cmdline in kernel/printk.c
> could be __init

OK, please send a fixup sometime.

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-30  1:43 [PATCH 4/5] serial: convert early_uart to earlycon for 8250 Yinghai Lu
  2007-05-30 18:57 ` Andrew Morton
@ 2007-05-31  3:13 ` Andrew Morton
  2007-05-31  4:34   ` Yinghai Lu
  1 sibling, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-31  3:13 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On Tue, 29 May 2007 18:43:59 -0700 Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:

> [PATCH 4/5] serial: convert early_uart to earlycon for 8250

drivers/serial/8250_early.c: In function 'parse_options':
drivers/serial/8250_early.c:143: error: 'FIX_EARLYCON_MEM_BASE' undeclared (first use in this function)
drivers/serial/8250_early.c:143: error: (Each undeclared identifier is reported only once

That was with http://userweb.kernel.org/~akpm/config-sony.txt, but this is
going to break a whole pile of architectures (alpha, powerpc, others).

I think I'll give up on it now.

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  3:13 ` Andrew Morton
@ 2007-05-31  4:34   ` Yinghai Lu
  2007-05-31  4:36     ` Yinghai Lu
  2007-05-31  4:39     ` Andrew Morton
  0 siblings, 2 replies; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31  4:34 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> On Tue, 29 May 2007 18:43:59 -0700 Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
>
> > [PATCH 4/5] serial: convert early_uart to earlycon for 8250
>
> drivers/serial/8250_early.c: In function 'parse_options':
> drivers/serial/8250_early.c:143: error: 'FIX_EARLYCON_MEM_BASE' undeclared (first use in this function)
> drivers/serial/8250_early.c:143: error: (Each undeclared identifier is reported only once
>
> That was with http://userweb.kernel.org/~akpm/config-sony.txt, but this is
> going to break a whole pile of architectures (alpha, powerpc, others).

alpha, powerpc, others may need sth like ia64, if they do not support fixmap.

diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index eb17a86..e29eaf8 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -423,6 +423,10 @@ extern void __iomem * ioremap(unsigned long
offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned
long size);
 extern void iounmap (volatile void __iomem *addr);

+/* for console=uart8250,mmio,0xffe5000,9600n8 */
+#define FIX_EARLYCON_MEM_BASE 1
+#define fix_ioremap(idx, phys) ioremap(phys, 64)
+
 /* Use normal IO mappings for DMI */
 #define dmi_ioremap ioremap
 #define dmi_iounmap(x,l) iounmap(x)


$ find . -name "fixmap.h"
./asm-sh/fixmap.h
./asm-um/fixmap.h
./asm-parisc/fixmap.h
./asm-x86_64/fixmap.h
./asm-sparc/fixmap.h
./asm-i386/fixmap.h
./asm-mips/fixmap.h

they will need
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a..e2d66de 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned
long size);
 extern void iounmap(volatile void __iomem *addr);

+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+
+static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
+{
+       void __iomem * vaddr;
+       set_fixmap_nocache(idx, phys & PAGE_MASK);
+       vaddr = (void __iomem *)__fix_to_virt(idx);
+       vaddr += phys & ~PAGE_MASK;
+
+       return vaddr;
+}
+
 /*
 * ISA I/O bus memory addresses are 1:1 with the physical address.
 */

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:34   ` Yinghai Lu
@ 2007-05-31  4:36     ` Yinghai Lu
  2007-05-31  4:48       ` Andrew Morton
  2007-05-31  4:39     ` Andrew Morton
  1 sibling, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31  4:36 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On 5/30/07, Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> > On Tue, 29 May 2007 18:43:59 -0700 Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> >
> > > [PATCH 4/5] serial: convert early_uart to earlycon for 8250
> >
> > drivers/serial/8250_early.c: In function 'parse_options':
> > drivers/serial/8250_early.c:143: error: 'FIX_EARLYCON_MEM_BASE' undeclared (first use in this function)
> > drivers/serial/8250_early.c:143: error: (Each undeclared identifier is reported only once
> >
> > That was with http://userweb.kernel.org/~akpm/config-sony.txt, but this is
> > going to break a whole pile of architectures (alpha, powerpc, others).
>
> alpha, powerpc, others may need sth like ia64, if they do not support fixmap.
>
>

or create dummy fixmap.h that doesn't support fixmap.

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:34   ` Yinghai Lu
  2007-05-31  4:36     ` Yinghai Lu
@ 2007-05-31  4:39     ` Andrew Morton
  2007-05-31  4:42       ` Yinghai Lu
  1 sibling, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-31  4:39 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On Wed, 30 May 2007 21:34:35 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:

> they will need
> diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
> index de2cd9a..e2d66de 100644
> --- a/include/asm-x86_64/io.h
> +++ b/include/asm-x86_64/io.h
> @@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);
>  extern void __iomem * ioremap_nocache (unsigned long offset, unsigned
> long size);
>  extern void iounmap(volatile void __iomem *addr);
> 
> +#include <asm/pgtable.h>
> +#include <asm/fixmap.h>
> +
> +static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
> +{
> +       void __iomem * vaddr;
> +       set_fixmap_nocache(idx, phys & PAGE_MASK);
> +       vaddr = (void __iomem *)__fix_to_virt(idx);
> +       vaddr += phys & ~PAGE_MASK;
> +
> +       return vaddr;
> +}
> +

I hope not - I just removed that inlined function.  It's too large and the
inclusion of pgtable.h in io.h causes all sorts of problems.

This function should go into arch/.../mm/ioremap.c

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:39     ` Andrew Morton
@ 2007-05-31  4:42       ` Yinghai Lu
  2007-05-31  4:51         ` Andrew Morton
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31  4:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> On Wed, 30 May 2007 21:34:35 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:
>
> > they will need
> > diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
> > index de2cd9a..e2d66de 100644
> > --- a/include/asm-x86_64/io.h
> > +++ b/include/asm-x86_64/io.h
> > @@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);
> >  extern void __iomem * ioremap_nocache (unsigned long offset, unsigned
> > long size);
> >  extern void iounmap(volatile void __iomem *addr);
> >
> > +#include <asm/pgtable.h>
> > +#include <asm/fixmap.h>
> > +
> > +static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
> > +{
> > +       void __iomem * vaddr;
> > +       set_fixmap_nocache(idx, phys & PAGE_MASK);
> > +       vaddr = (void __iomem *)__fix_to_virt(idx);
> > +       vaddr += phys & ~PAGE_MASK;
> > +
> > +       return vaddr;
> > +}
> > +
>
> I hope not - I just removed that inlined function.  It's too large and the
> inclusion of pgtable.h in io.h causes all sorts of problems.
>
> This function should go into arch/.../mm/ioremap.c
>
agree, but need to keep

#include <asm/fixmap.h>

and will create dummy fixmap.h for arch that doesn't support fixmap

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:36     ` Yinghai Lu
@ 2007-05-31  4:48       ` Andrew Morton
  2007-05-31 15:17         ` Bjorn Helgaas
  0 siblings, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-31  4:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On Wed, 30 May 2007 21:36:41 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:

> On 5/30/07, Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> > On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> > > On Tue, 29 May 2007 18:43:59 -0700 Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> > >
> > > > [PATCH 4/5] serial: convert early_uart to earlycon for 8250
> > >
> > > drivers/serial/8250_early.c: In function 'parse_options':
> > > drivers/serial/8250_early.c:143: error: 'FIX_EARLYCON_MEM_BASE' undeclared (first use in this function)
> > > drivers/serial/8250_early.c:143: error: (Each undeclared identifier is reported only once
> > >
> > > That was with http://userweb.kernel.org/~akpm/config-sony.txt, but this is
> > > going to break a whole pile of architectures (alpha, powerpc, others).
> >
> > alpha, powerpc, others may need sth like ia64, if they do not support fixmap.
> >
> >
> 
> or create dummy fixmap.h that doesn't support fixmap.
> 

You could require that the architecture implement some specific function
for mapping the early-uart.  Say,

void __iomem *map_early_uart(unsigned long phys_addr, unsigned long len);
void unmap_early_uart(void * __iomem *addr);

then, in drivers/serial/8250_early.c, do


void __iomem * __attribute__((weak))
map_early_uart(unsigned long phys_addr, unsigned long len)
{
	return ioremap(phys_addr, len);
}

void __attribute__((weak)) unmap_early_uart(void * __iomem *addr)
{
	iounmap(addr);
}

and in arch/i386/mm/ioremap.c



#ifdef CONFIG_something

void __iomem *map_early_uart(unsigned long phys_addr, unsigned long len)
{
	void __iomem * vaddr;
	set_fixmap_nocache(idx, phys & PAGE_MASK);
	vaddr = (void __iomem *)__fix_to_virt(idx);
	vaddr += phys & ~PAGE_MASK;

	return vaddr;
}

void unmap_early_uart(void * __iomem *addr)
{
	/* nothing to do */
}

#endif

or such.


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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:42       ` Yinghai Lu
@ 2007-05-31  4:51         ` Andrew Morton
  0 siblings, 0 replies; 20+ messages in thread
From: Andrew Morton @ 2007-05-31  4:51 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andi Kleen, Russell King, Bjorn Helgaas,
	Linux Kernel Mailing List

On Wed, 30 May 2007 21:42:15 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:

> On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> > On Wed, 30 May 2007 21:34:35 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:
> >
> > > they will need
> > > diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
> > > index de2cd9a..e2d66de 100644
> > > --- a/include/asm-x86_64/io.h
> > > +++ b/include/asm-x86_64/io.h
> > > @@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);
> > >  extern void __iomem * ioremap_nocache (unsigned long offset, unsigned
> > > long size);
> > >  extern void iounmap(volatile void __iomem *addr);
> > >
> > > +#include <asm/pgtable.h>
> > > +#include <asm/fixmap.h>
> > > +
> > > +static inline void __iomem * fix_ioremap (unsigned idx, unsigned long phys)
> > > +{
> > > +       void __iomem * vaddr;
> > > +       set_fixmap_nocache(idx, phys & PAGE_MASK);
> > > +       vaddr = (void __iomem *)__fix_to_virt(idx);
> > > +       vaddr += phys & ~PAGE_MASK;
> > > +
> > > +       return vaddr;
> > > +}
> > > +
> >
> > I hope not - I just removed that inlined function.  It's too large and the
> > inclusion of pgtable.h in io.h causes all sorts of problems.
> >
> > This function should go into arch/.../mm/ioremap.c
> >
> agree, but need to keep
> 
> #include <asm/fixmap.h>

No, there's no need for that and it is undesirable.

> and will create dummy fixmap.h for arch that doesn't support fixmap

So's that.  If we avoid the inlined function we will avoid adding more
include requirements.


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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31  4:48       ` Andrew Morton
@ 2007-05-31 15:17         ` Bjorn Helgaas
  2007-05-31 16:32           ` Yinghai Lu
  0 siblings, 1 reply; 20+ messages in thread
From: Bjorn Helgaas @ 2007-05-31 15:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Yinghai Lu, Andi Kleen, Russell King, Linux Kernel Mailing List

On Wednesday 30 May 2007 10:48:59 pm Andrew Morton wrote:
> On Wed, 30 May 2007 21:36:41 -0700 "Yinghai Lu" <yhlu.kernel@gmail.com> wrote:
> 
> > On 5/30/07, Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> > > On 5/30/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> > > > On Tue, 29 May 2007 18:43:59 -0700 Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> > > >
> > > > > [PATCH 4/5] serial: convert early_uart to earlycon for 8250
> > > >
> > > > drivers/serial/8250_early.c: In function 'parse_options':
> > > > drivers/serial/8250_early.c:143: error: 'FIX_EARLYCON_MEM_BASE' undeclared (first use in this function)
> > > > drivers/serial/8250_early.c:143: error: (Each undeclared identifier is reported only once
> > > >
> > > > That was with http://userweb.kernel.org/~akpm/config-sony.txt, but this is
> > > > going to break a whole pile of architectures (alpha, powerpc, others).
> > >
> > > alpha, powerpc, others may need sth like ia64, if they do not support fixmap.
> > 
> > or create dummy fixmap.h that doesn't support fixmap.
> 
> You could require that the architecture implement some specific function
> for mapping the early-uart.

We could, but we already have bt_ioremap, dmi_ioremap, and early_ioremap.
Do we really want to proliferate more flavors of "early ioremap"?  I'd
rather consolidate the ones we already have.

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31 15:17         ` Bjorn Helgaas
@ 2007-05-31 16:32           ` Yinghai Lu
  2007-05-31 16:45             ` Bjorn Helgaas
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31 16:32 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Andrew Morton, Andi Kleen, Russell King,
	Linux Kernel Mailing List

On 5/31/07, Bjorn Helgaas <bjorn.helgaas@hp.com> wrote:
> On Wednesday 30 May 2007 10:48:59 pm Andrew Morton wrote:
> > You could require that the architecture implement some specific function
> > for mapping the early-uart.
>
> We could, but we already have bt_ioremap, dmi_ioremap, and early_ioremap.
> Do we really want to proliferate more flavors of "early ioremap"?  I'd
> rather consolidate the ones we already have.
>
not really.

dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
bt_ioremap * -r
asm-i386/dmi.h:#define dmi_ioremap bt_ioremap
asm-i386/io.h: * bt_ioremap() and bt_iounmap() are for temporary early boot-time
asm-i386/io.h:extern void *bt_ioremap(unsigned long offset, unsigned long size);
asm-i386/io.h:#define dmi_ioremap bt_ioremap

dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
early_ioremap * -r
asm-x86_64/dmi.h:#define dmi_ioremap early_ioremap
asm-x86_64/io.h:extern void *early_ioremap(unsigned long addr,
unsigned long size);

dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
dmi_ioremap * -r
asm-i386/dmi.h:#define dmi_ioremap bt_ioremap
asm-i386/io.h:#define dmi_ioremap bt_ioremap
asm-ia64/io.h:#define dmi_ioremap ioremap
asm-x86_64/dmi.h:extern void *dmi_ioremap(unsigned long addr, unsigned
long size);
asm-x86_64/dmi.h:#define dmi_ioremap early_ioremap

YH

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31 16:32           ` Yinghai Lu
@ 2007-05-31 16:45             ` Bjorn Helgaas
  2007-05-31 18:49               ` Yinghai Lu
  0 siblings, 1 reply; 20+ messages in thread
From: Bjorn Helgaas @ 2007-05-31 16:45 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Andrew Morton, Andi Kleen, Russell King,
	Linux Kernel Mailing List

On Thursday 31 May 2007 10:32:42 am Yinghai Lu wrote:
> On 5/31/07, Bjorn Helgaas <bjorn.helgaas@hp.com> wrote:
> > On Wednesday 30 May 2007 10:48:59 pm Andrew Morton wrote:
> > > You could require that the architecture implement some specific function
> > > for mapping the early-uart.
> >
> > We could, but we already have bt_ioremap, dmi_ioremap, and early_ioremap.
> > Do we really want to proliferate more flavors of "early ioremap"?  I'd
> > rather consolidate the ones we already have.
> >
> not really.

I'm sorry, I don't understand the point you're making.

Andrew's proposal was that we could add early_uart_ioremap to the list of
bt_ioremap and dmi_ioremap.

I'm suggesting that maybe we should make bt_ioremap smart enough that
we could use it for early uart mapping.  And maybe we could get rid
of dmi_ioremap, and make DMI use bt_ioremap as well (this would require
some shims for x86_64 and ia64).

> dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
> bt_ioremap * -r
> asm-i386/dmi.h:#define dmi_ioremap bt_ioremap
> asm-i386/io.h: * bt_ioremap() and bt_iounmap() are for temporary early boot-time
> asm-i386/io.h:extern void *bt_ioremap(unsigned long offset, unsigned long size);
> asm-i386/io.h:#define dmi_ioremap bt_ioremap
> 
> dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
> early_ioremap * -r
> asm-x86_64/dmi.h:#define dmi_ioremap early_ioremap
> asm-x86_64/io.h:extern void *early_ioremap(unsigned long addr,
> unsigned long size);
> 
> dhcp-umpk12-63-201:/home/yhlu/xx/xx/kernel/linux-2.6/include # grep
> dmi_ioremap * -r
> asm-i386/dmi.h:#define dmi_ioremap bt_ioremap
> asm-i386/io.h:#define dmi_ioremap bt_ioremap
> asm-ia64/io.h:#define dmi_ioremap ioremap
> asm-x86_64/dmi.h:extern void *dmi_ioremap(unsigned long addr, unsigned
> long size);
> asm-x86_64/dmi.h:#define dmi_ioremap early_ioremap

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31 16:45             ` Bjorn Helgaas
@ 2007-05-31 18:49               ` Yinghai Lu
  0 siblings, 0 replies; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31 18:49 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Andrew Morton, Andi Kleen, Russell King,
	Linux Kernel Mailing List

On 5/31/07, Bjorn Helgaas <bjorn.helgaas@hp.com> wrote:
> > not really.
>
> I'm sorry, I don't understand the point you're making.
>
> Andrew's proposal was that we could add early_uart_ioremap to the list of
> bt_ioremap and dmi_ioremap.
>

for i386, bt_ioremap is using fixmap, and it is temporary boot-time
mappings, used before ioremap() is functional.
but we need one as permanent fixed address.

for x86_64, early_ioremap. I'd like to make to static, because
dmi_ioremap could use ioremap instead.

Fix address could make the earlycon can be used more earlier.

YH

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

* [PATCH 4/5] serial: convert early_uart to earlycon for 8250
@ 2007-05-31 21:01 Yinghai Lu
  2007-05-31 23:54 ` Andrew Morton
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2007-05-31 21:01 UTC (permalink / raw)
  To: Andrew Morton, Andi Kleen; +Cc: Linux Kernel Mailing List

Andrew,

Please don't drop others if there is problem with this one.

YH

[PATCH 4/5] serial: convert early_uart to earlycon for 8250

Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
include/asm-x86_64/serial.h. the serial8250_ports need to be probed late
in serial initializing stage. the console_init=>serial8250_console_init=>
register_console=>serial8250_console_setup will return -ENDEV, and console
ttyS0 can not be enabled at that time.
need to wait till uart_add_one_port in drivers/serial/serial_core.c to call
register_console to get console ttyS0. that is too late.

Make early_uart to use early_param, so uart console can be used earlier.
Make it to be bootconsole with CON_BOOT flag, so can use console handover
feature. and it will switch to corresponding normal serial console
automatically.

new command line will be:
	console=uart8250,io,0x3f8,9600n8
	console=uart8250,mmio,0xff5e0000,115200n8
or
	earlycon=uart8250,io,0x3f8,9600n8
	earlycon=uart8250,mmio,0xff5e0000,115200n8

it will print in very early stage:
	Early serial console at I/O port 0x3f8 (options '9600n8')
	console [uart0] enabled
later for console it will print:
	console handover: boot [uart0] -> real [ttyS0]

Signed-off-by: <yinghai.lu@sun.com>

 Documentation/kernel-parameters.txt |   11 +++
 arch/ia64/kernel/setup.c            |    4 -
 drivers/serial/8250.c               |   28 ++-------
 drivers/serial/8250_early.c         |  108 ++++++++++++++++--------------------
 drivers/serial/Kconfig              |   14 ++++
 include/asm-i386/fixmap.h           |    2 
 include/asm-i386/io.h               |    1 
 include/asm-x86_64/fixmap.h         |    4 +
 include/asm-x86_64/io.h             |    1 
 include/linux/console.h             |    2 
 include/linux/serial.h              |    6 --
 include/linux/serial_8250.h         |    3 +
 init/main.c                         |    5 +
 kernel/printk.c                     |   22 +++++++
 14 files changed, 118 insertions(+), 93 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ce91560..4a9e271 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -464,13 +464,20 @@ and is between 256 and 4096 characters. It is defined in the file
 			Documentation/networking/netconsole.txt for an
 			alternative.
 
-		uart,io,<addr>[,options]
-		uart,mmio,<addr>[,options]
+		uart8250,io,<addr>[,options]
+		uart8250,mmio,<addr>[,options]
 			Start an early, polled-mode console on the 8250/16550
 			UART at the specified I/O port or MMIO address,
 			switching to the matching ttyS device later.  The
 			options are the same as for ttyS, above.
 
+	earlycon=	[KNL] Output early console device and options.
+		uart8250,io,<addr>[,options]
+		uart8250,mmio,<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address.
+			The options are the same as for ttyS, above.
+
 	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
 			Format:
 			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24..dd7f95b 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@ early_console_setup (char *cmdline)
 	if (!efi_setup_pcdp_console(cmdline))
 		earlycons++;
 #endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	if (!early_serial_console_init(cmdline))
-		earlycons++;
-#endif
 
 	return (earlycons) ? 0 : -1;
 }
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab0..0b3ec38 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options)
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
+static int __init serial8250_console_early_setup(void)
+{
+	return serial8250_find_port_for_earlycon();
+}
+
 static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
 	.name		= "ttyS",
 	.write		= serial8250_console_write,
 	.device		= uart_console_device,
 	.setup		= serial8250_console_setup,
+	.early_setup	= serial8250_console_early_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.data		= &serial8250_reg,
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void)
 }
 console_initcall(serial8250_console_init);
 
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
 {
 	int line;
 	struct uart_port *port;
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p)
 	return -ENODEV;
 }
 
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
-	int line;
-
-	line = find_port(port);
-	if (line < 0)
-		return -ENODEV;
-
-	add_preferred_console("ttyS", line, options);
-	printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
-		line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
-		port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
-		    (unsigned long) port->iobase, options);
-	if (!(serial8250_console.flags & CON_ENABLED)) {
-		serial8250_console.flags &= ~CON_PRINTBUFFER;
-		register_console(&serial8250_console);
-	}
-	return line;
-}
-
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
 #define SERIAL8250_CONSOLE	NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e51119..58527c6 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
  * we locate the device directly by its MMIO or I/O port address.
  *
  * The user can specify the device directly, e.g.,
- *	console=uart,io,0x3f8,9600n8
- *	console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ *	earlycon=uart8250,io,0x3f8,9600n8
+ *	earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ *	console=uart8250,io,0x3f8,9600n8
+ *	console=uart8250,mmio,0xff5e0000,115200n8
  */
 
 #include <linux/tty.h>
@@ -32,17 +30,21 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
+#include <linux/serial_8250.h>
 #include <asm/io.h>
 #include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
 
-struct early_uart_device {
+struct early_serial8250_device {
 	struct uart_port port;
 	char options[16];		/* e.g., 115200n8 */
 	unsigned int baud;
 };
 
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
 
 static unsigned int __init serial_in(struct uart_port *port, int offset)
 {
@@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c)
 	serial_out(port, UART_TX, c);
 }
 
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
 {
 	struct uart_port *port = &early_device.port;
 	unsigned int ier;
@@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
 	return (port->uartclk / 16) / quot;
 }
 
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
 {
 	struct uart_port *port = &device->port;
 	unsigned int divisor;
@@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device)
 	serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
 {
 	struct uart_port *port = &device->port;
-	int mapsize = 64;
 	int mmio, length;
 
 	if (!options)
@@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options)
 	if (!strncmp(options, "mmio,", 5)) {
 		port->iotype = UPIO_MEM;
 		port->mapbase = simple_strtoul(options + 5, &options, 0);
-		port->membase = ioremap(port->mapbase, mapsize);
+#ifdef CONFIG_FIX_EARLYCON_MEM
+		set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
+		port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+		port->membase += port->mapbase & ~PAGE_MASK;
+#else
+		port->membase = ioremap(port->mapbase, 64);
 		if (!port->membase) {
 			printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
 				__FUNCTION__, port->mapbase);
 			return -ENOMEM;
 		}
+#endif
 		mmio = 1;
 	} else if (!strncmp(options, "io,", 3)) {
 		port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
 	return 0;
 }
 
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+	.name	= "uart",
+	.write	= early_serial8250_write,
+	.flags	= CON_PRINTBUFFER | CON_BOOT,
+	.index	= -1,
+};
+
+static int __init early_serial8250_setup(char *options)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	int err;
 
 	if (device->port.membase || device->port.iobase)
@@ -190,61 +204,39 @@ static int __init early_uart_setup(struct console *console, char *options)
 	return 0;
 }
 
-static struct console early_uart_console __initdata = {
-	.name	= "uart",
-	.write	= early_uart_write,
-	.setup	= early_uart_setup,
-	.flags	= CON_PRINTBUFFER,
-	.index	= -1,
-};
-
-static int __init early_uart_console_init(void)
-{
-	if (!early_uart_registered) {
-		register_console(&early_uart_console);
-		early_uart_registered = 1;
-	}
-	return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+static int __init setup_early_serial8250_console(char *cmdline)
 {
 	char *options;
 	int err;
 
-	options = strstr(cmdline, "console=uart,");
+	options = strstr(cmdline, "uart8250,");
 	if (!options)
-		return -ENODEV;
+		return 0;
 
 	options = strchr(cmdline, ',') + 1;
-	if ((err = early_uart_setup(NULL, options)) < 0)
+	if ((err = early_serial8250_setup(options)) < 0)
 		return err;
-	return early_uart_console_init();
+
+	register_console(&early_serial8250_console);
+
+	return 0;
 }
 
-static int __init early_uart_console_switch(void)
+int __init serial8250_find_port_for_earlycon(void)
 {
-	struct early_uart_device *device = &early_device;
+	struct early_serial8250_device *device = &early_device;
 	struct uart_port *port = &device->port;
-	int mmio, line;
+	int line;
 
-	if (!(early_uart_console.flags & CON_ENABLED))
-		return 0;
+	if (!device->port.membase && !device->port.iobase)
+		return -ENODEV;
 
-	/* Try to start the normal driver on a matching line.  */
-	mmio = (port->iotype == UPIO_MEM);
-	line = serial8250_start_console(port, device->options);
+	line = serial8250_find_port(port);
 	if (line < 0)
-		printk("No ttyS device at %s 0x%lx for console\n",
-			mmio ? "MMIO" : "I/O port",
-			mmio ? port->mapbase :
-			    (unsigned long) port->iobase);
-
-	unregister_console(&early_uart_console);
-	if (mmio)
-		iounmap(port->membase);
+		return -ENODEV;
 
-	return 0;
+	return update_console_cmdline("uart", 8250,
+				     "ttyS", line, device->options);
 }
-late_initcall(early_uart_console_switch);
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 315ea99..9cd751e 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE
 	  kernel will automatically use the first serial line, /dev/ttyS0, as
 	  system console.
 
+	  you can set that using a kernel command line option such as
+	  "console=uart8250,io,0x3f8,9600n8"
+	  "console=uart8250,mmio,0xff5e0000,115200n8".
+	  and it will switch to normal serial console when correponding port is
+	  ready.
+	  "earlycon=uart8250,io,0x3f8,9600n8"
+	  "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+	  it will not only setup early console.
+
 	  If unsure, say N.
 
+config FIX_EARLYCON_MEM
+	bool
+	depends on X86
+	default y
+
 config SERIAL_8250_GSC
 	tristate
 	depends on SERIAL_8250 && GSC
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052..249e753 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@ extern unsigned long __FIXADDR_TOP;
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VDSO,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586..7b65b5b 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -129,6 +129,7 @@ extern void iounmap(volatile void __iomem *addr);
  */
 extern void *bt_ioremap(unsigned long offset, unsigned long size);
 extern void bt_iounmap(void *addr, unsigned long size);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_ioremap bt_ioremap
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e167..2acb9b7 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@ enum fixed_addresses {
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
 	VSYSCALL_HPET,
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
 	FIX_HPET_BASE,
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 	FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 	if (idx >= __end_of_fixed_addresses)
 		__this_fixmap_does_not_exist();
 
-        return __fix_to_virt(idx);
+	return __fix_to_virt(idx);
 }
 
 #endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a..7475095 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -144,6 +144,7 @@ extern void early_iounmap(void *addr, unsigned long size);
  */
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap(volatile void __iomem *addr);
+extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
diff --git a/include/linux/console.h b/include/linux/console.h
index 62ef6e1..c44d3df 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -99,6 +99,7 @@ struct console {
 	struct tty_driver *(*device)(struct console *, int *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
+	int	(*early_setup)(void);
 	short	flags;
 	short	index;
 	int	cflag;
@@ -107,6 +108,7 @@ struct 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.h b/include/linux/serial.h
index 33fc8cb..deb7143 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@ struct serial_icounter_struct {
 #ifdef __KERNEL__
 #include <linux/compiler.h>
 
-/* Allow architectures to override entries in serial8250_ports[] at run time: */
-struct uart_port;	/* forward declaration */
-extern int early_serial_setup(struct uart_port *port);
-extern int early_serial_console_init(char *options);
-extern int serial8250_start_console(struct uart_port *port, char *options);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d8..23519fb 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,7 @@ void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
 
+extern int serial8250_find_port(struct uart_port *p);
+extern int serial8250_find_port_for_earlycon(void);
+
 #endif
diff --git a/init/main.c b/init/main.c
index eb8bdba..58dbe75 100644
--- a/init/main.c
+++ b/init/main.c
@@ -452,7 +452,10 @@ static int __init do_early_param(char *param, char *val)
 	struct obs_kernel_param *p;
 
 	for (p = __setup_start; p < __setup_end; p++) {
-		if (p->early && strcmp(param, p->str) == 0) {
+		if ((p->early && strcmp(param, p->str) == 0) ||
+		    (strcmp(param, "console") == 0 &&
+		     strcmp(p->str, "earlycon") == 0)
+		) {
 			if (p->setup_func(val) != 0)
 				printk(KERN_WARNING
 				       "Malformed early option '%s'\n", param);
diff --git a/kernel/printk.c b/kernel/printk.c
index 0bbdeac..8779626 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -726,6 +726,25 @@ int __init add_preferred_console(char *name, int idx, char *options)
 	return 0;
 }
 
+int __init update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
+{
+	struct console_cmdline *c;
+	int i;
+
+	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+		if (strcmp(console_cmdline[i].name, name) == 0 &&
+			  console_cmdline[i].index == idx) {
+				c = &console_cmdline[i];
+				memcpy(c->name, name_new, sizeof(c->name));
+				c->name[sizeof(c->name) - 1] = 0;
+				c->options = options;
+				c->index = idx_new;
+				return i;
+		}
+	/* not found */
+	return -1;
+}
+
 #ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
 /**
  * suspend_console - suspend the console subsystem
@@ -942,6 +961,9 @@ void register_console(struct console *console)
 	if (preferred_console < 0 || bootconsole || !console_drivers)
 		preferred_console = selected_console;
 
+	if (console->early_setup)
+		console->early_setup();
+
 	/*
 	 *	See if we want to use this console driver. If we
 	 *	didn't select a console we take the first one

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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31 21:01 Yinghai Lu
@ 2007-05-31 23:54 ` Andrew Morton
  2007-06-01  0:11   ` Yinghai Lu
  0 siblings, 1 reply; 20+ messages in thread
From: Andrew Morton @ 2007-05-31 23:54 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Andi Kleen, Linux Kernel Mailing List

On Thu, 31 May 2007 14:01:33 -0700
Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:

> Andrew,
> 
> Please don't drop others if there is problem with this one.
> 
> YH
> 
> [PATCH 4/5] serial: convert early_uart to earlycon for 8250
> 
> Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
> include/asm-x86_64/serial.h. the serial8250_ports need to be probed late
> in serial initializing stage. the console_init=>serial8250_console_init=>
> register_console=>serial8250_console_setup will return -ENDEV, and console
> ttyS0 can not be enabled at that time.
> need to wait till uart_add_one_port in drivers/serial/serial_core.c to call
> register_console to get console ttyS0. that is too late.
> 
> Make early_uart to use early_param, so uart console can be used earlier.
> Make it to be bootconsole with CON_BOOT flag, so can use console handover
> feature. and it will switch to corresponding normal serial console
> automatically.
> 
> new command line will be:
> 	console=uart8250,io,0x3f8,9600n8
> 	console=uart8250,mmio,0xff5e0000,115200n8
> or
> 	earlycon=uart8250,io,0x3f8,9600n8
> 	earlycon=uart8250,mmio,0xff5e0000,115200n8
> 
> it will print in very early stage:
> 	Early serial console at I/O port 0x3f8 (options '9600n8')
> 	console [uart0] enabled
> later for console it will print:
> 	console handover: boot [uart0] -> real [ttyS0]
> 
> ...
>
> --- a/drivers/serial/8250_early.c
> +++ b/drivers/serial/8250_early.c
> @@ -32,17 +30,21 @@
>  #include <linux/serial_core.h>
>  #include <linux/serial_reg.h>
>  #include <linux/serial.h>
> +#include <linux/serial_8250.h>
>  #include <asm/io.h>
>  #include <asm/serial.h>
> +#ifdef CONFIG_FIX_EARLYCON_MEM
> +#include <asm/pgtable.h>
> +#include <asm/fixmap.h>
> +#endif
>  
> ...
>
> @@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options)
>  	if (!strncmp(options, "mmio,", 5)) {
>  		port->iotype = UPIO_MEM;
>  		port->mapbase = simple_strtoul(options + 5, &options, 0);
> -		port->membase = ioremap(port->mapbase, mapsize);
> +#ifdef CONFIG_FIX_EARLYCON_MEM
> +		set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
> +		port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
> +		port->membase += port->mapbase & ~PAGE_MASK;
> +#else
> +		port->membase = ioremap(port->mapbase, 64);

ug.  OK, that'll work.  Simple and direct ;)

> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
>
> ...
>
> +config FIX_EARLYCON_MEM
> +	bool
> +	depends on X86
> +	default y
> +

It might have been nicer to do this in arch/i386/Kconfig and
arch/x86_64/Kconfig.  That way we don't end up with a great string of arch
selectors in non-arch Kconfig files (do "grep SPARC */Kconfig*")

otoh, doing that means that FIX_EARLYCON_MEM doesn't get mentioned in
drivers/serial/Kconfig and you need to go on a great hunting expedition to
find out who sets it.


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

* Re: [PATCH 4/5] serial: convert early_uart to earlycon for 8250
  2007-05-31 23:54 ` Andrew Morton
@ 2007-06-01  0:11   ` Yinghai Lu
  0 siblings, 0 replies; 20+ messages in thread
From: Yinghai Lu @ 2007-06-01  0:11 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Andi Kleen, Linux Kernel Mailing List

Andrew Morton wrote:
> On Thu, 31 May 2007 14:01:33 -0700
> Yinghai Lu <Yinghai.Lu@Sun.COM> wrote:
> 
>> Andrew,
>>
>> Please don't drop others if there is problem with this one.
>>
>> YH
>>
>> [PATCH 4/5] serial: convert early_uart to earlycon for 8250
>>
>> +config FIX_EARLYCON_MEM
>> +	bool
>> +	depends on X86
>> +	default y
>> +
> 
> It might have been nicer to do this in arch/i386/Kconfig and
> arch/x86_64/Kconfig.  That way we don't end up with a great string of arch
> selectors in non-arch Kconfig files (do "grep SPARC */Kconfig*")
> 
> otoh, doing that means that FIX_EARLYCON_MEM doesn't get mentioned in
> drivers/serial/Kconfig and you need to go on a great hunting expedition to
> find out who sets it.
> 

we could extend that to others arch that is support fixmap like
./asm-i386/fixmap.h
./asm-mips/fixmap.h
./asm-parisc/fixmap.h
./asm-sh/fixmap.h
./asm-sparc/fixmap.h
./asm-um/fixmap.h
./asm-x86_64/fixmap.h

so it will be
 >> +config FIX_EARLYCON_MEM
 >> +	bool
 >> +	depends on X86 || MIPS || PARISC || SH || SPARC || UM
 >> +	default y
 >> +

You you can provide another config like

CONFIG_FIXMAP

YH

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

end of thread, other threads:[~2007-06-01  0:11 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-30  1:43 [PATCH 4/5] serial: convert early_uart to earlycon for 8250 Yinghai Lu
2007-05-30 18:57 ` Andrew Morton
2007-05-30 19:58   ` Yinghai Lu
2007-05-30 20:18     ` Andrew Morton
2007-05-30 20:58       ` Yinghai Lu
2007-05-30 21:48         ` Andrew Morton
2007-05-31  3:13 ` Andrew Morton
2007-05-31  4:34   ` Yinghai Lu
2007-05-31  4:36     ` Yinghai Lu
2007-05-31  4:48       ` Andrew Morton
2007-05-31 15:17         ` Bjorn Helgaas
2007-05-31 16:32           ` Yinghai Lu
2007-05-31 16:45             ` Bjorn Helgaas
2007-05-31 18:49               ` Yinghai Lu
2007-05-31  4:39     ` Andrew Morton
2007-05-31  4:42       ` Yinghai Lu
2007-05-31  4:51         ` Andrew Morton
  -- strict thread matches above, loose matches on Subject: below --
2007-05-31 21:01 Yinghai Lu
2007-05-31 23:54 ` Andrew Morton
2007-06-01  0:11   ` Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox