
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICAO4O -------------------------------- During testing, it was found that in low-power scenarios, the CPU core frequently powers on and off, which causes the SDEI to fail. This is because the secure timer in the BIOS does not save and restore the state during the CPU core power-on and power-off process. The OS needs to add enable/disable operations in the suspend/resume process. Fixes: 06f3c8d59324 ("watchdog: add nmi_watchdog support for arm64 based on SDEI") Signed-off-by: Bowen You <youbowen2@huawei.com> --- arch/arm64/kernel/watchdog_sdei.c | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm64/kernel/watchdog_sdei.c b/arch/arm64/kernel/watchdog_sdei.c index b0302b22dc72..c891ea766684 100644 --- a/arch/arm64/kernel/watchdog_sdei.c +++ b/arch/arm64/kernel/watchdog_sdei.c @@ -16,6 +16,7 @@ #include <linux/arm_sdei.h> #include <linux/kprobes.h> #include <linux/nmi.h> +#include <linux/cpu_pm.h> /* We use the secure physical timer as SDEI NMI watchdog timer */ #define SDEI_NMI_WATCHDOG_HWIRQ 29 @@ -106,6 +107,40 @@ void sdei_watchdog_clear_eoi(void) sdei_api_clear_eoi(SDEI_NMI_WATCHDOG_HWIRQ); } +static int sdei_watchdog_pm_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + int rv; + + WARN_ON_ONCE(preemptible()); + + /* + * sdei watchdog not initialized yet, do nothing. + */ + if (sdei_watchdog_event_num == 0) + return NOTIFY_DONE; + + switch (action) { + case CPU_PM_ENTER: + rv = sdei_api_event_disable(sdei_watchdog_event_num); + break; + case CPU_PM_EXIT: + rv = sdei_api_event_enable(sdei_watchdog_event_num); + break; + default: + return NOTIFY_DONE; + } + + if (rv) + return notifier_from_errno(rv); + + return NOTIFY_OK; +} + +static struct notifier_block sdei_watchdog_pm_nb = { + .notifier_call = sdei_watchdog_pm_notifier, +}; + int __init sdei_watchdog_hardlockup_probe(void) { int ret; @@ -144,6 +179,11 @@ int __init sdei_watchdog_hardlockup_probe(void) return ret; } + ret = cpu_pm_register_notifier(&sdei_watchdog_pm_nb); + if (ret) { + pr_warn("Failed to register sdei PM notifier...\n"); + return ret; + } sdei_watchdog_registered = true; pr_info("SDEI Watchdog registered successfully\n"); -- 2.34.1