[PATCH 2/2] boot: introduce option to pass barebox-enabled watchdog to systemd

Ahmad Fatoum a.fatoum at pengutronix.de
Fri Nov 20 09:06:49 EST 2020


Like Linux, barebox supports co-existence of multiple watchdog
devices. On boot, barebox enables only the default watchdog, which
is defined as the watchdog with highest non-zero priority.

The kernel handles all watchdogs the same and defers to userspace,
which watchdogs to service. It can be useful to have barebox tell
the system, which watchdog it activated, so it can service the same.

Having this feature behind a global variable adds 567 bytes to a
LZO compressed THUMB2 barebox. Allow users to opt out by having
a Kconfig option instead.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/Kconfig | 10 ++++++++++
 common/boot.c  | 42 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/common/Kconfig b/common/Kconfig
index 9b73aa84549c..3cb43a7190bb 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1006,6 +1006,16 @@ config MACHINE_ID
 	  Note: if no hashable information is available no machine id will be passed
 	  to the kernel.
 
+config SYSTEMD_OF_WATCHDOG
+	bool "inform devicetree-enabled kernel of used watchdog"
+	depends on WATCHDOG && OFTREE && FLEXIBLE_BOOTARGS
+	help
+	  Sets the linux.bootargs.dyn.watchdog global variable with a value of
+	  systemd.watchdog-device=/dev/WDOG if barebox succeeded in enabling
+	  the watchdog WDOG prior to boot. WDOG is the alias of the watchdog
+	  in the kernel device tree. If the kernel is booted without a device
+	  tree or with one that lacks aliases, nothing is added.
+
 menu "OP-TEE loading"
 
 config OPTEE_SIZE
diff --git a/common/boot.c b/common/boot.c
index 90d504e3c324..76d03c26c4f4 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -139,6 +139,39 @@ late_initcall(init_boot);
 BAREBOX_MAGICVAR(global.boot.watchdog_timeout,
 		"Watchdog enable timeout in seconds before booting");
 
+static struct watchdog *__watchdog;
+
+static int watchdog_of_fixup(struct device_node *root, void *arg)
+{
+	int alias_id;
+	char *buf;
+
+	if (!__watchdog)
+		return 0;
+
+	alias_id = watchdog_get_alias_id_from(__watchdog, root);
+	if (alias_id < 0)
+		return 0;
+
+	buf = basprintf("systemd.watchdog-device=/dev/watchdog%d", alias_id);
+	if (!buf)
+		return 0;
+
+	globalvar_add_simple("linux.bootargs.dyn.watchdog", buf);
+	free(buf);
+
+	return 0;
+}
+
+static int __maybe_unused of_register_watchdog_fixup(void)
+{
+	return of_register_fixup(watchdog_of_fixup, NULL);
+}
+#ifdef CONFIG_SYSTEMD_OF_WATCHDOG
+/* _must_ not be run after late_initcall(of_register_bootargs_fixup) */
+device_initcall(of_register_watchdog_fixup);
+#endif
+
 int boot_entry(struct bootentry *be, int verbose, int dryrun)
 {
 	int ret;
@@ -146,10 +179,13 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun)
 	printf("Booting entry '%s'\n", be->title);
 
 	if (IS_ENABLED(CONFIG_WATCHDOG) && boot_watchdog_timeout) {
-		ret = watchdog_set_timeout(watchdog_get_default(),
-					   boot_watchdog_timeout);
-		if (ret)
+		__watchdog = watchdog_get_default();
+
+		ret = watchdog_set_timeout(__watchdog, boot_watchdog_timeout);
+		if (ret) {
 			pr_warn("Failed to enable watchdog: %s\n", strerror(-ret));
+			__watchdog = NULL;
+		}
 	}
 
 	ret = be->boot(be, verbose, dryrun);
-- 
2.29.2




More information about the barebox mailing list