Skip to contentSkip to conversation

cpufreq: Boost related cleanups / fixes

PATCH In review Viresh Kumar 2 participants 7 messages Apr 24, 2025 – Apr 25, 2025 CPU frequency scaling framework

lore
Share & tools
lore

Viresh Kumar

author maintainer
#0 lore raw

v2 cover cpufreq: Boost related cleanups / fixes

Hello,

This series tries to fix boost related issues found recently.

The first patch fixes the boost related breakage introduced recently. It should be applied for v6.15-rc4.

The other four patches are general optimizations and fixes for boost handling in general. These can be applied to -rc or next merge window.

--
Viresh

V1->V2:
- Drop one patch.
- Fix the commit log of 1/5.
- Add Reviewed-by and Tested-by tags.

Viresh Kumar (5):
cpufreq: acpi: Re-sync CPU boost state on system resume
cpufreq: Don't unnecessarily call set_boost()
cpufreq: Introduce policy_set_boost()
cpufreq: Preserve policy's boost state after resume
cpufreq: Force sync policy boost with global boost on sysfs update

 drivers/cpufreq/acpi-cpufreq.c | 15 +++++++--
 drivers/cpufreq/cpufreq.c      | 58 ++++++++++++++++++++--------------
 2 files changed, 47 insertions(+), 26 deletions(-)
Signature · 1 line
2.31.1.272.g89b43f80a514
author maintainer
#1 lore raw

PATCH v2 1/5 cpufreq: acpi: Re-sync CPU boost state on system resume

During CPU hotunplug events (such as those occurring during suspend/resume cycles), platform firmware may modify the CPU boost state.

If boost was disabled prior to CPU removal, it correctly remains disabled upon re-plug. However, if firmware re-enables boost while the CPU is offline, the CPU may return with boost enabled—even if it was originally disabled—once it is hotplugged back in. This leads to inconsistent behavior and violates user or kernel policy expectations.

To maintain consistency, ensure the boost state is re-synchronized with the kernel policy when a CPU is hotplugged back in.

Note: This re-synchronization is not necessary during the initial call to ->init() for a CPU, as the cpufreq core handles it via cpufreq_online(). At that point, acpi_cpufreq_driver.boost_enabled is initialized to the value returned by boost_state(0).

Fixes 2b16c631832d ("cpufreq: ACPI: Remove set_boost in acpi_cpufreq_cpu_init()")
---
 drivers/cpufreq/acpi-cpufreq.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/cpufreq/acpi-cpufreq.c +13 -2
index 924314cdeebc..d26b610e4f24 100644
@@ -909,8 +909,19 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	if (perf->states[0].core_frequency * 1000 != freq_table[0].frequency)
 		pr_warn(FW_WARN "P-state 0 is not max freq\n");
 
-	if (acpi_cpufreq_driver.set_boost)
-		policy->boost_supported = true;
+	if (acpi_cpufreq_driver.set_boost) {
+		if (policy->boost_supported) {
+			/*
+			 * The firmware may have altered boost state while the
+			 * CPU was offline (for example during a suspend-resume
+			 * cycle).
+			 */
+			if (policy->boost_enabled != boost_state(cpu))
+				set_boost(policy, policy->boost_enabled);
+		} else {
+			policy->boost_supported = true;
+		}
+	}
 
 	return result;
 
Signature · 1 line
2.31.1.272.g89b43f80a514
#2 lore raw

Re: [PATCH V2 1/5] cpufreq: acpi: Re-sync CPU boost state on system resume

Quoted 19 lines · Viresh Kumar

During CPU hotunplug events (such as those occurring during suspend/resume cycles), platform firmware may modify the CPU boost state.

If boost was disabled prior to CPU removal, it correctly remains disabled upon re-plug. However, if firmware re-enables boost while the CPU is offline, the CPU may return with boost enabled—even if it was originally disabled—once it is hotplugged back in. This leads to inconsistent behavior and violates user or kernel policy expectations.

To maintain consistency, ensure the boost state is re-synchronized with the kernel policy when a CPU is hotplugged back in.

Note: This re-synchronization is not necessary during the initial call to ->init() for a CPU, as the cpufreq core handles it via cpufreq_online(). At that point, acpi_cpufreq_driver.boost_enabled is initialized to the value returned by boost_state(0).

Quoted 6 lines
Fixes 2b16c631832d ("cpufreq: ACPI: Remove set_boost in acpi_cpufreq_cpu_init()")

I gather that this patch is for 6.15 and the rest of the series is for 6.16, so applied accordingly.

Quoted 33 lines
---
 drivers/cpufreq/acpi-cpufreq.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/cpufreq/acpi-cpufreq.c +13 -3
index 924314cdeebc..d26b610e4f24 100644
@@ -909,8 +909,19 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        if (perf->states[0].core_frequency * 1000 != freq_table[0].frequency)
                pr_warn(FW_WARN "P-state 0 is not max freq\n");
 
-       if (acpi_cpufreq_driver.set_boost)
-               policy->boost_supported = true;
+       if (acpi_cpufreq_driver.set_boost) {
+               if (policy->boost_supported) {
+                       /*
+                        * The firmware may have altered boost state while the
+                        * CPU was offline (for example during a suspend-resume
+                        * cycle).
+                        */
+                       if (policy->boost_enabled != boost_state(cpu))
+                               set_boost(policy, policy->boost_enabled);
+               } else {
+                       policy->boost_supported = true;
+               }
+       }
 
        return result;
 
--

2.31.1.272.g89b43f80a514

author maintainer
#3 lore raw

PATCH v2 2/5 cpufreq: Don't unnecessarily call set_boost()

In reply to Viresh Kumar

The policy specific boost value may already be set correctly in cpufreq_boost_trigger_state(), don't update it again unnecessarily.

---
 drivers/cpufreq/cpufreq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/cpufreq.c +1 -1
index 3841c9da6cac..e31891c7b500 100644
@@ -2861,7 +2861,7 @@ static int cpufreq_boost_trigger_state(int state)
 
 	cpus_read_lock();
 	for_each_active_policy(policy) {
-		if (!policy->boost_supported)
+		if (!policy->boost_supported || policy->boost_enabled == state)
 			continue;
 
 		policy->boost_enabled = state;
Signature · 1 line
2.31.1.272.g89b43f80a514
author maintainer
#4 lore raw

PATCH v2 3/5 cpufreq: Introduce policy_set_boost()

In reply to Viresh Kumar

Introduce policy_set_boost() to update boost state of a cpufreq policy.

No intentional function change.

---
 drivers/cpufreq/cpufreq.c | 49 +++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 23 deletions(-)
drivers/cpufreq/cpufreq.c +26 -23
index e31891c7b500..24745088403b 100644
@@ -620,6 +620,22 @@ static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf)
 	return sysfs_emit(buf, "%d\n", policy->boost_enabled);
 }
 
+static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
+{
+	int ret;
+
+	if (policy->boost_enabled == enable)
+		return 0;
+
+	policy->boost_enabled = enable;
+
+	ret = cpufreq_driver->set_boost(policy, enable);
+	if (ret)
+		policy->boost_enabled = !policy->boost_enabled;
+
+	return ret;
+}
+
 static ssize_t store_local_boost(struct cpufreq_policy *policy,
 				 const char *buf, size_t count)
 {
@@ -635,21 +651,14 @@ static ssize_t store_local_boost(struct cpufreq_policy *policy,
 	if (!policy->boost_supported)
 		return -EINVAL;
 
-	if (policy->boost_enabled == enable)
-		return count;
-
-	policy->boost_enabled = enable;
-
 	cpus_read_lock();
-	ret = cpufreq_driver->set_boost(policy, enable);
+	ret = policy_set_boost(policy, enable);
 	cpus_read_unlock();
 
-	if (ret) {
-		policy->boost_enabled = !policy->boost_enabled;
-		return ret;
-	}
+	if (!ret)
+		return count;
 
-	return count;
+	return ret;
 }
 
 static struct freq_attr local_boost = __ATTR(boost, 0644, show_local_boost, store_local_boost);
@@ -1618,15 +1627,12 @@ static int cpufreq_online(unsigned int cpu)
 		policy->cdev = of_cpufreq_cooling_register(policy);
 
 	/* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
-	if (cpufreq_driver->set_boost && policy->boost_supported &&
-	    policy->boost_enabled != cpufreq_boost_enabled()) {
-		policy->boost_enabled = cpufreq_boost_enabled();
-		ret = cpufreq_driver->set_boost(policy, policy->boost_enabled);
+	if (cpufreq_driver->set_boost && policy->boost_supported) {
+		ret = policy_set_boost(policy, cpufreq_boost_enabled());
 		if (ret) {
 			/* If the set_boost fails, the online operation is not affected */
 			pr_info("%s: CPU%d: Cannot %s BOOST\n", __func__, policy->cpu,
-				str_enable_disable(policy->boost_enabled));
-			policy->boost_enabled = !policy->boost_enabled;
+				str_enable_disable(cpufreq_boost_enabled()));
 		}
 	}
 
@@ -2861,15 +2867,12 @@ static int cpufreq_boost_trigger_state(int state)
 
 	cpus_read_lock();
 	for_each_active_policy(policy) {
-		if (!policy->boost_supported || policy->boost_enabled == state)
+		if (!policy->boost_supported)
 			continue;
 
-		policy->boost_enabled = state;
-		ret = cpufreq_driver->set_boost(policy, state);
-		if (ret) {
-			policy->boost_enabled = !policy->boost_enabled;
+		ret = policy_set_boost(policy, state);
+		if (ret)
 			goto err_reset_state;
-		}
 	}
 	cpus_read_unlock();
 
Signature · 1 line
2.31.1.272.g89b43f80a514
author maintainer
#5 lore raw

PATCH v2 4/5 cpufreq: Preserve policy's boost state after resume

In reply to Viresh Kumar

If the global boost flag was enabled and policy boost flag was disabled before a suspend resume cycle, cpufreq_online() will enable the policy boost flag on resume.

While it is important for the policy boost flag to mirror the global boost flag when a policy is first created, it should be avoided when the policy is reinitialized (for example after a suspend resume cycle).

Though, if the global boost flag is disabled at this point of time, we want to make sure policy boost flag is disabled too.

---
 drivers/cpufreq/cpufreq.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/cpufreq/cpufreq.c +7 -2
index 24745088403b..0ad459bc8f84 100644
@@ -1626,8 +1626,13 @@ static int cpufreq_online(unsigned int cpu)
 	if (new_policy && cpufreq_thermal_control_enabled(cpufreq_driver))
 		policy->cdev = of_cpufreq_cooling_register(policy);
 
-	/* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
-	if (cpufreq_driver->set_boost && policy->boost_supported) {
+	/*
+	 * Let the per-policy boost flag mirror the cpufreq_driver boost during
+	 * initialization for a new policy. For an existing policy, maintain the
+	 * previous boost value unless global boost is disabled.
+	 */
+	if (cpufreq_driver->set_boost && policy->boost_supported &&
+	    (new_policy || !cpufreq_boost_enabled())) {
 		ret = policy_set_boost(policy, cpufreq_boost_enabled());
 		if (ret) {
 			/* If the set_boost fails, the online operation is not affected */
Signature · 1 line
2.31.1.272.g89b43f80a514
author maintainer
#6 lore raw

PATCH v2 5/5 cpufreq: Force sync policy boost with global boost on sysfs update

In reply to Viresh Kumar

If the global boost flag is enabled and policy boost flag is disabled, a call to cpufreq_boost_trigger_state(true) must enable the policy's boost state.

The current code misses that because of an optimization. Fix it.

---
 drivers/cpufreq/cpufreq.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/cpufreq/cpufreq.c +4 -2
index 0ad459bc8f84..4ac5d4fcfdd4 100644
@@ -2863,8 +2863,10 @@ static int cpufreq_boost_trigger_state(int state)
 	unsigned long flags;
 	int ret = 0;
 
-	if (cpufreq_driver->boost_enabled == state)
-		return 0;
+	/*
+	 * Don't compare 'cpufreq_driver->boost_enabled' with 'state' here to
+	 * make sure all policies are in sync with global boost flag.
+	 */
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver->boost_enabled = state;
Signature · 1 line
2.31.1.272.g89b43f80a514