On pseries LPAR systems, watchdog timers configured from userspace can remain active after a kernel panic. When a panic triggers kdump, the crashing kernel jumps directly to the kdump kernel without stopping active watchdogs. As a result, the watchdogs remain active after the kdump kernel starts.
If dump capture takes longer than the watchdog timeout, PHYP resets the LPAR before the dump is fully captured, causing dump capture to fail. Fix this by issuing the `H_WATCHDOG` hcall during the crash shutdown sequence to stop all active watchdogs before booting the kdump kernel. Cc: [email protected] Fixes: 69472ffa6575 ("watchdog/pseries-wdt: initial support for H_WATCHDOG-based watchdog timers") Reported-by: Mahesh Kumar G <[email protected]> Suggested-by: Ritesh Harjani (IBM) <[email protected]> Reviewed-by: Ritesh Harjani (IBM) <[email protected]> Signed-off-by: Sourabh Jain <[email protected]> --- arch/powerpc/include/asm/papr-watchdog.h | 6 ++++++ arch/powerpc/platforms/pseries/setup.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/powerpc/include/asm/papr-watchdog.h b/arch/powerpc/include/asm/papr-watchdog.h index 308ffb73932d..bf876fc2caae 100644 --- a/arch/powerpc/include/asm/papr-watchdog.h +++ b/arch/powerpc/include/asm/papr-watchdog.h @@ -21,6 +21,12 @@ #define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */ #define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */ +/* + * R5: "watchdogNumber": + * PAPR says use -1 (all ones) to stop all watchdogs. + */ +#define PSERIES_WDT_NUM_ALL ((unsigned long)-1) + /* * H_WATCHDOG Output * diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index aed12412c600..f29e7547c995 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -77,6 +77,7 @@ #include <asm/dtl.h> #include <asm/hvconsole.h> #include <asm/setup.h> +#include <asm/papr-watchdog.h> #include "pseries.h" @@ -185,6 +186,16 @@ static void __init fwnmi_init(void) #endif } +static void pseries_crash_stop_watchdogs(void) +{ + long rc; + + rc = plpar_hcall_norets_notrace(H_WATCHDOG, PSERIES_WDTF_OP_STOP, + PSERIES_WDT_NUM_ALL); + if (rc != H_SUCCESS && rc != H_NOOP) + pr_warn("Could not stop watchdogs before kdump rc=%ld\n", rc); +} + /* * Affix a device for the first timer to the platform bus if * we have firmware support for the H_WATCHDOG hypercall. @@ -203,6 +214,9 @@ static __init int pseries_wdt_init(void) return PTR_ERR(pdev); } + if (crash_shutdown_register(pseries_crash_stop_watchdogs)) + pr_warn("Could not register watchdog crash shutdown handler\n"); + return 0; } machine_subsys_initcall(pseries, pseries_wdt_init); -- 2.52.0
