Linux Power Management development
 help / color / mirror / Atom feed
* [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout
@ 2026-07-14  9:52 Faruque Ansari
  2026-07-14  9:52 ` [PATCH 1/2] power: reset: pscrr: add kernel panic reason tracking Faruque Ansari
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Faruque Ansari @ 2026-07-14  9:52 UTC (permalink / raw)
  To: Sebastian Reichel, Wim Van Sebroeck, Guenter Roeck, Benson Leung,
	Tzung-Bi Shih, Oleksij Rempel, Srinivas Kandagatla,
	Daniel Lezcano
  Cc: linux-pm, linux-kernel, linux-watchdog, linux-arm-msm, kernel,
	avaneesh.dwivedi, Umang Chheda, Faruque Ansari

This series extends the Power State Change Reason Register (PSCRR)[1]
framework to capture two additional reset causes.

  1. Kernel panic — a panic notifier writes PSCR_KERNEL_PANIC to NVMEM
     before the system resets, so the next boot can distinguish a panic
     from other reset causes.

  2. Watchdog pretimeout — set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT) is
     called from watchdog_notify_pretimeout(), when the watchdog fire its
     pre-reset notification before resetting the system, so the reason gets
     saved and we know its was a watchdog timeout that caused the reset.

[1] https://lore.kernel.org/lkml/20250618120255.3141862-1-o.rempel@pengutronix.de/

To: Sebastian Reichel <sre@kernel.org>
To: Wim Van Sebroeck <wim@linux-watchdog.org>
To: Guenter Roeck <linux@roeck-us.net>
To: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
To: Benson Leung <bleung@chromium.org>
To: Tzung-Bi Shih <tzungbi@kernel.org>
To: Daniel Lezcano <daniel.lezcano@linaro.org>
To: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-watchdog@vger.kernel.org
Cc: linux-arm-msm@vger.org
Cc: kernel@pengutronix.de
Cc: Liam Girdwood" <lgirdwood@gmail.com>
Cc: Mark Brown" <broonie@kernel.org>
Cc: Rafael J. Wysocki" <rafael@kernel.org>
Cc: Zhang Rui" <rui.zhang@intel.com>
Cc: Lukasz Luba" <lukasz.luba@arm.com>
Cc: Søren Andersen" <san@skov.dk>
Cc: Guenter Roeck" <groeck@chromium.org>
Cc: Matti Vaittinen" <mazziesaccount@gmail.com>
Cc: Ahmad Fatoum" <a.fatoum@pengutronix.de>
Cc: Andrew Morton" <akpm@linux-foundation.org>
Cc: avaneesh.dwivedi@oss.qualcomm.com
Cc: Umang Chheda <umang.chheda@oss.qualcomm.com>

Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
---
Faruque Ansari (2):
      power: reset: pscrr: add kernel panic reason tracking
      watchdog: pscrr: add watchdog pretimeout reason tracking

 drivers/power/reset/pscrr.c            | 33 +++++++++++++++++++++++++++++++++
 drivers/watchdog/watchdog_pretimeout.c |  3 +++
 include/linux/power/power_on_reason.h  |  2 ++
 include/linux/reboot.h                 |  2 ++
 kernel/reboot.c                        |  2 ++
 5 files changed, 42 insertions(+)
---
base-commit: 9696e3e0e12695f18c26e339bc609a2d56b51c5a
change-id: 20260714-pscrr-reboot-reason-2b4e16ccb6b8

Best regards,
-- 
Faruque Ansari <faruque.ansari@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] power: reset: pscrr: add kernel panic reason tracking
  2026-07-14  9:52 [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Faruque Ansari
@ 2026-07-14  9:52 ` Faruque Ansari
  2026-07-14  9:52 ` [PATCH 2/2] watchdog: pscrr: add watchdog pretimeout " Faruque Ansari
  2026-07-15  6:20 ` [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Oleksij Rempel
  2 siblings, 0 replies; 4+ messages in thread
From: Faruque Ansari @ 2026-07-14  9:52 UTC (permalink / raw)
  To: Sebastian Reichel, Wim Van Sebroeck, Guenter Roeck, Benson Leung,
	Tzung-Bi Shih, Oleksij Rempel, Srinivas Kandagatla,
	Daniel Lezcano
  Cc: linux-pm, linux-kernel, linux-watchdog, linux-arm-msm, kernel,
	avaneesh.dwivedi, Umang Chheda, Faruque Ansari

Without this change, a kernel panic leaves no trace in NVMEM — the
system resets silently and the next boot sees PSCR_UNKNOWN, making
post-mortem diagnosis harder.

Add a panic notifier so the recorded shutdown reason survives a kernel
panic and is available for inspection on the next boot.  Also introduce
PSCR_KERNEL_PANIC as a dedicated reason code with its human-readable
string so userspace and bootloaders can distinguish a panic-driven reset
from other reset causes.

Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
---
 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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] watchdog: pscrr: add watchdog pretimeout reason tracking
  2026-07-14  9:52 [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Faruque Ansari
  2026-07-14  9:52 ` [PATCH 1/2] power: reset: pscrr: add kernel panic reason tracking Faruque Ansari
@ 2026-07-14  9:52 ` Faruque Ansari
  2026-07-15  6:20 ` [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Oleksij Rempel
  2 siblings, 0 replies; 4+ messages in thread
From: Faruque Ansari @ 2026-07-14  9:52 UTC (permalink / raw)
  To: Sebastian Reichel, Wim Van Sebroeck, Guenter Roeck, Benson Leung,
	Tzung-Bi Shih, Oleksij Rempel, Srinivas Kandagatla,
	Daniel Lezcano
  Cc: linux-pm, linux-kernel, linux-watchdog, linux-arm-msm, kernel,
	avaneesh.dwivedi, Umang Chheda, Faruque Ansari

A watchdog pretimeout fires before the actual reset, giving the kernel
a brief window to record what happened.  Without this change that
window goes unused and the next boot sees PSCR_UNKNOWN, making it
impossible to tell a watchdog-driven reset from any other cause.

Call set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT) at the top of
watchdog_notify_pretimeout() so the reason is recorded as soon as the
pretimeout is signalled, before any governor action runs.

Signed-off-by: Faruque Ansari <faruque.ansari@oss.qualcomm.com>
---
 drivers/power/reset/pscrr.c            | 3 ++-
 drivers/watchdog/watchdog_pretimeout.c | 3 +++
 include/linux/power/power_on_reason.h  | 1 +
 include/linux/reboot.h                 | 1 +
 kernel/reboot.c                        | 1 +
 5 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/power/reset/pscrr.c b/drivers/power/reset/pscrr.c
index b5906f127e88..36642cf9f27c 100644
--- a/drivers/power/reset/pscrr.c
+++ b/drivers/power/reset/pscrr.c
@@ -149,7 +149,8 @@ static int pscrr_panic_notifier(struct notifier_block *nb,
 	if (!backend || !backend->ops || !backend->ops->write_reason)
 		return NOTIFY_OK;
 
-	set_psc_reason(PSCR_KERNEL_PANIC);
+	if (get_psc_reason() != PSCR_WATCHDOG_PRETIMEOUT)
+		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",
diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c
index 02e09b9e396d..ea48d4eca4aa 100644
--- a/drivers/watchdog/watchdog_pretimeout.c
+++ b/drivers/watchdog/watchdog_pretimeout.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -103,6 +104,8 @@ void watchdog_notify_pretimeout(struct watchdog_device *wdd)
 {
 	unsigned long flags;
 
+	set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT);
+
 	spin_lock_irqsave(&pretimeout_lock, flags);
 	if (!wdd->gov) {
 		spin_unlock_irqrestore(&pretimeout_lock, flags);
diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h
index 4ac1bdfdc211..c5846c0ccde4 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_KERNEL_PANIC "kernel panic"
+#define POWER_ON_REASON_WATCHDOG_PRETIMEOUT "watchdog pretimeout"
 
 #endif /* POWER_ON_REASON_H */
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index a492b1652038..fccbffc9dbef 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -237,6 +237,7 @@ enum psc_reason {
 	PSCR_OVER_TEMPERATURE,
 	PSCR_EC_PANIC,
 	PSCR_KERNEL_PANIC,
+	PSCR_WATCHDOG_PRETIMEOUT,
 
 	/* Number of reasons */
 	PSCR_REASON_COUNT,
diff --git a/kernel/reboot.c b/kernel/reboot.c
index f1df52f8773a..629002a951c2 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -1066,6 +1066,7 @@ static const char * const pscr_reason_strs[] = {
 	[PSCR_OVER_TEMPERATURE]   = POWER_ON_REASON_OVER_TEMPERATURE,
 	[PSCR_EC_PANIC]           = POWER_ON_REASON_EC_PANIC,
 	[PSCR_KERNEL_PANIC]       = POWER_ON_REASON_KERNEL_PANIC,
+	[PSCR_WATCHDOG_PRETIMEOUT] = POWER_ON_REASON_WATCHDOG_PRETIMEOUT,
 };
 
 /**

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout
  2026-07-14  9:52 [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Faruque Ansari
  2026-07-14  9:52 ` [PATCH 1/2] power: reset: pscrr: add kernel panic reason tracking Faruque Ansari
  2026-07-14  9:52 ` [PATCH 2/2] watchdog: pscrr: add watchdog pretimeout " Faruque Ansari
@ 2026-07-15  6:20 ` Oleksij Rempel
  2 siblings, 0 replies; 4+ messages in thread
From: Oleksij Rempel @ 2026-07-15  6:20 UTC (permalink / raw)
  To: Faruque Ansari
  Cc: Sebastian Reichel, Wim Van Sebroeck, Guenter Roeck, Benson Leung,
	Tzung-Bi Shih, Srinivas Kandagatla, Daniel Lezcano, linux-pm,
	linux-kernel, linux-watchdog, linux-arm-msm, kernel,
	avaneesh.dwivedi, Umang Chheda

Hi Faruque,

On Tue, Jul 14, 2026 at 03:22:33PM +0530, Faruque Ansari wrote:
> This series extends the Power State Change Reason Register (PSCRR)[1]
> framework to capture two additional reset causes.
> 
>   1. Kernel panic — a panic notifier writes PSCR_KERNEL_PANIC to NVMEM
>      before the system resets, so the next boot can distinguish a panic
>      from other reset causes.
> 
>   2. Watchdog pretimeout — set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT) is
>      called from watchdog_notify_pretimeout(), when the watchdog fire its
>      pre-reset notification before resetting the system, so the reason gets
>      saved and we know its was a watchdog timeout that caused the reset.

Thank you, LGTM!

Right now I'm on a netdev conference, will need to take a closer look
after it.

Best Regards,
Oleksij
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-15  6:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14  9:52 [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Faruque Ansari
2026-07-14  9:52 ` [PATCH 1/2] power: reset: pscrr: add kernel panic reason tracking Faruque Ansari
2026-07-14  9:52 ` [PATCH 2/2] watchdog: pscrr: add watchdog pretimeout " Faruque Ansari
2026-07-15  6:20 ` [PATCH 0/2] power: reset: pscrr: record reset cause on panic and watchdog pretimeout Oleksij Rempel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox