[PATCH 2/5] cpuidle: subscribe to global latency QoS notifiers

From: Yaxiong Tian

Date: Tue Jul 21 2026 - 05:29:43 EST


Register for CPU latency and wakeup latency QoS notifications and
bump a per-CPU generation counter when either aggregate constraint
changes. This prepares for caching the governor latency requirement
without introducing a direct qos-to-cpuidle call dependency.

Signed-off-by: Yaxiong Tian <tianyaxiong@xxxxxxxxxx>
---
drivers/cpuidle/governor.c | 58 ++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)

diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c
index 5d0e7f78c6c5..bc4a70d30c34 100644
--- a/drivers/cpuidle/governor.c
+++ b/drivers/cpuidle/governor.c
@@ -8,10 +8,13 @@
* This code is licenced under the GPL.
*/

+#include <linux/atomic.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
+#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/pm_qos.h>

#include "cpuidle.h"
@@ -22,6 +25,61 @@ LIST_HEAD(cpuidle_governors);
struct cpuidle_governor *cpuidle_curr_governor;
struct cpuidle_governor *cpuidle_prev_governor;

+/*
+ * Per-CPU generation bumped to invalidate that CPU's cached latency
+ * constraint. Consumers of the generation are added in later changes.
+ */
+static DEFINE_PER_CPU(atomic_t, latency_req_gen);
+
+static void cpuidle_latency_req_invalidate_cpu(unsigned int cpu)
+{
+ atomic_inc(per_cpu_ptr(&latency_req_gen, cpu));
+}
+
+static void cpuidle_latency_req_invalidate_all(void)
+{
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu)
+ cpuidle_latency_req_invalidate_cpu(cpu);
+}
+
+static int cpuidle_global_qos_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ cpuidle_latency_req_invalidate_all();
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cpuidle_latency_qos_nb = {
+ .notifier_call = cpuidle_global_qos_notify,
+};
+
+#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP
+static struct notifier_block cpuidle_wakeup_qos_nb = {
+ .notifier_call = cpuidle_global_qos_notify,
+};
+#endif
+
+static int __init cpuidle_latency_req_init(void)
+{
+ int ret;
+
+ ret = cpu_latency_qos_add_notifier(&cpuidle_latency_qos_nb);
+ if (ret)
+ return ret;
+
+#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP
+ ret = cpu_wakeup_latency_qos_add_notifier(&cpuidle_wakeup_qos_nb);
+ if (ret) {
+ cpu_latency_qos_remove_notifier(&cpuidle_latency_qos_nb);
+ return ret;
+ }
+#endif
+ return 0;
+}
+core_initcall(cpuidle_latency_req_init);
+
/**
* cpuidle_find_governor - finds a governor of the specified name
* @str: the name
--
2.43.0