[PATCH v2 1/3] power: reset: pscrr: add kernel panic reason tracking
Faruque Ansari <[email protected]> Wed, 22 Jul 2026 20:43:00 +0530
| Newsgroups | org.kernel.vger.linux-watchdog,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm |
|---|---|
| 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.c | 32 ++++++++++++++++++++++++++++++++ include/linux/power/power_on_reason.h | 1 + include/linux/reboot.h | 1 + kernel/reboot.c | 1 + 4 files changed, 35 insertions(+) diff --git a/drivers/power/reset/pscrr.c b/drivers/power/reset/pscrr.c index 92e8ef97421c..b5906f127e88 100644 --- a/drivers/power/reset/pscrr.c +++ b/drivers/power/reset/pscrr.c @@ -60,6 +60,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/notifier.h> +#include <linux/panic_notifier.h> #include <linux/power/power_on_reason.h> #include <linux/pscrr.h> #include <linux/reboot.h> @@ -78,6 +79,7 @@ struct pscrr_core { /* Kobject for sysfs */ struct kobject *kobj; struct notifier_block reboot_nb; + struct notifier_block panic_nb; }; static struct pscrr_core g_pscrr = { @@ -136,6 +138,30 @@ static int pscrr_reboot_notifier(struct notifier_block *nb, return NOTIFY_OK; } +static int pscrr_panic_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + int ret; + struct pscrr_backend *backend; + + backend = g_pscrr.backend; + + if (!backend || !backend->ops || !backend->ops->write_reason) + return NOTIFY_OK; + + set_psc_reason(PSCR_KERNEL_PANIC); + ret = backend->ops->write_reason(get_psc_reason()); + if (ret) + pr_err("PSCRR: Failed to store reason %d (%s) at panic, err=%pe\n", + get_psc_reason(), psc_reason_to_str(get_psc_reason()), + ERR_PTR(ret)); + else + pr_debug("PSCRR: Stored reason %d (%s) at panic.\n", + get_psc_reason(), psc_reason_to_str(get_psc_reason())); + + return NOTIFY_OK; +} + /*----------------------------------------------------------------------*/ /* Sysfs Interface */ /*----------------------------------------------------------------------*/ @@ -349,6 +375,10 @@ int pscrr_core_init(const struct pscrr_backend_ops *ops) goto err_free; } + /* Setup the panic notifier to persist reason on kernel panic */ + g_pscrr.panic_nb.notifier_call = pscrr_panic_notifier; + atomic_notifier_chain_register(&panic_notifier_list, &g_pscrr.panic_nb); + /* Create a kobject and sysfs group under /sys/kernel/pscrr */ g_pscrr.kobj = kobject_create_and_add("pscrr", kernel_kobj); if (!g_pscrr.kobj) { @@ -371,6 +401,7 @@ int pscrr_core_init(const struct pscrr_backend_ops *ops) err_kobj_put: kobject_put(g_pscrr.kobj); err_unreg_reboot: + atomic_notifier_chain_unregister(&panic_notifier_list, &g_pscrr.panic_nb); unregister_reboot_notifier(&g_pscrr.reboot_nb); err_free: kfree(g_pscrr.backend); @@ -391,6 +422,7 @@ void pscrr_core_exit(void) kobject_put(g_pscrr.kobj); } + atomic_notifier_chain_unregister(&panic_notifier_list, &g_pscrr.panic_nb); unregister_reboot_notifier(&g_pscrr.reboot_nb); kfree(g_pscrr.backend); diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h index bf9501792696..4ac1bdfdc211 100644 --- a/include/linux/power/power_on_reason.h +++ b/include/linux/power/power_on_reason.h @@ -19,5 +19,6 @@ #define POWER_ON_REASON_REGULATOR_FAILURE "regulator failure" #define POWER_ON_REASON_OVER_TEMPERATURE "over temperature" #define POWER_ON_REASON_EC_PANIC "EC panic" +#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 6477910c6a9e..a492b1652038 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -236,6 +236,7 @@ enum psc_reason { PSCR_REGULATOR_FAILURE, PSCR_OVER_TEMPERATURE, PSCR_EC_PANIC, + PSCR_KERNEL_PANIC, /* Number of reasons */ PSCR_REASON_COUNT, diff --git a/kernel/reboot.c b/kernel/reboot.c index 61e0027b7550..f1df52f8773a 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -1065,6 +1065,7 @@ static const char * const pscr_reason_strs[] = { [PSCR_REGULATOR_FAILURE] = POWER_ON_REASON_REGULATOR_FAILURE, [PSCR_OVER_TEMPERATURE] = POWER_ON_REASON_OVER_TEMPERATURE, [PSCR_EC_PANIC] = POWER_ON_REASON_EC_PANIC, + [PSCR_KERNEL_PANIC] = POWER_ON_REASON_KERNEL_PANIC, }; /** -- 2.34.1