Commit a4912303 authored by Daniel Thompson's avatar Daniel Thompson

serial: kgdboc: Allow earlycon initialization to be deferred

Currently there is no guarantee that an earlycon will be initialized
before kgdboc tries to adopt it. Almost the opposite: on systems
with ACPI then if earlycon has no arguments then it is guaranteed that
earlycon will not be initialized.

This patch mitigates the problem by giving kgdboc_earlycon a second
chance during console_init(). This isn't quite as good as stopping during
early parameter parsing but it is still early in the kernel boot.
Signed-off-by: default avatarDaniel Thompson <daniel.thompson@linaro.org>
Link: https://lore.kernel.org/r/20200430161741.1832050-1-daniel.thompson@linaro.orgReviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
parent f71fc3bc
...@@ -514,6 +514,10 @@ static struct kgdb_io kgdboc_earlycon_io_ops = { ...@@ -514,6 +514,10 @@ static struct kgdb_io kgdboc_earlycon_io_ops = {
.is_console = true, .is_console = true,
}; };
#define MAX_CONSOLE_NAME_LEN (sizeof((struct console *) 0)->name)
static char kgdboc_earlycon_param[MAX_CONSOLE_NAME_LEN] __initdata;
static bool kgdboc_earlycon_late_enable __initdata;
static int __init kgdboc_earlycon_init(char *opt) static int __init kgdboc_earlycon_init(char *opt)
{ {
struct console *con; struct console *con;
...@@ -533,7 +537,23 @@ static int __init kgdboc_earlycon_init(char *opt) ...@@ -533,7 +537,23 @@ static int __init kgdboc_earlycon_init(char *opt)
} }
if (!con) { if (!con) {
/*
* Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets
* in first and, in any case, on ACPI systems earlycon may
* defer its own initialization (usually to somewhere within
* setup_arch() ). To cope with either of these situations
* we can defer our own initialization to a little later in
* the boot.
*/
if (!kgdboc_earlycon_late_enable) {
pr_info("No suitable earlycon yet, will try later\n");
if (opt)
strscpy(kgdboc_earlycon_param, opt,
sizeof(kgdboc_earlycon_param));
kgdboc_earlycon_late_enable = true;
} else {
pr_info("Couldn't find kgdb earlycon\n"); pr_info("Couldn't find kgdb earlycon\n");
}
goto unlock; goto unlock;
} }
...@@ -556,6 +576,23 @@ static int __init kgdboc_earlycon_init(char *opt) ...@@ -556,6 +576,23 @@ static int __init kgdboc_earlycon_init(char *opt)
} }
early_param("kgdboc_earlycon", kgdboc_earlycon_init); early_param("kgdboc_earlycon", kgdboc_earlycon_init);
/*
* This is only intended for the late adoption of an early console.
*
* It is not a reliable way to adopt regular consoles because we can not
* control what order console initcalls are made and, in any case, many
* regular consoles are registered much later in the boot process than
* the console initcalls!
*/
static int __init kgdboc_earlycon_late_init(void)
{
if (kgdboc_earlycon_late_enable)
kgdboc_earlycon_init(kgdboc_earlycon_param);
return 0;
}
console_initcall(kgdboc_earlycon_late_init);
#endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ #endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */
module_init(init_kgdboc); module_init(init_kgdboc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment