aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <Yinghai.Lu@Sun.COM>2007-07-16 02:37:59 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:35 -0400
commit18a8bd949d6adb311ea816125ff65050df1f3f6e (patch)
tree4365db908430747a5c08cacdb4354577b7bfead7
parentb1c931e39327ef121797927d4b3198d370e75b9b (diff)
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> Cc: Andi Kleen <ak@suse.de> Cc: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Gerd Hoffmann <kraxel@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--arch/ia64/kernel/setup.c4
-rw-r--r--drivers/firmware/pcdp.c6
-rw-r--r--drivers/serial/8250.c28
-rw-r--r--drivers/serial/8250_early.c117
-rw-r--r--drivers/serial/Kconfig14
-rw-r--r--include/asm-i386/fixmap.h2
-rw-r--r--include/asm-i386/io.h1
-rw-r--r--include/asm-x86_64/fixmap.h4
-rw-r--r--include/asm-x86_64/io.h1
-rw-r--r--include/linux/console.h2
-rw-r--r--include/linux/serial.h6
-rw-r--r--include/linux/serial_8250.h4
-rw-r--r--init/main.c5
-rw-r--r--kernel/printk.c22
15 files changed, 132 insertions, 95 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4d880b3d1f3..62aab585d9d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -462,13 +462,20 @@ and is between 256 and 4096 characters. It is defined in the file
462 Documentation/networking/netconsole.txt for an 462 Documentation/networking/netconsole.txt for an
463 alternative. 463 alternative.
464 464
465 uart,io,<addr>[,options] 465 uart[8250],io,<addr>[,options]
466 uart,mmio,<addr>[,options] 466 uart[8250],mmio,<addr>[,options]
467 Start an early, polled-mode console on the 8250/16550 467 Start an early, polled-mode console on the 8250/16550
468 UART at the specified I/O port or MMIO address, 468 UART at the specified I/O port or MMIO address,
469 switching to the matching ttyS device later. The 469 switching to the matching ttyS device later. The
470 options are the same as for ttyS, above. 470 options are the same as for ttyS, above.
471 471
472 earlycon= [KNL] Output early console device and options.
473 uart[8250],io,<addr>[,options]
474 uart[8250],mmio,<addr>[,options]
475 Start an early, polled-mode console on the 8250/16550
476 UART at the specified I/O port or MMIO address.
477 The options are the same as for ttyS, above.
478
472 cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver 479 cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
473 Format: 480 Format:
474 <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>] 481 <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 188fb73c684..4d9864cc92c 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -390,10 +390,6 @@ early_console_setup (char *cmdline)
390 if (!efi_setup_pcdp_console(cmdline)) 390 if (!efi_setup_pcdp_console(cmdline))
391 earlycons++; 391 earlycons++;
392#endif 392#endif
393#ifdef CONFIG_SERIAL_8250_CONSOLE
394 if (!early_serial_console_init(cmdline))
395 earlycons++;
396#endif
397 393
398 return (earlycons) ? 0 : -1; 394 return (earlycons) ? 0 : -1;
399} 395}
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 2b4b76e8bd7..58e9f8e457f 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,6 +15,7 @@
15#include <linux/console.h> 15#include <linux/console.h>
16#include <linux/efi.h> 16#include <linux/efi.h>
17#include <linux/serial.h> 17#include <linux/serial.h>
18#include <linux/serial_8250.h>
18#include <asm/vga.h> 19#include <asm/vga.h>
19#include "pcdp.h" 20#include "pcdp.h"
20 21
@@ -27,7 +28,7 @@ setup_serial_console(struct pcdp_uart *uart)
27 char parity; 28 char parity;
28 29
29 mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); 30 mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
30 p += sprintf(p, "console=uart,%s,0x%lx", 31 p += sprintf(p, "uart8250,%s,0x%lx",
31 mmio ? "mmio" : "io", uart->addr.address); 32 mmio ? "mmio" : "io", uart->addr.address);
32 if (uart->baud) { 33 if (uart->baud) {
33 p += sprintf(p, ",%lu", uart->baud); 34 p += sprintf(p, ",%lu", uart->baud);
@@ -41,7 +42,8 @@ setup_serial_console(struct pcdp_uart *uart)
41 } 42 }
42 } 43 }
43 44
44 return early_serial_console_init(options); 45 add_preferred_console("uart", 8250, &options[9]);
46 return setup_early_serial8250_console(options);
45#else 47#else
46 return -ENODEV; 48 return -ENODEV;
47#endif 49#endif
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab083a8..0b3ec38ae61 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)
2514 return uart_set_options(port, co, baud, parity, bits, flow); 2514 return uart_set_options(port, co, baud, parity, bits, flow);
2515} 2515}
2516 2516
2517static int __init serial8250_console_early_setup(void)
2518{
2519 return serial8250_find_port_for_earlycon();
2520}
2521
2517static struct uart_driver serial8250_reg; 2522static struct uart_driver serial8250_reg;
2518static struct console serial8250_console = { 2523static struct console serial8250_console = {
2519 .name = "ttyS", 2524 .name = "ttyS",
2520 .write = serial8250_console_write, 2525 .write = serial8250_console_write,
2521 .device = uart_console_device, 2526 .device = uart_console_device,
2522 .setup = serial8250_console_setup, 2527 .setup = serial8250_console_setup,
2528 .early_setup = serial8250_console_early_setup,
2523 .flags = CON_PRINTBUFFER, 2529 .flags = CON_PRINTBUFFER,
2524 .index = -1, 2530 .index = -1,
2525 .data = &serial8250_reg, 2531 .data = &serial8250_reg,
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void)
2533} 2539}
2534console_initcall(serial8250_console_init); 2540console_initcall(serial8250_console_init);
2535 2541
2536static int __init find_port(struct uart_port *p) 2542int serial8250_find_port(struct uart_port *p)
2537{ 2543{
2538 int line; 2544 int line;
2539 struct uart_port *port; 2545 struct uart_port *port;
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p)
2546 return -ENODEV; 2552 return -ENODEV;
2547} 2553}
2548 2554
2549int __init serial8250_start_console(struct uart_port *port, char *options)
2550{
2551 int line;
2552
2553 line = find_port(port);
2554 if (line < 0)
2555 return -ENODEV;
2556
2557 add_preferred_console("ttyS", line, options);
2558 printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
2559 line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
2560 port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
2561 (unsigned long) port->iobase, options);
2562 if (!(serial8250_console.flags & CON_ENABLED)) {
2563 serial8250_console.flags &= ~CON_PRINTBUFFER;
2564 register_console(&serial8250_console);
2565 }
2566 return line;
2567}
2568
2569#define SERIAL8250_CONSOLE &serial8250_console 2555#define SERIAL8250_CONSOLE &serial8250_console
2570#else 2556#else
2571#define SERIAL8250_CONSOLE NULL 2557#define SERIAL8250_CONSOLE NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e511199b4c..947c20507e1 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
17 * we locate the device directly by its MMIO or I/O port address. 17 * we locate the device directly by its MMIO or I/O port address.
18 * 18 *
19 * The user can specify the device directly, e.g., 19 * The user can specify the device directly, e.g.,
20 * console=uart,io,0x3f8,9600n8 20 * earlycon=uart8250,io,0x3f8,9600n8
21 * console=uart,mmio,0xff5e0000,115200n8 21 * earlycon=uart8250,mmio,0xff5e0000,115200n8
22 * or platform code can call early_uart_console_init() to set 22 * or
23 * the early UART device. 23 * console=uart8250,io,0x3f8,9600n8
24 * 24 * console=uart8250,mmio,0xff5e0000,115200n8
25 * After the normal serial driver starts, we try to locate the
26 * matching ttyS device and start a console there.
27 */ 25 */
28 26
29#include <linux/tty.h> 27#include <linux/tty.h>
@@ -32,17 +30,21 @@
32#include <linux/serial_core.h> 30#include <linux/serial_core.h>
33#include <linux/serial_reg.h> 31#include <linux/serial_reg.h>
34#include <linux/serial.h> 32#include <linux/serial.h>
33#include <linux/serial_8250.h>
35#include <asm/io.h> 34#include <asm/io.h>
36#include <asm/serial.h> 35#include <asm/serial.h>
36#ifdef CONFIG_FIX_EARLYCON_MEM
37#include <asm/pgtable.h>
38#include <asm/fixmap.h>
39#endif
37 40
38struct early_uart_device { 41struct early_serial8250_device {
39 struct uart_port port; 42 struct uart_port port;
40 char options[16]; /* e.g., 115200n8 */ 43 char options[16]; /* e.g., 115200n8 */
41 unsigned int baud; 44 unsigned int baud;
42}; 45};
43 46
44static struct early_uart_device early_device __initdata; 47static struct early_serial8250_device early_device;
45static int early_uart_registered __initdata;
46 48
47static unsigned int __init serial_in(struct uart_port *port, int offset) 49static unsigned int __init serial_in(struct uart_port *port, int offset)
48{ 50{
@@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c)
80 serial_out(port, UART_TX, c); 82 serial_out(port, UART_TX, c);
81} 83}
82 84
83static void __init early_uart_write(struct console *console, const char *s, unsigned int count) 85static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
84{ 86{
85 struct uart_port *port = &early_device.port; 87 struct uart_port *port = &early_device.port;
86 unsigned int ier; 88 unsigned int ier;
@@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
111 return (port->uartclk / 16) / quot; 113 return (port->uartclk / 16) / quot;
112} 114}
113 115
114static void __init init_port(struct early_uart_device *device) 116static void __init init_port(struct early_serial8250_device *device)
115{ 117{
116 struct uart_port *port = &device->port; 118 struct uart_port *port = &device->port;
117 unsigned int divisor; 119 unsigned int divisor;
@@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device)
130 serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); 132 serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
131} 133}
132 134
133static int __init parse_options(struct early_uart_device *device, char *options) 135static int __init parse_options(struct early_serial8250_device *device, char *options)
134{ 136{
135 struct uart_port *port = &device->port; 137 struct uart_port *port = &device->port;
136 int mapsize = 64;
137 int mmio, length; 138 int mmio, length;
138 139
139 if (!options) 140 if (!options)
@@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options)
143 if (!strncmp(options, "mmio,", 5)) { 144 if (!strncmp(options, "mmio,", 5)) {
144 port->iotype = UPIO_MEM; 145 port->iotype = UPIO_MEM;
145 port->mapbase = simple_strtoul(options + 5, &options, 0); 146 port->mapbase = simple_strtoul(options + 5, &options, 0);
146 port->membase = ioremap(port->mapbase, mapsize); 147#ifdef CONFIG_FIX_EARLYCON_MEM
148 set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
149 port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
150 port->membase += port->mapbase & ~PAGE_MASK;
151#else
152 port->membase = ioremap(port->mapbase, 64);
147 if (!port->membase) { 153 if (!port->membase) {
148 printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", 154 printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
149 __FUNCTION__, port->mapbase); 155 __FUNCTION__, port->mapbase);
150 return -ENOMEM; 156 return -ENOMEM;
151 } 157 }
158#endif
152 mmio = 1; 159 mmio = 1;
153 } else if (!strncmp(options, "io,", 3)) { 160 } else if (!strncmp(options, "io,", 3)) {
154 port->iotype = UPIO_PORT; 161 port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
175 return 0; 182 return 0;
176} 183}
177 184
178static int __init early_uart_setup(struct console *console, char *options) 185static struct console early_serial8250_console __initdata = {
186 .name = "uart",
187 .write = early_serial8250_write,
188 .flags = CON_PRINTBUFFER | CON_BOOT,
189 .index = -1,
190};
191
192static int __init early_serial8250_setup(char *options)
179{ 193{
180 struct early_uart_device *device = &early_device; 194 struct early_serial8250_device *device = &early_device;
181 int err; 195 int err;
182 196
183 if (device->port.membase || device->port.iobase) 197 if (device->port.membase || device->port.iobase)
@@ -190,61 +204,48 @@ static int __init early_uart_setup(struct console *console, char *options)
190 return 0; 204 return 0;
191} 205}
192 206
193static struct console early_uart_console __initdata = { 207int __init setup_early_serial8250_console(char *cmdline)
194 .name = "uart",
195 .write = early_uart_write,
196 .setup = early_uart_setup,
197 .flags = CON_PRINTBUFFER,
198 .index = -1,
199};
200
201static int __init early_uart_console_init(void)
202{
203 if (!early_uart_registered) {
204 register_console(&early_uart_console);
205 early_uart_registered = 1;
206 }
207 return 0;
208}
209console_initcall(early_uart_console_init);
210
211int __init early_serial_console_init(char *cmdline)
212{ 208{
213 char *options; 209 char *options;
214 int err; 210 int err;
215 211
216 options = strstr(cmdline, "console=uart,"); 212 options = strstr(cmdline, "uart8250,");
217 if (!options) 213 if (!options) {
218 return -ENODEV; 214 options = strstr(cmdline, "uart,");
215 if (!options)
216 return 0;
217 }
219 218
220 options = strchr(cmdline, ',') + 1; 219 options = strchr(cmdline, ',') + 1;
221 if ((err = early_uart_setup(NULL, options)) < 0) 220 if ((err = early_serial8250_setup(options)) < 0)
222 return err; 221 return err;
223 return early_uart_console_init(); 222
223 register_console(&early_serial8250_console);
224
225 return 0;
224} 226}
225 227
226static int __init early_uart_console_switch(void) 228int __init serial8250_find_port_for_earlycon(void)
227{ 229{
228 struct early_uart_device *device = &early_device; 230 struct early_serial8250_device *device = &early_device;
229 struct uart_port *port = &device->port; 231 struct uart_port *port = &device->port;
230 int mmio, line; 232 int line;
233 int ret;
231 234
232 if (!(early_uart_console.flags & CON_ENABLED)) 235 if (!device->port.membase && !device->port.iobase)
233 return 0; 236 return -ENODEV;
234 237
235 /* Try to start the normal driver on a matching line. */ 238 line = serial8250_find_port(port);
236 mmio = (port->iotype == UPIO_MEM);
237 line = serial8250_start_console(port, device->options);
238 if (line < 0) 239 if (line < 0)
239 printk("No ttyS device at %s 0x%lx for console\n", 240 return -ENODEV;
240 mmio ? "MMIO" : "I/O port",
241 mmio ? port->mapbase :
242 (unsigned long) port->iobase);
243 241
244 unregister_console(&early_uart_console); 242 ret = update_console_cmdline("uart", 8250,
245 if (mmio) 243 "ttyS", line, device->options);
246 iounmap(port->membase); 244 if (ret < 0)
245 ret = update_console_cmdline("uart", 0,
246 "ttyS", line, device->options);
247 247
248 return 0; 248 return ret;
249} 249}
250late_initcall(early_uart_console_switch); 250
251early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2adbed4e10f..cab42cbd920 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE
62 kernel will automatically use the first serial line, /dev/ttyS0, as 62 kernel will automatically use the first serial line, /dev/ttyS0, as
63 system console. 63 system console.
64 64
65 you can set that using a kernel command line option such as
66 "console=uart8250,io,0x3f8,9600n8"
67 "console=uart8250,mmio,0xff5e0000,115200n8".
68 and it will switch to normal serial console when correponding port is
69 ready.
70 "earlycon=uart8250,io,0x3f8,9600n8"
71 "earlycon=uart8250,mmio,0xff5e0000,115200n8".
72 it will not only setup early console.
73
65 If unsure, say N. 74 If unsure, say N.
66 75
76config FIX_EARLYCON_MEM
77 bool
78 depends on X86
79 default y
80
67config SERIAL_8250_GSC 81config SERIAL_8250_GSC
68 tristate 82 tristate
69 depends on SERIAL_8250 && GSC 83 depends on SERIAL_8250 && GSC
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 80ea052ee3a..249e753ac80 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -54,6 +54,8 @@ extern unsigned long __FIXADDR_TOP;
54enum fixed_addresses { 54enum fixed_addresses {
55 FIX_HOLE, 55 FIX_HOLE,
56 FIX_VDSO, 56 FIX_VDSO,
57 FIX_DBGP_BASE,
58 FIX_EARLYCON_MEM_BASE,
57#ifdef CONFIG_X86_LOCAL_APIC 59#ifdef CONFIG_X86_LOCAL_APIC
58 FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ 60 FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
59#endif 61#endif
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index e797586a5bf..7b65b5b0003 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -129,6 +129,7 @@ extern void iounmap(volatile void __iomem *addr);
129 */ 129 */
130extern void *bt_ioremap(unsigned long offset, unsigned long size); 130extern void *bt_ioremap(unsigned long offset, unsigned long size);
131extern void bt_iounmap(void *addr, unsigned long size); 131extern void bt_iounmap(void *addr, unsigned long size);
132extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
132 133
133/* Use early IO mappings for DMI because it's initialized early */ 134/* Use early IO mappings for DMI because it's initialized early */
134#define dmi_ioremap bt_ioremap 135#define dmi_ioremap bt_ioremap
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index e90e1677531..2acb9b7f641 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@ enum fixed_addresses {
35 VSYSCALL_LAST_PAGE, 35 VSYSCALL_LAST_PAGE,
36 VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, 36 VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
37 VSYSCALL_HPET, 37 VSYSCALL_HPET,
38 FIX_DBGP_BASE,
39 FIX_EARLYCON_MEM_BASE,
38 FIX_HPET_BASE, 40 FIX_HPET_BASE,
39 FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ 41 FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
40 FIX_IO_APIC_BASE_0, 42 FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
84 if (idx >= __end_of_fixed_addresses) 86 if (idx >= __end_of_fixed_addresses)
85 __this_fixmap_does_not_exist(); 87 __this_fixmap_does_not_exist();
86 88
87 return __fix_to_virt(idx); 89 return __fix_to_virt(idx);
88} 90}
89 91
90#endif 92#endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index de2cd9a2303..7475095c506 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);
144 */ 144 */
145extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); 145extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
146extern void iounmap(volatile void __iomem *addr); 146extern void iounmap(volatile void __iomem *addr);
147extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
147 148
148/* 149/*
149 * ISA I/O bus memory addresses are 1:1 with the physical address. 150 * 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 62ef6e11d0d..c44d3dfde7a 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -99,6 +99,7 @@ struct console {
99 struct tty_driver *(*device)(struct console *, int *); 99 struct tty_driver *(*device)(struct console *, int *);
100 void (*unblank)(void); 100 void (*unblank)(void);
101 int (*setup)(struct console *, char *); 101 int (*setup)(struct console *, char *);
102 int (*early_setup)(void);
102 short flags; 103 short flags;
103 short index; 104 short index;
104 int cflag; 105 int cflag;
@@ -107,6 +108,7 @@ struct console {
107}; 108};
108 109
109extern int add_preferred_console(char *name, int idx, char *options); 110extern int add_preferred_console(char *name, int idx, char *options);
111extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
110extern void register_console(struct console *); 112extern void register_console(struct console *);
111extern int unregister_console(struct console *); 113extern int unregister_console(struct console *);
112extern struct console *console_drivers; 114extern struct console *console_drivers;
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 33fc8cb8ddf..deb714314fb 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -177,11 +177,5 @@ struct serial_icounter_struct {
177#ifdef __KERNEL__ 177#ifdef __KERNEL__
178#include <linux/compiler.h> 178#include <linux/compiler.h>
179 179
180/* Allow architectures to override entries in serial8250_ports[] at run time: */
181struct uart_port; /* forward declaration */
182extern int early_serial_setup(struct uart_port *port);
183extern int early_serial_console_init(char *options);
184extern int serial8250_start_console(struct uart_port *port, char *options);
185
186#endif /* __KERNEL__ */ 180#endif /* __KERNEL__ */
187#endif /* _LINUX_SERIAL_H */ 181#endif /* _LINUX_SERIAL_H */
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 71310d80c09..706ee9a4c80 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -60,4 +60,8 @@ void serial8250_unregister_port(int line);
60void serial8250_suspend_port(int line); 60void serial8250_suspend_port(int line);
61void serial8250_resume_port(int line); 61void serial8250_resume_port(int line);
62 62
63extern int serial8250_find_port(struct uart_port *p);
64extern int serial8250_find_port_for_earlycon(void);
65extern int setup_early_serial8250_console(char *cmdline);
66
63#endif 67#endif
diff --git a/init/main.c b/init/main.c
index 0eb1c7463fe..038c7cb5239 100644
--- a/init/main.c
+++ b/init/main.c
@@ -453,7 +453,10 @@ static int __init do_early_param(char *param, char *val)
453 struct obs_kernel_param *p; 453 struct obs_kernel_param *p;
454 454
455 for (p = __setup_start; p < __setup_end; p++) { 455 for (p = __setup_start; p < __setup_end; p++) {
456 if (p->early && strcmp(param, p->str) == 0) { 456 if ((p->early && strcmp(param, p->str) == 0) ||
457 (strcmp(param, "console") == 0 &&
458 strcmp(p->str, "earlycon") == 0)
459 ) {
457 if (p->setup_func(val) != 0) 460 if (p->setup_func(val) != 0)
458 printk(KERN_WARNING 461 printk(KERN_WARNING
459 "Malformed early option '%s'\n", param); 462 "Malformed early option '%s'\n", param);
diff --git a/kernel/printk.c b/kernel/printk.c
index 7ce9a8c1331..f46cc6dff46 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -726,6 +726,25 @@ int __init add_preferred_console(char *name, int idx, char *options)
726 return 0; 726 return 0;
727} 727}
728 728
729int __init update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
730{
731 struct console_cmdline *c;
732 int i;
733
734 for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
735 if (strcmp(console_cmdline[i].name, name) == 0 &&
736 console_cmdline[i].index == idx) {
737 c = &console_cmdline[i];
738 memcpy(c->name, name_new, sizeof(c->name));
739 c->name[sizeof(c->name) - 1] = 0;
740 c->options = options;
741 c->index = idx_new;
742 return i;
743 }
744 /* not found */
745 return -1;
746}
747
729#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND 748#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
730/** 749/**
731 * suspend_console - suspend the console subsystem 750 * suspend_console - suspend the console subsystem
@@ -942,6 +961,9 @@ void register_console(struct console *console)
942 if (preferred_console < 0 || bootconsole || !console_drivers) 961 if (preferred_console < 0 || bootconsole || !console_drivers)
943 preferred_console = selected_console; 962 preferred_console = selected_console;
944 963
964 if (console->early_setup)
965 console->early_setup();
966
945 /* 967 /*
946 * See if we want to use this console driver. If we 968 * See if we want to use this console driver. If we
947 * didn't select a console we take the first one 969 * didn't select a console we take the first one