[PATCH] cpufreq: Fix per-policy boost behavior after CPU hotplug

From: PoShao Chen
Date: Tue Jun 11 2024 - 08:01:36 EST


This patch fixes the behavior of the cpufreq boost when the
global boost flag is toggled during CPU hotplug offline. This action
previously led to incorrect scaling_max_freq values when the CPU was
brought back online. The issue also manifested as incorrect
scaling_cur_freq under the performance governor.

For example, after the following operations, even if the global boost
is disabled, the resulting scaling_max_freq and scaling_cur_freq
will still reflect the settings of an enabled boost.

$ echo performance > /sys/devices/system/cpu/cpufreq/policy7/scaling_governor
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3200000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3200000

$ echo 1 > /sys/devices/system/cpu/cpufreq/boost
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3250000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3250000

$ echo 0 > /sys/devices/system/cpu/cpu7/online
$ echo 0 > /sys/devices/system/cpu/cpufreq/boost
$ echo 1 > /sys/devices/system/cpu/cpu7/online
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3250000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3250000

Signed-off-by: PoShao Chen <poshao.chen@xxxxxxxxxxxx>
---
drivers/cpufreq/cpufreq.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a45aac17c20f..1f067d91a0b0 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1495,6 +1495,35 @@ static int cpufreq_online(unsigned int cpu)

blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_CREATE_POLICY, policy);
+ } else {
+ /*
+ * Call freq_qos_update_request() for the per-policy boost flag mirror
+ * the cpufreq_driver boost during hotplug online.
+ * Register an online callback if the default mirroring of the global
+ * boost setting is not intended.
+ */
+ if (!cpufreq_driver->online) {
+ ret = freq_qos_update_request(policy->max_freq_req, policy->max);
+ if (ret)
+ pr_err("%s: freq qos update failed\n", __func__);
+ } else {
+ /*
+ * Let the per-policy boost flag mirror the cpufreq_driver
+ * boost if an illegal state occurs after hotplug
+ */
+ if (policy->boost_enabled && !cpufreq_driver->boost_enabled) {
+ pr_info("%s: per-policy boost flag mirror the cpufreq_driver
+ boost\n", __func__);
+ policy->boost_enabled = cpufreq_driver->boost_enabled;
+ ret = cpufreq_driver->set_boost(policy,
+ cpufreq_driver->boost_enabled);
+ if (ret) {
+ policy->boost_enabled = !policy->boost_enabled;
+ pr_err("%s: per-policy boost flag mirror the cpufreq_driver
+ boost failed\n", __func__);
+ }
+ }
+ }
}

if (cpufreq_driver->get && has_target()) {
--
2.18.0