Patch "watchdog/perf: adapt the watchdog_perf interface for async model" has been added to the 6.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    watchdog/perf: adapt the watchdog_perf interface for async model

to the 6.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     watchdog-perf-adapt-the-watchdog_perf-interface-for-.patch
and it can be found in the queue-6.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit ac2cc3f08048bd88f1829aa7a4abd3076ee9f4ba
Author: Lecopzer Chen <lecopzer.chen@xxxxxxxxxxxx>
Date:   Fri May 19 10:18:40 2023 -0700

    watchdog/perf: adapt the watchdog_perf interface for async model
    
    [ Upstream commit 930d8f8dbab97cb05dba30e67a2dfa0c6dbf4bc7 ]
    
    When lockup_detector_init()->watchdog_hardlockup_probe(), PMU may be not
    ready yet.  E.g.  on arm64, PMU is not ready until
    device_initcall(armv8_pmu_driver_init).  And it is deeply integrated with
    the driver model and cpuhp.  Hence it is hard to push this initialization
    before smp_init().
    
    But it is easy to take an opposite approach and try to initialize the
    watchdog once again later.  The delayed probe is called using workqueues.
    It need to allocate memory and must be proceed in a normal context.  The
    delayed probe is able to use if watchdog_hardlockup_probe() returns
    non-zero which means the return code returned when PMU is not ready yet.
    
    Provide an API - lockup_detector_retry_init() for anyone who needs to
    delayed init lockup detector if they had ever failed at
    lockup_detector_init().
    
    The original assumption is: nobody should use delayed probe after
    lockup_detector_check() which has __init attribute.  That is, anyone uses
    this API must call between lockup_detector_init() and
    lockup_detector_check(), and the caller must have __init attribute
    
    Link: https://lkml.kernel.org/r/20230519101840.v5.16.If4ad5dd5d09fb1309cebf8bcead4b6a5a7758ca7@changeid
    Reviewed-by: Petr Mladek <pmladek@xxxxxxxx>
    Co-developed-by: Pingfan Liu <kernelfans@xxxxxxxxx>
    Signed-off-by: Pingfan Liu <kernelfans@xxxxxxxxx>
    Signed-off-by: Lecopzer Chen <lecopzer.chen@xxxxxxxxxxxx>
    Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
    Suggested-by: Petr Mladek <pmladek@xxxxxxxx>
    Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
    Cc: Catalin Marinas <catalin.marinas@xxxxxxx>
    Cc: Chen-Yu Tsai <wens@xxxxxxxx>
    Cc: Christophe Leroy <christophe.leroy@xxxxxxxxxx>
    Cc: Colin Cross <ccross@xxxxxxxxxxx>
    Cc: Daniel Thompson <daniel.thompson@xxxxxxxxxx>
    Cc: "David S. Miller" <davem@xxxxxxxxxxxxx>
    Cc: Guenter Roeck <groeck@xxxxxxxxxxxx>
    Cc: Ian Rogers <irogers@xxxxxxxxxx>
    Cc: Marc Zyngier <maz@xxxxxxxxxx>
    Cc: Mark Rutland <mark.rutland@xxxxxxx>
    Cc: Masayoshi Mizuma <msys.mizuma@xxxxxxxxx>
    Cc: Matthias Kaehlcke <mka@xxxxxxxxxxxx>
    Cc: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
    Cc: Nicholas Piggin <npiggin@xxxxxxxxx>
    Cc: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
    Cc: "Ravi V. Shankar" <ravi.v.shankar@xxxxxxxxx>
    Cc: Ricardo Neri <ricardo.neri@xxxxxxxxx>
    Cc: Stephane Eranian <eranian@xxxxxxxxxx>
    Cc: Stephen Boyd <swboyd@xxxxxxxxxxxx>
    Cc: Sumit Garg <sumit.garg@xxxxxxxxxx>
    Cc: Tzung-Bi Shih <tzungbi@xxxxxxxxxxxx>
    Cc: Will Deacon <will@xxxxxxxxxx>
    Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
    Stable-dep-of: 9ec272c586b0 ("watchdog/hardlockup: keep kernel.nmi_watchdog sysctl as 0444 if probe fails")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index 600a61c65a9a9..c4f58baf7ccb2 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -13,6 +13,7 @@
 
 #ifdef CONFIG_LOCKUP_DETECTOR
 void lockup_detector_init(void);
+void lockup_detector_retry_init(void);
 void lockup_detector_soft_poweroff(void);
 void lockup_detector_cleanup(void);
 
@@ -32,6 +33,7 @@ extern int sysctl_hardlockup_all_cpu_backtrace;
 
 #else /* CONFIG_LOCKUP_DETECTOR */
 static inline void lockup_detector_init(void) { }
+static inline void lockup_detector_retry_init(void) { }
 static inline void lockup_detector_soft_poweroff(void) { }
 static inline void lockup_detector_cleanup(void) { }
 #endif /* !CONFIG_LOCKUP_DETECTOR */
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 06ea59c05ee94..f2e991894af62 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -175,7 +175,13 @@ void __weak watchdog_hardlockup_disable(unsigned int cpu)
 	hardlockup_detector_perf_disable();
 }
 
-/* Return 0, if a hardlockup watchdog is available. Error code otherwise */
+/*
+ * Watchdog-detector specific API.
+ *
+ * Return 0 when hardlockup watchdog is available, negative value otherwise.
+ * Note that the negative value means that a delayed probe might
+ * succeed later.
+ */
 int __weak __init watchdog_hardlockup_probe(void)
 {
 	return hardlockup_detector_perf_init();
@@ -904,6 +910,62 @@ static void __init watchdog_sysctl_init(void)
 #define watchdog_sysctl_init() do { } while (0)
 #endif /* CONFIG_SYSCTL */
 
+static void __init lockup_detector_delay_init(struct work_struct *work);
+static bool allow_lockup_detector_init_retry __initdata;
+
+static struct work_struct detector_work __initdata =
+		__WORK_INITIALIZER(detector_work, lockup_detector_delay_init);
+
+static void __init lockup_detector_delay_init(struct work_struct *work)
+{
+	int ret;
+
+	ret = watchdog_hardlockup_probe();
+	if (ret) {
+		pr_info("Delayed init of the lockup detector failed: %d\n", ret);
+		pr_info("Hard watchdog permanently disabled\n");
+		return;
+	}
+
+	allow_lockup_detector_init_retry = false;
+
+	watchdog_hardlockup_available = true;
+	lockup_detector_setup();
+}
+
+/*
+ * lockup_detector_retry_init - retry init lockup detector if possible.
+ *
+ * Retry hardlockup detector init. It is useful when it requires some
+ * functionality that has to be initialized later on a particular
+ * platform.
+ */
+void __init lockup_detector_retry_init(void)
+{
+	/* Must be called before late init calls */
+	if (!allow_lockup_detector_init_retry)
+		return;
+
+	schedule_work(&detector_work);
+}
+
+/*
+ * Ensure that optional delayed hardlockup init is proceed before
+ * the init code and memory is freed.
+ */
+static int __init lockup_detector_check(void)
+{
+	/* Prevent any later retry. */
+	allow_lockup_detector_init_retry = false;
+
+	/* Make sure no work is pending. */
+	flush_work(&detector_work);
+
+	return 0;
+
+}
+late_initcall_sync(lockup_detector_check);
+
 void __init lockup_detector_init(void)
 {
 	if (tick_nohz_full_enabled())
@@ -914,6 +976,9 @@ void __init lockup_detector_init(void)
 
 	if (!watchdog_hardlockup_probe())
 		watchdog_hardlockup_available = true;
+	else
+		allow_lockup_detector_init_retry = true;
+
 	lockup_detector_setup();
 	watchdog_sysctl_init();
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux