]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
serial: kgdboc: Allow earlycon initialization to be deferred
authorDaniel Thompson <daniel.thompson@linaro.org>
Thu, 30 Apr 2020 16:17:41 +0000 (17:17 +0100)
committerDaniel Thompson <daniel.thompson@linaro.org>
Tue, 2 Jun 2020 14:15:45 +0000 (15:15 +0100)
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: Daniel Thompson <daniel.thompson@linaro.org>
Link: https://lore.kernel.org/r/20200430161741.1832050-1-daniel.thompson@linaro.org
Reviewed-by: Douglas Anderson <dianders@chromium.org>
drivers/tty/serial/kgdboc.c

index fa6f7a3e73b99661cf7a3ee842b4aa835be2d0e6..41396982e9e081815c7db4177172657ad5db77b8 100644 (file)
@@ -514,6 +514,10 @@ static struct kgdb_io kgdboc_earlycon_io_ops = {
        .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)
 {
        struct console *con;
@@ -533,7 +537,23 @@ static int __init kgdboc_earlycon_init(char *opt)
        }
 
        if (!con) {
-               pr_info("Couldn't find kgdb earlycon\n");
+               /*
+                * 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");
+               }
                goto unlock;
        }
 
@@ -556,6 +576,23 @@ unlock:
 }
 
 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) */
 
 module_init(init_kgdboc);