* [PATCH 0/6] cpufreq: Introduce boost frequency QoS
@ 2026-01-26 10:18 Pierre Gondois
2026-01-26 10:18 ` [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint Pierre Gondois
` (5 more replies)
0 siblings, 6 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
The Power Management Quality of Service (PM QoS) allows to
aggregate constraints from multiple entities. It is currently
used to manage the min/max frequency of a given policy.
Frequency constraints can come from:
- Thermal framework: acpi_thermal_cpufreq_init()
- Firmware: _PPC objects: acpi_processor_ppc_init()
- User: by setting policyX/scaling_[min|max]_freq
The minimum of the max frequency constraints is used to compute
the resulting maximum allowed frequency.
When enabling boost frequencies, the same frequency request object
(policy->max_freq_req) as to handle requests from users is used.
As a result, when setting:
- scaling_max_freq
- boost
The last sysfs file used overwrites the request from the other
sysfs file.
To avoid this:
1. Create a per-policy boost_freq_req to save the boost
constraints instead of overwriting the last scaling_max_freq
constraint.
2. policy_set_boost() calls the cpufreq set_boost callback.
Update the newly added boost_freq_req request from there:
- whenever boost is toggled
- to cover all possible paths
3. In the existing set_boost() callbacks:
- Don't update policy->max as this is done through the qos notifier
cpufreq_notifier_max() which calls cpufreq_set_policy().
- Remove freq_qos_update_request() calls as the qos request is now
done in policy_set_boost() and updates the new boost_freq_req
This patch-set additionally does:
- if a driver .init() callback sets policy->min and policy->max,
these values are used are min/max_freq_req QoS constraints
- Remove policy->min and policy->max initialization in .init()
callback if the value is identical to cpuinfo.min/max_freq
- RFC: allow decreasing cpuinfo.max_freq when using freq_table.
------------
E.g.:
On a Juno with available frequencies: 600.000, 1.000.000
Boost frequencies: 1.200.000
Using the cppc-cpufreq driver.
---
Without the patches:
# ## Init state
scaling_max_freq:1000000
cpuinfo_max_freq:1000000
# echo 700000 > scaling_max_freq
scaling_max_freq:700000
cpuinfo_max_freq:1000000
# echo 1 > ../boost
scaling_max_freq:1200000
cpuinfo_max_freq:1200000
# echo 800000 > scaling_max_freq
scaling_max_freq:800000
cpuinfo_max_freq:1200000
# echo 0 > ../boost
scaling_max_freq:1000000
cpuinfo_max_freq:1000000
---
With the patches:
# ## Init
scaling_max_freq:1000000
cpuinfo_max_freq:1000000
# echo 700000 > scaling_max_freq
scaling_max_freq:700000
cpuinfo_max_freq:1000000
# echo 1 > ../boost
scaling_max_freq:700000
cpuinfo_max_freq:1200000
# echo 800000 > scaling_max_freq
scaling_max_freq:800000
cpuinfo_max_freq:1200000
# echo 0 > ../boost
scaling_max_freq:800000
cpuinfo_max_freq:1000000
---
With the patches, the maximum scaling frequency requested is
conserved even though boosting is enabled/disabled.
---
v1: https://lore.kernel.org/all/20251204101344.192678-1-pierre.gondois@arm.com/#t
v2: https://lore.kernel.org/all/20251208105933.1369125-1-pierre.gondois@arm.com/#t
Changes:
- Fixed error path
- Integrated [PATCH 1/4] Revert "cpufreq: Fix re-boost issue after hotplugging a CPU"
to another patch
v3:
Changes:
- Fixed error path
- Extracted the revert of:
"cpufreq: Fix re-boost issue after hotplugging a CPU"
for clarity purpose
- Set cpuinfo.max_freq as a max_freq_req QoS constraint by default
New patches:
- "cpufreq: Allow decreasing cpuinfo.max_freq"
- "cpufreq: Set policy->min and max as QoS constraints"
Pierre Gondois (6):
cpufreq: Remove per-CPU QoS constraint
cpufreq: Add boost_freq_req QoS request
cpufreq: Centralize boost freq QoS requests
cpufreq: Update .set_boost() callbacks to rely on boost_freq_req
cpufreq: Set policy->min and max as real QoS constraints
cpufreq/freq_table: Allow decreasing cpuinfo.max_freq
drivers/cpufreq/acpi-cpufreq.c | 1 +
drivers/cpufreq/amd-pstate.c | 26 +++++----
drivers/cpufreq/cppc_cpufreq.c | 10 +---
drivers/cpufreq/cpufreq-nforce2.c | 4 +-
drivers/cpufreq/cpufreq.c | 87 +++++++++++++++++++++++--------
drivers/cpufreq/freq_table.c | 14 ++---
drivers/cpufreq/gx-suspmod.c | 9 ++--
drivers/cpufreq/intel_pstate.c | 3 --
drivers/cpufreq/pcc-cpufreq.c | 8 +--
drivers/cpufreq/pxa3xx-cpufreq.c | 4 +-
drivers/cpufreq/virtual-cpufreq.c | 6 +--
include/linux/cpufreq.h | 1 +
12 files changed, 101 insertions(+), 72 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
2026-01-31 3:28 ` zhenglifeng (A)
2026-01-26 10:18 ` [PATCH 2/6] cpufreq: Add boost_freq_req QoS request Pierre Gondois
` (4 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
policy->max_freq_req represents the maximum allowed frequency as
requested by the policyX/scaling_max_freq sysfs file. This request
applies to all CPUs of the policy. It is not possible to request
a per-CPU maximum frequency.
Thus, the interaction between the policy boost and scaling_max_freq
settings should be handled by adding a boost specific QoS constraint.
This will be handled in the following patches.
This patch reverts of:
commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
a CPU")
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/cpufreq.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 4472bb1ec83c7..db414c052658b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1481,10 +1481,6 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_CREATE_POLICY, policy);
- } else {
- ret = freq_qos_update_request(policy->max_freq_req, policy->max);
- if (ret < 0)
- goto out_destroy_policy;
}
if (cpufreq_driver->get && has_target()) {
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/6] cpufreq: Add boost_freq_req QoS request
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
2026-01-26 10:18 ` [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
2026-01-31 4:00 ` zhenglifeng (A)
2026-01-26 10:18 ` [PATCH 3/6] cpufreq: Centralize boost freq QoS requests Pierre Gondois
` (3 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
The Power Management Quality of Service (PM QoS) allows to
aggregate constraints from multiple entities. It is currently
used to manage the min/max frequency of a given policy.
Frequency constraints can come for instance from:
- Thermal framework: acpi_thermal_cpufreq_init()
- Firmware: _PPC objects: acpi_processor_ppc_init()
- User: by setting policyX/scaling_[min|max]_freq
The minimum of the max frequency constraints is used to compute
the resulting maximum allowed frequency.
When enabling boost frequencies, the same frequency request object
(policy->max_freq_req) as to handle requests from users is used.
As a result, when setting:
- scaling_max_freq
- boost
The last sysfs file used overwrites the request from the other
sysfs file.
To avoid this, create a per-policy boost_freq_req to save the boost
constraints instead of overwriting the last scaling_max_freq
constraint.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/cpufreq.c | 40 ++++++++++++++++++++++++++++++++++-----
include/linux/cpufreq.h | 1 +
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index db414c052658b..c8fb4c6656e94 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1359,17 +1359,24 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
/* Cancel any pending policy->update work before freeing the policy. */
cancel_work_sync(&policy->update);
- if (policy->max_freq_req) {
+ if (policy->max_freq_req || policy->boost_freq_req) {
/*
- * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY
- * notification, since CPUFREQ_CREATE_POLICY notification was
- * sent after adding max_freq_req earlier.
+ * Remove max/boost _freq_req after sending CPUFREQ_REMOVE_POLICY
+ * notification, since CPUFREQ_CREATE_POLICY notification was sent
+ * after adding max/boost _freq_req earlier.
*/
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_REMOVE_POLICY, policy);
- freq_qos_remove_request(policy->max_freq_req);
}
+ if (policy->boost_freq_req) {
+ freq_qos_remove_request(policy->boost_freq_req);
+ kfree(policy->boost_freq_req);
+ }
+
+ if (policy->max_freq_req)
+ freq_qos_remove_request(policy->max_freq_req);
+
freq_qos_remove_request(policy->min_freq_req);
kfree(policy->min_freq_req);
@@ -1479,6 +1486,29 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
goto out_destroy_policy;
}
+ if (policy->boost_supported) {
+ policy->boost_freq_req = kzalloc(sizeof(*policy->boost_freq_req),
+ GFP_KERNEL);
+ if (!policy->boost_freq_req) {
+ ret = -ENOMEM;
+ goto out_destroy_policy;
+ }
+
+ ret = freq_qos_add_request(&policy->constraints,
+ policy->boost_freq_req,
+ FREQ_QOS_MAX,
+ FREQ_QOS_MAX_DEFAULT_VALUE);
+ if (ret < 0) {
+ /*
+ * So we don't call freq_qos_remove_request() for an
+ * uninitialized request.
+ */
+ kfree(policy->boost_freq_req);
+ policy->boost_freq_req = NULL;
+ goto out_destroy_policy;
+ }
+ }
+
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_CREATE_POLICY, policy);
}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 0465d1e6f72ac..c292a6a19e4f5 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -81,6 +81,7 @@ struct cpufreq_policy {
struct freq_constraints constraints;
struct freq_qos_request *min_freq_req;
struct freq_qos_request *max_freq_req;
+ struct freq_qos_request *boost_freq_req;
struct cpufreq_frequency_table *freq_table;
enum cpufreq_table_sorting freq_table_sorted;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/6] cpufreq: Centralize boost freq QoS requests
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
2026-01-26 10:18 ` [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint Pierre Gondois
2026-01-26 10:18 ` [PATCH 2/6] cpufreq: Add boost_freq_req QoS request Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
2026-01-31 4:11 ` zhenglifeng (A)
2026-01-26 10:18 ` [PATCH 4/6] cpufreq: Update .set_boost() callbacks to rely on boost_freq_req Pierre Gondois
` (2 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
policy_set_boost() calls the cpufreq set_boost callback.
Update the newly added boost_freq_req request from there:
- whenever boost is toggled
- to cover all possible paths
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/cpufreq.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c8fb4c6656e94..505da5b00e575 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -603,10 +603,19 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
policy->boost_enabled = enable;
ret = cpufreq_driver->set_boost(policy, enable);
- if (ret)
+ if (ret) {
policy->boost_enabled = !policy->boost_enabled;
+ return ret;
+ }
- return ret;
+ ret = freq_qos_update_request(policy->boost_freq_req, policy->cpuinfo.max_freq);
+ if (ret < 0) {
+ policy->boost_enabled = !policy->boost_enabled;
+ cpufreq_driver->set_boost(policy, !policy->boost_enabled);
+ return ret;
+ }
+
+ return 0;
}
static ssize_t store_local_boost(struct cpufreq_policy *policy,
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/6] cpufreq: Update .set_boost() callbacks to rely on boost_freq_req
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
` (2 preceding siblings ...)
2026-01-26 10:18 ` [PATCH 3/6] cpufreq: Centralize boost freq QoS requests Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
2026-01-26 10:18 ` [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints Pierre Gondois
2026-01-26 10:18 ` [RFC PATCH 6/6] cpufreq/freq_table: Allow decreasing cpuinfo.max_freq Pierre Gondois
5 siblings, 0 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
In the existing .set_boost() callbacks:
- Don't update policy->max as this is done through the qos notifier
cpufreq_notifier_max() which calls cpufreq_set_policy().
- Remove freq_qos_update_request() calls as the qos request is now
done in policy_set_boost() and updates the new boost_freq_req
Note:
cpufreq_frequency_table_cpuinfo() is also called through:
cpufreq_policy_online()
\-cpufreq_table_validate_and_sort()
\-cpufreq_frequency_table_cpuinfo()
which relies on cpufreq_frequency_table_cpuinfo() to set
policy->min and max initizalization at driver init. This
regression is solved in the next patch.
Note2:
acpi-cpufreq.c seems to be the only cpufreq driver not
setting cpuinfo.max_freq. Populate it the nominal frequency at
driver init.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/acpi-cpufreq.c | 1 +
drivers/cpufreq/amd-pstate.c | 2 --
drivers/cpufreq/cppc_cpufreq.c | 10 ++--------
drivers/cpufreq/cpufreq.c | 16 +++++++---------
drivers/cpufreq/freq_table.c | 7 +++----
5 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index e73a66785d69d..6a6e26e1be14a 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -857,6 +857,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
* governor from selecting inadequate CPU frequencies.
*/
arch_set_max_freq_ratio(true);
+ policy->cpuinfo.max_freq = nominal_freq;
}
policy->freq_table = freq_table;
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index c45bc98721d24..310d5938cbdf6 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -756,8 +756,6 @@ static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
else if (policy->cpuinfo.max_freq > nominal_freq)
policy->cpuinfo.max_freq = nominal_freq;
- policy->max = policy->cpuinfo.max_freq;
-
if (cppc_state == AMD_PSTATE_PASSIVE) {
ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
if (ret < 0)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 9eac77c4f2944..4c46c7ea318eb 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -775,17 +775,11 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
struct cppc_perf_caps *caps = &cpu_data->perf_caps;
- int ret;
if (state)
- policy->max = cppc_perf_to_khz(caps, caps->highest_perf);
+ policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->highest_perf);
else
- policy->max = cppc_perf_to_khz(caps, caps->nominal_perf);
- policy->cpuinfo.max_freq = policy->max;
-
- ret = freq_qos_update_request(policy->max_freq_req, policy->max);
- if (ret < 0)
- return ret;
+ policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, caps->nominal_perf);
return 0;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 505da5b00e575..43bf6aed90e49 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1503,10 +1503,14 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
goto out_destroy_policy;
}
+ /*
+ * If boost is supported,
+ * init the constraint with cpuinfo.max_freq.
+ */
ret = freq_qos_add_request(&policy->constraints,
policy->boost_freq_req,
FREQ_QOS_MAX,
- FREQ_QOS_MAX_DEFAULT_VALUE);
+ policy->cpuinfo.max_freq);
if (ret < 0) {
/*
* So we don't call freq_qos_remove_request() for an
@@ -2821,16 +2825,10 @@ int cpufreq_boost_set_sw(struct cpufreq_policy *policy, int state)
return -ENXIO;
ret = cpufreq_frequency_table_cpuinfo(policy);
- if (ret) {
+ if (ret)
pr_err("%s: Policy frequency update failed\n", __func__);
- return ret;
- }
- ret = freq_qos_update_request(policy->max_freq_req, policy->max);
- if (ret < 0)
- return ret;
-
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_boost_set_sw);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 7f251daf03ce3..9b37f37c36389 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -49,16 +49,15 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
max_freq = freq;
}
- policy->min = policy->cpuinfo.min_freq = min_freq;
- policy->max = max_freq;
+ policy->cpuinfo.min_freq = min_freq;
/*
* If the driver has set its own cpuinfo.max_freq above max_freq, leave
* it as is.
*/
if (policy->cpuinfo.max_freq < max_freq)
- policy->max = policy->cpuinfo.max_freq = max_freq;
+ policy->cpuinfo.max_freq = max_freq;
- if (policy->min == ~0)
+ if (min_freq == ~0)
return -EINVAL;
else
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
` (3 preceding siblings ...)
2026-01-26 10:18 ` [PATCH 4/6] cpufreq: Update .set_boost() callbacks to rely on boost_freq_req Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
2026-01-29 6:02 ` kernel test robot
2026-01-29 9:52 ` kernel test robot
2026-01-26 10:18 ` [RFC PATCH 6/6] cpufreq/freq_table: Allow decreasing cpuinfo.max_freq Pierre Gondois
5 siblings, 2 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
cpufreq_set_policy() will ultimately override the policy min/max
values written in the .init() callback through:
cpufreq_policy_online()
\-cpufreq_init_policy()
\-cpufreq_set_policy()
\-/* Set policy->min/max */
Thus the policy min/max values provided are only temporary.
There is an exception if CPUFREQ_NEED_INITIAL_FREQ_CHECK is set and:
cpufreq_policy_online()
\-cpufreq_init_policy()
\-__cpufreq_driver_target()
\-cpufreq_driver->target()
is called. In this case, some drivers use the policy min/max
values in their .target() callback before they are overridden.
Check cpufreq drivers:
- if their .target() callback doesn't use policy->min or max,
remove the initialization
- assuming policy->min or max values were populated as constraints,
set them as QoS real constraints in cpufreq_policy_online()
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/amd-pstate.c | 24 ++++++++++++------------
drivers/cpufreq/cpufreq-nforce2.c | 4 ++--
drivers/cpufreq/cpufreq.c | 16 ++++++++++++++--
drivers/cpufreq/gx-suspmod.c | 9 ++++-----
drivers/cpufreq/intel_pstate.c | 3 ---
drivers/cpufreq/pcc-cpufreq.c | 8 ++++----
drivers/cpufreq/pxa3xx-cpufreq.c | 4 ++--
drivers/cpufreq/virtual-cpufreq.c | 6 +++---
8 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 310d5938cbdf6..aaafbe9b26cae 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1003,12 +1003,12 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
perf = READ_ONCE(cpudata->perf);
- policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
- cpudata->nominal_freq,
- perf.lowest_perf);
- policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf,
- cpudata->nominal_freq,
- perf.highest_perf);
+ policy->cpuinfo.min_freq = perf_to_freq(perf,
+ cpudata->nominal_freq,
+ perf.lowest_perf);
+ policy->cpuinfo.max_freq = perf_to_freq(perf,
+ cpudata->nominal_freq,
+ perf.highest_perf);
ret = amd_pstate_cppc_enable(policy);
if (ret)
@@ -1485,12 +1485,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
perf = READ_ONCE(cpudata->perf);
- policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
- cpudata->nominal_freq,
- perf.lowest_perf);
- policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf,
- cpudata->nominal_freq,
- perf.highest_perf);
+ policy->cpuinfo.min_freq = perf_to_freq(perf,
+ cpudata->nominal_freq,
+ perf.lowest_perf);
+ policy->cpuinfo.max_freq = perf_to_freq(perf,
+ cpudata->nominal_freq,
+ perf.highest_perf);
policy->driver_data = cpudata;
ret = amd_pstate_cppc_enable(policy);
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c
index fbbbe501cf2dc..831102522ad64 100644
--- a/drivers/cpufreq/cpufreq-nforce2.c
+++ b/drivers/cpufreq/cpufreq-nforce2.c
@@ -355,8 +355,8 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
min_fsb = NFORCE2_MIN_FSB;
/* cpuinfo and default policy values */
- policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100;
- policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100;
+ policy->cpuinfo.min_freq = min_fsb * fid * 100;
+ policy->cpuinfo.max_freq = max_fsb * fid * 100;
return 0;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 43bf6aed90e49..209e2673ca50b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1455,6 +1455,18 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
if (new_policy) {
+ unsigned int min, max;
+
+ /*
+ * If the driver has set policy->min or max,
+ * use the value as a QoS request.
+ */
+ min = max(FREQ_QOS_MIN_DEFAULT_VALUE, policy->min);
+ if (policy->max)
+ max = min(FREQ_QOS_MAX_DEFAULT_VALUE, policy->max);
+ else
+ max = FREQ_QOS_MAX_DEFAULT_VALUE;
+
for_each_cpu(j, policy->related_cpus) {
per_cpu(cpufreq_cpu_data, j) = policy;
add_cpu_dev_symlink(policy, j, get_cpu_device(j));
@@ -1469,7 +1481,7 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
ret = freq_qos_add_request(&policy->constraints,
policy->min_freq_req, FREQ_QOS_MIN,
- FREQ_QOS_MIN_DEFAULT_VALUE);
+ min);
if (ret < 0) {
/*
* So we don't call freq_qos_remove_request() for an
@@ -1489,7 +1501,7 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
ret = freq_qos_add_request(&policy->constraints,
policy->max_freq_req, FREQ_QOS_MAX,
- FREQ_QOS_MAX_DEFAULT_VALUE);
+ max);
if (ret < 0) {
policy->max_freq_req = NULL;
goto out_destroy_policy;
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c
index 75b3ef7ec6796..57999b8d51fa2 100644
--- a/drivers/cpufreq/gx-suspmod.c
+++ b/drivers/cpufreq/gx-suspmod.c
@@ -397,7 +397,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
{
- unsigned int maxfreq;
+ unsigned int minfreq, maxfreq;
if (!policy || policy->cpu != 0)
return -ENODEV;
@@ -418,11 +418,10 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
policy->cpu = 0;
if (max_duration < POLICY_MIN_DIV)
- policy->min = maxfreq / max_duration;
+ minfreq = maxfreq / max_duration;
else
- policy->min = maxfreq / POLICY_MIN_DIV;
- policy->max = maxfreq;
- policy->cpuinfo.min_freq = maxfreq / max_duration;
+ minfreq = maxfreq / POLICY_MIN_DIV;
+ policy->cpuinfo.min_freq = minfreq;
policy->cpuinfo.max_freq = maxfreq;
return 0;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index ec4abe3745736..bf2f7524d04a9 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -3047,9 +3047,6 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
- policy->min = policy->cpuinfo.min_freq;
- policy->max = policy->cpuinfo.max_freq;
-
intel_pstate_init_acpi_perf_limits(policy);
policy->fast_switch_possible = true;
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index ac2e90a65f0c4..231edfe8cabaa 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -551,13 +551,13 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
goto out;
}
- policy->max = policy->cpuinfo.max_freq =
+ policy->cpuinfo.max_freq =
ioread32(&pcch_hdr->nominal) * 1000;
- policy->min = policy->cpuinfo.min_freq =
+ policy->cpuinfo.min_freq =
ioread32(&pcch_hdr->minimum_frequency) * 1000;
- pr_debug("init: policy->max is %d, policy->min is %d\n",
- policy->max, policy->min);
+ pr_debug("init: max_freq is %d, min_freq is %d\n",
+ policy->cpuinfo.max_freq, policy->cpuinfo.min_freq);
out:
return result;
}
diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index 4afa48d172dbe..f53b9d7edc76a 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -185,8 +185,8 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
int ret = -EINVAL;
/* set default policy and cpuinfo */
- policy->min = policy->cpuinfo.min_freq = 104000;
- policy->max = policy->cpuinfo.max_freq =
+ policy->cpuinfo.min_freq = 104000;
+ policy->cpuinfo.max_freq =
(cpu_is_pxa320()) ? 806000 : 624000;
policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
diff --git a/drivers/cpufreq/virtual-cpufreq.c b/drivers/cpufreq/virtual-cpufreq.c
index 6ffa16d239b2b..6f7dbef7fda96 100644
--- a/drivers/cpufreq/virtual-cpufreq.c
+++ b/drivers/cpufreq/virtual-cpufreq.c
@@ -164,10 +164,10 @@ static int virt_cpufreq_get_freq_info(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = 1;
policy->cpuinfo.max_freq = virt_cpufreq_get_perftbl_entry(policy->cpu, 0);
- policy->min = policy->cpuinfo.min_freq;
- policy->max = policy->cpuinfo.max_freq;
+ policy->cpuinfo.min_freq;
+ policy->cpuinfo.max_freq;
- policy->cur = policy->max;
+ policy->cur = policy->cpuinfo.max_freq;
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC PATCH 6/6] cpufreq/freq_table: Allow decreasing cpuinfo.max_freq
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
` (4 preceding siblings ...)
2026-01-26 10:18 ` [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints Pierre Gondois
@ 2026-01-26 10:18 ` Pierre Gondois
5 siblings, 0 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-01-26 10:18 UTC (permalink / raw)
To: linux-kernel
Cc: Jie Zhan, zhenglifeng1, Ionela Voinescu, Christian Loehle, sumitg,
Pierre Gondois, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Srinivas Pandruvada, Len Brown, Saravana Kannan, linux-pm
Drivers not using freq. tables update cpuinfo.max_freq in their
.set_boost() callback. E.g. amd-pstate, cppc_cpufreq.
Drivers relying on freq. tables and supporting boost frequencies
rely on cpufreq_frequency_table_cpuinfo(). cpuinfo.max_freq is
only updated if the new maximal value is higher than the previous
one.
Using the scmi-cpufreq driver which relies on freq. tables, enabling
boost will permanently increases the cpuinfo.max_freq value.
This patch allows to lower cpuinfo.max_freq.
Note:
commit 538b0188da46 ("cpufreq: ACPI: Set cpuinfo.max_freq directly
if max boost is known")
favored having cpuinfo.max_freq reporting the maximal boosted
frequency of a CPU instead of the maximal reachable frequency
due to regressions in the frequency reported by cpuinfo.max
and scaling_cur_freq.
As stated above, this is not what most of the other cpufreq driver
do. I assume that the following patch:
commit 3c55e94c0ade ("cpufreq: ACPI: Extend frequency tables to
cover boost frequencies")
was correct, but might not have tagged the boosted frequency with
the CPUFREQ_BOOST_FREQ flag in the freq. table.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
drivers/cpufreq/freq_table.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 9b37f37c36389..bd08cbe9e9ba3 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -50,12 +50,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
}
policy->cpuinfo.min_freq = min_freq;
- /*
- * If the driver has set its own cpuinfo.max_freq above max_freq, leave
- * it as is.
- */
- if (policy->cpuinfo.max_freq < max_freq)
- policy->cpuinfo.max_freq = max_freq;
+ policy->cpuinfo.max_freq = max_freq;
if (min_freq == ~0)
return -EINVAL;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints
2026-01-26 10:18 ` [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints Pierre Gondois
@ 2026-01-29 6:02 ` kernel test robot
2026-01-29 9:52 ` kernel test robot
1 sibling, 0 replies; 16+ messages in thread
From: kernel test robot @ 2026-01-29 6:02 UTC (permalink / raw)
To: Pierre Gondois, linux-kernel
Cc: llvm, oe-kbuild-all, Jie Zhan, zhenglifeng1, Ionela Voinescu,
Christian Loehle, sumitg, Pierre Gondois, Rafael J. Wysocki,
Viresh Kumar, Huang Rui, Gautham R. Shenoy, Mario Limonciello,
Perry Yuan, Srinivas Pandruvada, Len Brown, Saravana Kannan,
linux-pm
Hi Pierre,
kernel test robot noticed the following build warnings:
[auto build test WARNING on rafael-pm/linux-next]
[also build test WARNING on rafael-pm/bleeding-edge linus/master v6.19-rc7 next-20260128]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Pierre-Gondois/cpufreq-Remove-per-CPU-QoS-constraint/20260126-182440
base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link: https://lore.kernel.org/r/20260126101826.94030-6-pierre.gondois%40arm.com
patch subject: [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20260129/202601291343.bghsD4zH-lkp@intel.com/config)
compiler: clang version 16.0.6 (https://github.com/llvm/llvm-project 7cbf1a2591520c2491aa35339f227775f4d3adf6)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260129/202601291343.bghsD4zH-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601291343.bghsD4zH-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/cpufreq/virtual-cpufreq.c:167:19: warning: expression result unused [-Wunused-value]
policy->cpuinfo.min_freq;
~~~~~~~~~~~~~~~ ^~~~~~~~
drivers/cpufreq/virtual-cpufreq.c:168:19: warning: expression result unused [-Wunused-value]
policy->cpuinfo.max_freq;
~~~~~~~~~~~~~~~ ^~~~~~~~
2 warnings generated.
vim +167 drivers/cpufreq/virtual-cpufreq.c
155
156 static int virt_cpufreq_get_freq_info(struct cpufreq_policy *policy)
157 {
158 struct cpufreq_frequency_table *table;
159 u32 num_perftbl_entries, idx;
160
161 num_perftbl_entries = per_cpu(perftbl_num_entries, policy->cpu);
162
163 if (num_perftbl_entries == 1) {
164 policy->cpuinfo.min_freq = 1;
165 policy->cpuinfo.max_freq = virt_cpufreq_get_perftbl_entry(policy->cpu, 0);
166
> 167 policy->cpuinfo.min_freq;
168 policy->cpuinfo.max_freq;
169
170 policy->cur = policy->cpuinfo.max_freq;
171 return 0;
172 }
173
174 table = kcalloc(num_perftbl_entries + 1, sizeof(*table), GFP_KERNEL);
175 if (!table)
176 return -ENOMEM;
177
178 for (idx = 0; idx < num_perftbl_entries; idx++)
179 table[idx].frequency = virt_cpufreq_get_perftbl_entry(policy->cpu, idx);
180
181 table[idx].frequency = CPUFREQ_TABLE_END;
182 policy->freq_table = table;
183
184 return 0;
185 }
186
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints
2026-01-26 10:18 ` [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints Pierre Gondois
2026-01-29 6:02 ` kernel test robot
@ 2026-01-29 9:52 ` kernel test robot
1 sibling, 0 replies; 16+ messages in thread
From: kernel test robot @ 2026-01-29 9:52 UTC (permalink / raw)
To: Pierre Gondois, linux-kernel
Cc: oe-kbuild-all, Jie Zhan, zhenglifeng1, Ionela Voinescu,
Christian Loehle, sumitg, Pierre Gondois, Rafael J. Wysocki,
Viresh Kumar, Huang Rui, Gautham R. Shenoy, Mario Limonciello,
Perry Yuan, Srinivas Pandruvada, Len Brown, Saravana Kannan,
linux-pm
Hi Pierre,
kernel test robot noticed the following build warnings:
[auto build test WARNING on rafael-pm/linux-next]
[also build test WARNING on rafael-pm/bleeding-edge linus/master v6.19-rc7 next-20260128]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Pierre-Gondois/cpufreq-Remove-per-CPU-QoS-constraint/20260126-182440
base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link: https://lore.kernel.org/r/20260126101826.94030-6-pierre.gondois%40arm.com
patch subject: [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20260129/202601291700.LY8K4K9v-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260129/202601291700.LY8K4K9v-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601291700.LY8K4K9v-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/cpufreq/virtual-cpufreq.c: In function 'virt_cpufreq_get_freq_info':
>> drivers/cpufreq/virtual-cpufreq.c:167:32: warning: statement with no effect [-Wunused-value]
167 | policy->cpuinfo.min_freq;
| ~~~~~~~~~~~~~~~^~~~~~~~~
drivers/cpufreq/virtual-cpufreq.c:168:32: warning: statement with no effect [-Wunused-value]
168 | policy->cpuinfo.max_freq;
| ~~~~~~~~~~~~~~~^~~~~~~~~
vim +167 drivers/cpufreq/virtual-cpufreq.c
155
156 static int virt_cpufreq_get_freq_info(struct cpufreq_policy *policy)
157 {
158 struct cpufreq_frequency_table *table;
159 u32 num_perftbl_entries, idx;
160
161 num_perftbl_entries = per_cpu(perftbl_num_entries, policy->cpu);
162
163 if (num_perftbl_entries == 1) {
164 policy->cpuinfo.min_freq = 1;
165 policy->cpuinfo.max_freq = virt_cpufreq_get_perftbl_entry(policy->cpu, 0);
166
> 167 policy->cpuinfo.min_freq;
168 policy->cpuinfo.max_freq;
169
170 policy->cur = policy->cpuinfo.max_freq;
171 return 0;
172 }
173
174 table = kcalloc(num_perftbl_entries + 1, sizeof(*table), GFP_KERNEL);
175 if (!table)
176 return -ENOMEM;
177
178 for (idx = 0; idx < num_perftbl_entries; idx++)
179 table[idx].frequency = virt_cpufreq_get_perftbl_entry(policy->cpu, idx);
180
181 table[idx].frequency = CPUFREQ_TABLE_END;
182 policy->freq_table = table;
183
184 return 0;
185 }
186
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint
2026-01-26 10:18 ` [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint Pierre Gondois
@ 2026-01-31 3:28 ` zhenglifeng (A)
2026-02-05 13:59 ` Pierre Gondois
0 siblings, 1 reply; 16+ messages in thread
From: zhenglifeng (A) @ 2026-01-31 3:28 UTC (permalink / raw)
To: Pierre Gondois
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm, linux-kernel
On 2026/1/26 18:18, Pierre Gondois wrote:
> policy->max_freq_req represents the maximum allowed frequency as
> requested by the policyX/scaling_max_freq sysfs file. This request
> applies to all CPUs of the policy. It is not possible to request
> a per-CPU maximum frequency.
>
> Thus, the interaction between the policy boost and scaling_max_freq
> settings should be handled by adding a boost specific QoS constraint.
> This will be handled in the following patches.
>
> This patch reverts of:
> commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
> a CPU")
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/cpufreq/cpufreq.c | 4 ----
> 1 file changed, 4 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 4472bb1ec83c7..db414c052658b 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1481,10 +1481,6 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>
> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
> CPUFREQ_CREATE_POLICY, policy);
> - } else {
> - ret = freq_qos_update_request(policy->max_freq_req, policy->max);
> - if (ret < 0)
> - goto out_destroy_policy;
I think this shouldn't be the first patch. This can be removed only after
adding boost_freq_req, otherwise it's letting the problem out again.
> }
>
> if (cpufreq_driver->get && has_target()) {
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/6] cpufreq: Add boost_freq_req QoS request
2026-01-26 10:18 ` [PATCH 2/6] cpufreq: Add boost_freq_req QoS request Pierre Gondois
@ 2026-01-31 4:00 ` zhenglifeng (A)
2026-02-05 13:58 ` Pierre Gondois
0 siblings, 1 reply; 16+ messages in thread
From: zhenglifeng (A) @ 2026-01-31 4:00 UTC (permalink / raw)
To: Pierre Gondois
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm, linux-kernel
On 2026/1/26 18:18, Pierre Gondois wrote:
> The Power Management Quality of Service (PM QoS) allows to
> aggregate constraints from multiple entities. It is currently
> used to manage the min/max frequency of a given policy.
>
> Frequency constraints can come for instance from:
> - Thermal framework: acpi_thermal_cpufreq_init()
> - Firmware: _PPC objects: acpi_processor_ppc_init()
> - User: by setting policyX/scaling_[min|max]_freq
> The minimum of the max frequency constraints is used to compute
> the resulting maximum allowed frequency.
>
> When enabling boost frequencies, the same frequency request object
> (policy->max_freq_req) as to handle requests from users is used.
> As a result, when setting:
> - scaling_max_freq
> - boost
> The last sysfs file used overwrites the request from the other
> sysfs file.
>
> To avoid this, create a per-policy boost_freq_req to save the boost
> constraints instead of overwriting the last scaling_max_freq
> constraint.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/cpufreq/cpufreq.c | 40 ++++++++++++++++++++++++++++++++++-----
> include/linux/cpufreq.h | 1 +
> 2 files changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index db414c052658b..c8fb4c6656e94 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1359,17 +1359,24 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
> /* Cancel any pending policy->update work before freeing the policy. */
> cancel_work_sync(&policy->update);
>
> - if (policy->max_freq_req) {
> + if (policy->max_freq_req || policy->boost_freq_req) {
> /*
> - * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY
> - * notification, since CPUFREQ_CREATE_POLICY notification was
> - * sent after adding max_freq_req earlier.
> + * Remove max/boost _freq_req after sending CPUFREQ_REMOVE_POLICY
> + * notification, since CPUFREQ_CREATE_POLICY notification was sent
> + * after adding max/boost _freq_req earlier.
> */
> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
> CPUFREQ_REMOVE_POLICY, policy);
As we discussed in [1], CPUFREQ_REMOVE_POLICY notification will be sent
here without sending CPUFREQ_CREATE_POLICY notification before if adding
boost_freq_req fails.
[1] https://lore.kernel.org/all/a615ab13-bd54-4051-ae61-2bfe8b59427e@arm.com/
> - freq_qos_remove_request(policy->max_freq_req);
> }
>
> + if (policy->boost_freq_req) {
> + freq_qos_remove_request(policy->boost_freq_req);
> + kfree(policy->boost_freq_req);
> + }
> +
> + if (policy->max_freq_req)
> + freq_qos_remove_request(policy->max_freq_req);
> +
Thses two 'if's are unnecessary. It's OK to call freq_qos_remove_request
and kfree when the QoS request is NULL.
> freq_qos_remove_request(policy->min_freq_req);
> kfree(policy->min_freq_req);
>
> @@ -1479,6 +1486,29 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
> goto out_destroy_policy;
> }
>
> + if (policy->boost_supported) {
> + policy->boost_freq_req = kzalloc(sizeof(*policy->boost_freq_req),
> + GFP_KERNEL);
> + if (!policy->boost_freq_req) {
> + ret = -ENOMEM;
> + goto out_destroy_policy;
> + }
> +
> + ret = freq_qos_add_request(&policy->constraints,
> + policy->boost_freq_req,
> + FREQ_QOS_MAX,
> + FREQ_QOS_MAX_DEFAULT_VALUE);
> + if (ret < 0) {
> + /*
> + * So we don't call freq_qos_remove_request() for an
> + * uninitialized request.
> + */
> + kfree(policy->boost_freq_req);
> + policy->boost_freq_req = NULL;
> + goto out_destroy_policy;
> + }
> + }
> +
> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
> CPUFREQ_CREATE_POLICY, policy);
> }
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index 0465d1e6f72ac..c292a6a19e4f5 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -81,6 +81,7 @@ struct cpufreq_policy {
> struct freq_constraints constraints;
> struct freq_qos_request *min_freq_req;
> struct freq_qos_request *max_freq_req;
> + struct freq_qos_request *boost_freq_req;
>
> struct cpufreq_frequency_table *freq_table;
> enum cpufreq_table_sorting freq_table_sorted;
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/6] cpufreq: Centralize boost freq QoS requests
2026-01-26 10:18 ` [PATCH 3/6] cpufreq: Centralize boost freq QoS requests Pierre Gondois
@ 2026-01-31 4:11 ` zhenglifeng (A)
2026-02-05 13:58 ` Pierre Gondois
0 siblings, 1 reply; 16+ messages in thread
From: zhenglifeng (A) @ 2026-01-31 4:11 UTC (permalink / raw)
To: Pierre Gondois, linux-kernel
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm
On 2026/1/26 18:18, Pierre Gondois wrote:
> policy_set_boost() calls the cpufreq set_boost callback.
> Update the newly added boost_freq_req request from there:
> - whenever boost is toggled
> - to cover all possible paths
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
> drivers/cpufreq/cpufreq.c | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index c8fb4c6656e94..505da5b00e575 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -603,10 +603,19 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
> policy->boost_enabled = enable;
>
> ret = cpufreq_driver->set_boost(policy, enable);
> - if (ret)
> + if (ret) {
> policy->boost_enabled = !policy->boost_enabled;
> + return ret;
> + }
>
> - return ret;
> + ret = freq_qos_update_request(policy->boost_freq_req, policy->cpuinfo.max_freq);
> + if (ret < 0) {
> + policy->boost_enabled = !policy->boost_enabled;
> + cpufreq_driver->set_boost(policy, !policy->boost_enabled);
!policy->boost_enabled twice.
> + return ret;
> + }
> +
> + return 0;
> }
>
> static ssize_t store_local_boost(struct cpufreq_policy *policy,
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/6] cpufreq: Centralize boost freq QoS requests
2026-01-31 4:11 ` zhenglifeng (A)
@ 2026-02-05 13:58 ` Pierre Gondois
0 siblings, 0 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-02-05 13:58 UTC (permalink / raw)
To: zhenglifeng (A), linux-kernel
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm
On 1/31/26 05:11, zhenglifeng (A) wrote:
> On 2026/1/26 18:18, Pierre Gondois wrote:
>> policy_set_boost() calls the cpufreq set_boost callback.
>> Update the newly added boost_freq_req request from there:
>> - whenever boost is toggled
>> - to cover all possible paths
>>
>> Signed-off-by: Pierre Gondois<pierre.gondois@arm.com>
>> ---
>> drivers/cpufreq/cpufreq.c | 13 +++++++++++--
>> 1 file changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> index c8fb4c6656e94..505da5b00e575 100644
>> --- a/drivers/cpufreq/cpufreq.c
>> +++ b/drivers/cpufreq/cpufreq.c
>> @@ -603,10 +603,19 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
>> policy->boost_enabled = enable;
>>
>> ret = cpufreq_driver->set_boost(policy, enable);
>> - if (ret)
>> + if (ret) {
>> policy->boost_enabled = !policy->boost_enabled;
>> + return ret;
>> + }
>>
>> - return ret;
>> + ret = freq_qos_update_request(policy->boost_freq_req, policy->cpuinfo.max_freq);
>> + if (ret < 0) {
>> + policy->boost_enabled = !policy->boost_enabled;
>> + cpufreq_driver->set_boost(policy, !policy->boost_enabled);
> !policy->boost_enabled twice.
Yes indeed.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/6] cpufreq: Add boost_freq_req QoS request
2026-01-31 4:00 ` zhenglifeng (A)
@ 2026-02-05 13:58 ` Pierre Gondois
0 siblings, 0 replies; 16+ messages in thread
From: Pierre Gondois @ 2026-02-05 13:58 UTC (permalink / raw)
To: zhenglifeng (A)
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm, linux-kernel
Hello Lifeng,
Thanks for the review,
On 1/31/26 05:00, zhenglifeng (A) wrote:
> On 2026/1/26 18:18, Pierre Gondois wrote:
>> The Power Management Quality of Service (PM QoS) allows to
>> aggregate constraints from multiple entities. It is currently
>> used to manage the min/max frequency of a given policy.
>>
>> Frequency constraints can come for instance from:
>> - Thermal framework: acpi_thermal_cpufreq_init()
>> - Firmware: _PPC objects: acpi_processor_ppc_init()
>> - User: by setting policyX/scaling_[min|max]_freq
>> The minimum of the max frequency constraints is used to compute
>> the resulting maximum allowed frequency.
>>
>> When enabling boost frequencies, the same frequency request object
>> (policy->max_freq_req) as to handle requests from users is used.
>> As a result, when setting:
>> - scaling_max_freq
>> - boost
>> The last sysfs file used overwrites the request from the other
>> sysfs file.
>>
>> To avoid this, create a per-policy boost_freq_req to save the boost
>> constraints instead of overwriting the last scaling_max_freq
>> constraint.
>>
>> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
>> ---
>> drivers/cpufreq/cpufreq.c | 40 ++++++++++++++++++++++++++++++++++-----
>> include/linux/cpufreq.h | 1 +
>> 2 files changed, 36 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> index db414c052658b..c8fb4c6656e94 100644
>> --- a/drivers/cpufreq/cpufreq.c
>> +++ b/drivers/cpufreq/cpufreq.c
>> @@ -1359,17 +1359,24 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
>> /* Cancel any pending policy->update work before freeing the policy. */
>> cancel_work_sync(&policy->update);
>>
>> - if (policy->max_freq_req) {
>> + if (policy->max_freq_req || policy->boost_freq_req) {
>> /*
>> - * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY
>> - * notification, since CPUFREQ_CREATE_POLICY notification was
>> - * sent after adding max_freq_req earlier.
>> + * Remove max/boost _freq_req after sending CPUFREQ_REMOVE_POLICY
>> + * notification, since CPUFREQ_CREATE_POLICY notification was sent
>> + * after adding max/boost _freq_req earlier.
>> */
>> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
>> CPUFREQ_REMOVE_POLICY, policy);
> As we discussed in [1], CPUFREQ_REMOVE_POLICY notification will be sent
> here without sending CPUFREQ_CREATE_POLICY notification before if adding
> boost_freq_req fails.
>
> [1] https://lore.kernel.org/all/a615ab13-bd54-4051-ae61-2bfe8b59427e@arm.com/
Yes right indeed.
The following condition should be more correct:
if ((policy->max_freq_req && !policy->boost_supported) ||
policy->boost_freq_req) {
...
}
>> - freq_qos_remove_request(policy->max_freq_req);
>> }
>>
>> + if (policy->boost_freq_req) {
>> + freq_qos_remove_request(policy->boost_freq_req);
>> + kfree(policy->boost_freq_req);
>> + }
>> +
>> + if (policy->max_freq_req)
>> + freq_qos_remove_request(policy->max_freq_req);
>> +
> Thses two 'if's are unnecessary. It's OK to call freq_qos_remove_request
> and kfree when the QoS request is NULL.
Ok
>> freq_qos_remove_request(policy->min_freq_req);
>> kfree(policy->min_freq_req);
>>
>> @@ -1479,6 +1486,29 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>> goto out_destroy_policy;
>> }
>>
>> + if (policy->boost_supported) {
>> + policy->boost_freq_req = kzalloc(sizeof(*policy->boost_freq_req),
>> + GFP_KERNEL);
>> + if (!policy->boost_freq_req) {
>> + ret = -ENOMEM;
>> + goto out_destroy_policy;
>> + }
>> +
>> + ret = freq_qos_add_request(&policy->constraints,
>> + policy->boost_freq_req,
>> + FREQ_QOS_MAX,
>> + FREQ_QOS_MAX_DEFAULT_VALUE);
>> + if (ret < 0) {
>> + /*
>> + * So we don't call freq_qos_remove_request() for an
>> + * uninitialized request.
>> + */
>> + kfree(policy->boost_freq_req);
>> + policy->boost_freq_req = NULL;
>> + goto out_destroy_policy;
>> + }
>> + }
>> +
>> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
>> CPUFREQ_CREATE_POLICY, policy);
>> }
>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>> index 0465d1e6f72ac..c292a6a19e4f5 100644
>> --- a/include/linux/cpufreq.h
>> +++ b/include/linux/cpufreq.h
>> @@ -81,6 +81,7 @@ struct cpufreq_policy {
>> struct freq_constraints constraints;
>> struct freq_qos_request *min_freq_req;
>> struct freq_qos_request *max_freq_req;
>> + struct freq_qos_request *boost_freq_req;
>>
>> struct cpufreq_frequency_table *freq_table;
>> enum cpufreq_table_sorting freq_table_sorted;
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint
2026-01-31 3:28 ` zhenglifeng (A)
@ 2026-02-05 13:59 ` Pierre Gondois
2026-02-06 7:17 ` zhenglifeng (A)
0 siblings, 1 reply; 16+ messages in thread
From: Pierre Gondois @ 2026-02-05 13:59 UTC (permalink / raw)
To: zhenglifeng (A)
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm, linux-kernel
On 1/31/26 04:28, zhenglifeng (A) wrote:
> On 2026/1/26 18:18, Pierre Gondois wrote:
>> policy->max_freq_req represents the maximum allowed frequency as
>> requested by the policyX/scaling_max_freq sysfs file. This request
>> applies to all CPUs of the policy. It is not possible to request
>> a per-CPU maximum frequency.
>>
>> Thus, the interaction between the policy boost and scaling_max_freq
>> settings should be handled by adding a boost specific QoS constraint.
>> This will be handled in the following patches.
>>
>> This patch reverts of:
>> commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
>> a CPU")
>>
>> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
>> ---
>> drivers/cpufreq/cpufreq.c | 4 ----
>> 1 file changed, 4 deletions(-)
>>
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> index 4472bb1ec83c7..db414c052658b 100644
>> --- a/drivers/cpufreq/cpufreq.c
>> +++ b/drivers/cpufreq/cpufreq.c
>> @@ -1481,10 +1481,6 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>>
>> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
>> CPUFREQ_CREATE_POLICY, policy);
>> - } else {
>> - ret = freq_qos_update_request(policy->max_freq_req, policy->max);
>> - if (ret < 0)
>> - goto out_destroy_policy;
> I think this shouldn't be the first patch. This can be removed only after
> adding boost_freq_req, otherwise it's letting the problem out again.
Would it be ok to change the order of the patches (i.e. patch 1 and 2)
instead of melding this change in another patch ?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint
2026-02-05 13:59 ` Pierre Gondois
@ 2026-02-06 7:17 ` zhenglifeng (A)
0 siblings, 0 replies; 16+ messages in thread
From: zhenglifeng (A) @ 2026-02-06 7:17 UTC (permalink / raw)
To: Pierre Gondois
Cc: Jie Zhan, Ionela Voinescu, Christian Loehle, sumitg,
Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
Mario Limonciello, Perry Yuan, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm, linux-kernel
On 2026/2/5 21:59, Pierre Gondois wrote:
>
> On 1/31/26 04:28, zhenglifeng (A) wrote:
>> On 2026/1/26 18:18, Pierre Gondois wrote:
>>> policy->max_freq_req represents the maximum allowed frequency as
>>> requested by the policyX/scaling_max_freq sysfs file. This request
>>> applies to all CPUs of the policy. It is not possible to request
>>> a per-CPU maximum frequency.
>>>
>>> Thus, the interaction between the policy boost and scaling_max_freq
>>> settings should be handled by adding a boost specific QoS constraint.
>>> This will be handled in the following patches.
>>>
>>> This patch reverts of:
>>> commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
>>> a CPU")
>>>
>>> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
>>> ---
>>> drivers/cpufreq/cpufreq.c | 4 ----
>>> 1 file changed, 4 deletions(-)
>>>
>>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>>> index 4472bb1ec83c7..db414c052658b 100644
>>> --- a/drivers/cpufreq/cpufreq.c
>>> +++ b/drivers/cpufreq/cpufreq.c
>>> @@ -1481,10 +1481,6 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>>> blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
>>> CPUFREQ_CREATE_POLICY, policy);
>>> - } else {
>>> - ret = freq_qos_update_request(policy->max_freq_req, policy->max);
>>> - if (ret < 0)
>>> - goto out_destroy_policy;
>> I think this shouldn't be the first patch. This can be removed only after
>> adding boost_freq_req, otherwise it's letting the problem out again.
>
>
> Would it be ok to change the order of the patches (i.e. patch 1 and 2) instead of melding this change in another patch ?
>
I tested the patch on my machine, and it seems the original problem no
longer exists. So I now think it's OK to revert this commit.
Reviewed-by: Lifeng Zheng <zhenglifeng1@huawei.com>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-02-06 7:17 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-26 10:18 [PATCH 0/6] cpufreq: Introduce boost frequency QoS Pierre Gondois
2026-01-26 10:18 ` [PATCH 1/6] cpufreq: Remove per-CPU QoS constraint Pierre Gondois
2026-01-31 3:28 ` zhenglifeng (A)
2026-02-05 13:59 ` Pierre Gondois
2026-02-06 7:17 ` zhenglifeng (A)
2026-01-26 10:18 ` [PATCH 2/6] cpufreq: Add boost_freq_req QoS request Pierre Gondois
2026-01-31 4:00 ` zhenglifeng (A)
2026-02-05 13:58 ` Pierre Gondois
2026-01-26 10:18 ` [PATCH 3/6] cpufreq: Centralize boost freq QoS requests Pierre Gondois
2026-01-31 4:11 ` zhenglifeng (A)
2026-02-05 13:58 ` Pierre Gondois
2026-01-26 10:18 ` [PATCH 4/6] cpufreq: Update .set_boost() callbacks to rely on boost_freq_req Pierre Gondois
2026-01-26 10:18 ` [PATCH 5/6] cpufreq: Set policy->min and max as real QoS constraints Pierre Gondois
2026-01-29 6:02 ` kernel test robot
2026-01-29 9:52 ` kernel test robot
2026-01-26 10:18 ` [RFC PATCH 6/6] cpufreq/freq_table: Allow decreasing cpuinfo.max_freq Pierre Gondois
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox