[PATCH v4 1/3] power: reset: pscrr: add kernel panic reason tracking

Faruque Ansari <[email protected]>
Newsgroups org.kernel.vger.linux-pm,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-watchdog
Message-ID <[email protected]>
Kernel panic resets are not recorded in NVMEM, causing subsequent
boots to report PSCR_UNKNOWN and making post-mortem analysis more
difficult.

Register a panic notifier to preserve the shutdown reason across
panic-triggered resets. Add PSCR_KERNEL_PANIC as a dedicated reset
reason code and its corresponding reason string to identify kernel
panic resets on subsequent boots.

Signed-off-by: Faruque Ansari <[email protected]>
---
 drivers/power/reset/pscrr/pscrr.c     | 27 +++++++++++++++++++++++++++
 include/linux/power/power_on_reason.h |  1 +
 include/linux/reboot.h                |  3 +++
 kernel/reboot.c                       |  1 +
 4 files changed, 32 insertions(+)

diff --git a/drivers/power/reset/pscrr/pscrr.c b/drivers/power/reset/pscrr/pscrr.c
index 6f23f4c4f590..8c45b84059a9 100644
--- a/drivers/power/reset/pscrr/pscrr.c
+++ b/drivers/power/reset/pscrr/pscrr.c
@@ -41,6 +41,7 @@
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/of.h>
+#include <linux/panic_notifier.h>
 #include <linux/pscrr.h>
 #include <linux/reboot.h>
 #include <linux/slab.h>
@@ -519,6 +520,29 @@ static struct notifier_block pscrr_reboot_nb = {
 	.notifier_call = pscrr_reboot_notifier,
 };
 
+/*
+ * Panic notifier: record that the machine went down through a kernel panic, so
+ * the cause is visible on the next boot. Runs in atomic panic context, so the
+ * provider list is walked without pscrr_lock - providers no longer come or go
+ * once the machine is going down.
+ */
+static int pscrr_panic_notifier(struct notifier_block *nb,
+				unsigned long action, void *unused)
+{
+	struct pscrr_provider_dir *dir;
+
+	set_psc_reason(PSCR_KERNEL_PANIC);
+
+	list_for_each_entry(dir, &pscrr_dirs, node)
+		pscrr_do_record(dir, get_psc_reason());
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block pscrr_panic_nb = {
+	.notifier_call = pscrr_panic_notifier,
+};
+
 /*----------------------------------------------------------------------*/
 /* Built-in provider: device-tree /chosen/reset-source                  */
 /*----------------------------------------------------------------------*/
@@ -611,6 +635,8 @@ static int __init pscrr_core_init(void)
 		return ret;
 	}
 
+	atomic_notifier_chain_register(&panic_notifier_list, &pscrr_panic_nb);
+
 	pscrr_register_reset_source();
 
 	return 0;
@@ -619,6 +645,7 @@ static int __init pscrr_core_init(void)
 static void __exit pscrr_core_exit(void)
 {
 	pscrr_provider_unregister(&pscrr_reset_source_provider);
+	atomic_notifier_chain_unregister(&panic_notifier_list, &pscrr_panic_nb);
 	unregister_reboot_notifier(&pscrr_reboot_nb);
 	kobject_put(pscrr_root);
 	pscrr_root = NULL;
diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h
index 13e61ace14f5..8c99bdd75021 100644
--- a/include/linux/power/power_on_reason.h
+++ b/include/linux/power/power_on_reason.h
@@ -20,5 +20,6 @@
 #define POWER_ON_REASON_OVER_TEMPERATURE "over temperature"
 #define POWER_ON_REASON_EC_PANIC "EC panic"
 #define POWER_ON_REASON_EXTERNAL "external reset"
+#define POWER_ON_REASON_KERNEL_PANIC "kernel panic"
 
 #endif /* POWER_ON_REASON_H */
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 13f004ad1066..a117dd5eaecd 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -241,6 +241,8 @@ extern void orderly_reboot(void);
  *
  * @PSCR_XTAL_FAIL: Reset caused by a crystal oscillator failure.
  *
+ * @PSCR_KERNEL_PANIC: Reset that followed a kernel panic.
+ *
  * @PSCR_REASON_COUNT: Number of defined power state change reasons. This
  *	value is useful for range checking and potential future extensions
  *	while maintaining compatibility.
@@ -264,6 +266,7 @@ enum psc_reason {
 	PSCR_RESET_BUTTON,
 	PSCR_CPU_CLK_FAIL,
 	PSCR_XTAL_FAIL,
+	PSCR_KERNEL_PANIC,
 
 	/* Number of reasons */
 	PSCR_REASON_COUNT,
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 75af5d763465..979ecf3b093c 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -1109,6 +1109,7 @@ static const struct psc_reason_desc psc_reason_descs[] = {
 	[PSCR_RESET_BUTTON]	 = { "reset-button",	  POWER_ON_REASON_RST_BTN },
 	[PSCR_CPU_CLK_FAIL]	 = { "cpu-clock-failure", POWER_ON_REASON_CPU_CLK_FAIL },
 	[PSCR_XTAL_FAIL]	 = { "crystal-failure",	  POWER_ON_REASON_XTAL_FAIL },
+	[PSCR_KERNEL_PANIC]	 = { "kernel-panic",	  POWER_ON_REASON_KERNEL_PANIC },
 };
 
 /**

-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.