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 <[email protected]>
---
V1 -> V2: Adjusted log messages and fixed build error.
Link:
https://lore.kernel.org/all/[email protected]/
---
drivers/cpufreq/cpufreq.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a45aac17c20f..faadae05bc8a 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: local boost flag mirror the global 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: Failed to mirror the global boost flag\n",
+ __func__);
+ }
+ }
+ }
}
if (cpufreq_driver->get && has_target()) {
--
2.18.0
On 12-06-24, 11:31, PoShao Chen wrote:
> 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
Please try this instead:
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7c6879efe9ef..bd9fe2b0f032 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -43,6 +43,9 @@ static LIST_HEAD(cpufreq_policy_list);
#define for_each_inactive_policy(__policy) \
for_each_suitable_policy(__policy, false)
+#define for_each_policy(__policy) \
+ list_for_each_entry(__policy, &cpufreq_policy_list, policy_list)
+
/* Iterate over governors */
static LIST_HEAD(cpufreq_governor_list);
#define for_each_governor(__governor) \
@@ -2815,7 +2818,7 @@ int cpufreq_boost_trigger_state(int state)
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
cpus_read_lock();
- for_each_active_policy(policy) {
+ for_each_policy(policy) {
policy->boost_enabled = state;
ret = cpufreq_driver->set_boost(policy, state);
if (ret) {
--
viresh