drivers/cpufreq/cppc_cpufreq.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
The ACPI 6.5 specification describes "Lowest Performance" as the absolute
lowest performance level of the platform. It notes:
"Selecting a performance level lower than the lowest nonlinear performance
level may actually cause an efficiency penalty, but should reduce the
instantaneous power consumption of the processor. In traditional terms,
this represents the T-state range of performance levels."
Currently, the cpufreq core initializes the minimum QoS request to 0.
While this allows userspace to modify limits, it causes the CPU frequency
to drop below lowest_nonlinear_perf by default. This hurts performance with
negligible power savings.
To fix this, implement a "soft" limit in cppc_verify_policy(). If the
policy minimum is still the default (0), it is clamped to
lowest_nonlinear_perf. However, if userspace has explicitly set a lower
limit, that configuration takes precedence.
Signed-off-by: Pengjie Zhang <zhangpengjie2@huawei.com>
---
drivers/cpufreq/cppc_cpufreq.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 9eac77c4f294..59aa1721438b 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -301,9 +301,23 @@ static unsigned int cppc_cpufreq_fast_switch(struct cpufreq_policy *policy,
return target_freq;
}
-static int cppc_verify_policy(struct cpufreq_policy_data *policy)
+static int cppc_verify_policy(struct cpufreq_policy_data *policy_data)
{
- cpufreq_verify_within_cpu_limits(policy);
+ if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) =
+ cpufreq_cpu_get(policy_data->cpu);
+ struct cppc_cpudata *cpu_data;
+
+ if (!policy)
+ return -EINVAL;
+
+ cpu_data = policy->driver_data;
+ policy_data->min = cppc_perf_to_khz(&cpu_data->perf_caps,
+ cpu_data->perf_caps.lowest_nonlinear_perf);
+ }
+
+ cpufreq_verify_within_cpu_limits(policy_data);
+
return 0;
}
--
2.33.0
Gentle Ping.
Thanks!
On 1/16/2026 5:45 PM, Pengjie Zhang wrote:
> The ACPI 6.5 specification describes "Lowest Performance" as the absolute
> lowest performance level of the platform. It notes:
>
> "Selecting a performance level lower than the lowest nonlinear performance
> level may actually cause an efficiency penalty, but should reduce the
> instantaneous power consumption of the processor. In traditional terms,
> this represents the T-state range of performance levels."
>
> Currently, the cpufreq core initializes the minimum QoS request to 0.
> While this allows userspace to modify limits, it causes the CPU frequency
> to drop below lowest_nonlinear_perf by default. This hurts performance with
> negligible power savings.
>
> To fix this, implement a "soft" limit in cppc_verify_policy(). If the
> policy minimum is still the default (0), it is clamped to
> lowest_nonlinear_perf. However, if userspace has explicitly set a lower
> limit, that configuration takes precedence.
>
> Signed-off-by: Pengjie Zhang <zhangpengjie2@huawei.com>
> ---
> drivers/cpufreq/cppc_cpufreq.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 9eac77c4f294..59aa1721438b 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -301,9 +301,23 @@ static unsigned int cppc_cpufreq_fast_switch(struct cpufreq_policy *policy,
> return target_freq;
> }
>
> -static int cppc_verify_policy(struct cpufreq_policy_data *policy)
> +static int cppc_verify_policy(struct cpufreq_policy_data *policy_data)
> {
> - cpufreq_verify_within_cpu_limits(policy);
> + if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
> + struct cpufreq_policy *policy __free(put_cpufreq_policy) =
> + cpufreq_cpu_get(policy_data->cpu);
> + struct cppc_cpudata *cpu_data;
> +
> + if (!policy)
> + return -EINVAL;
> +
> + cpu_data = policy->driver_data;
> + policy_data->min = cppc_perf_to_khz(&cpu_data->perf_caps,
> + cpu_data->perf_caps.lowest_nonlinear_perf);
> + }
> +
> + cpufreq_verify_within_cpu_limits(policy_data);
> +
> return 0;
> }
>
© 2016 - 2026 Red Hat, Inc.