* [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
@ 2026-09-15 6:57 Jianyong Wu
2026-09-15 9:32 ` Hongyan Xia
2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
0 siblings, 2 replies; 8+ messages in thread
From: Jianyong Wu @ 2026-09-15 6:57 UTC (permalink / raw)
To: rafael, viresh.kumar, kprateek.nayak, vincent.guittot
Cc: linux-pm, linux-kernel, ray.huang, mario.limonciello, perry.yuan,
zhanjie9, zhenglifeng1, pierre.gondois, sumitg,
srinivas.pandruvada, lenb, hongyan.xia, zhongqiu.han, wujianyong,
jianyong.wu, wangfengyu, zhongyuan, huangsj
Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
However, cpuinfo.max_freq may include boost frequencies and therefore
does not necessarily represent the maximum sustainable frequency. On
some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
the frequency table only contains non-boost frequencies. Consequently,
cpufreq pressure remains nonzero even without an additional frequency
limit.
Furthermore, drivers may update cpuinfo.max_freq when boost is enabled
or disabled. With a fixed policy limit below the maximum non-boost
frequency, this changes the pressure reference and hence the reported
pressure, although the non-boost frequency limit remains unchanged.
Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a reference
frequency excluding boost. Populate it from the nominal frequency in
amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
Use this value when arch_scale_freq_ref() returns zero. Preserve the
existing cpuinfo.max_freq fallback for drivers that leave the new field
at zero.
Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
passive modes. With no additional frequency limit, pressure is zero.
With a fixed limit below the non-boost reference frequency, pressure
remains unchanged across boost transitions.
Fixes: d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq")
Signed-off-by: Jianyong Wu <wujianyong@hygon.cn>
---
The earlier fix was incorrect and has been abandoned. This patch takes
a different approach.
Previous discussion: https://lore.kernel.org/all/SI2PR04MB4931A8BA0EF213B0238BD9E4E3BD2@SI2PR04MB4931.apcprd04.prod.outlook.com/
drivers/cpufreq/acpi-cpufreq.c | 3 +++
drivers/cpufreq/amd-pstate.c | 2 ++
drivers/cpufreq/cppc_cpufreq.c | 3 ++-
drivers/cpufreq/cpufreq.c | 4 +++-
drivers/cpufreq/intel_pstate.c | 2 ++
include/linux/cpufreq.h | 2 ++
6 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 21639d9ac753..e7b22456ebb8 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -856,6 +856,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
}
freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
+ /* Init max sustainable cpu frequency */
+ policy->cpuinfo.max_sustainable_freq = freq_table[0].frequency;
+
max_boost_ratio = get_max_boost_ratio(cpu, &nominal_freq);
if (max_boost_ratio) {
unsigned int freq = nominal_freq;
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 3a6b4b224a66..6fc28bb1499b 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1085,6 +1085,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
perf.lowest_perf);
policy->cpuinfo.max_freq = cpudata->max_freq;
+ policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
policy->driver_data = cpudata;
ret = amd_pstate_cppc_enable(policy);
if (ret)
@@ -1912,6 +1913,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = perf_to_freq(perf, cpudata->nominal_freq,
perf.lowest_perf);
policy->cpuinfo.max_freq = cpudata->max_freq;
+ policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
policy->driver_data = cpudata;
ret = amd_pstate_cppc_enable(policy);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 6fe0e972952a..f803fcdca483 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -682,7 +682,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = cppc_perf_to_khz(caps, caps->lowest_perf);
policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, policy->boost_enabled ?
caps->highest_perf : caps->nominal_perf);
-
+ policy->cpuinfo.max_sustainable_freq =
+ cppc_perf_to_khz(caps, caps->nominal_perf);
policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
policy->shared_type = cpu_data->shared_type;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b898b6544069..c1d54a22265d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2587,7 +2587,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
cpu = cpumask_first(policy->related_cpus);
max_freq = arch_scale_freq_ref(cpu);
if (!max_freq)
- max_freq = policy->cpuinfo.max_freq;
+ max_freq = policy->cpuinfo.max_sustainable_freq ?
+ policy->cpuinfo.max_sustainable_freq :
+ policy->cpuinfo.max_freq;
capped_freq = policy->max;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6e984c114d96..daef7e99fead 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1474,6 +1474,7 @@ static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,
policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
+ policy->cpuinfo.max_sustainable_freq = cpudata->pstate.max_freq;
refresh_frequency_limits(policy);
}
@@ -3052,6 +3053,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = cpu->pstate.min_freq;
policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+ policy->cpuinfo.max_sustainable_freq = cpu->pstate.max_freq;
intel_pstate_init_acpi_perf_limits(policy);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ae9d1ce4f49c..aa3f60a167be 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -45,6 +45,8 @@ enum cpufreq_table_sorting {
struct cpufreq_cpuinfo {
unsigned int max_freq;
unsigned int min_freq;
+ /* Maximum sustainable frequency excluding boost, or 0 if unknown. */
+ unsigned int max_sustainable_freq;
/* in 10^(-9) s = nanoseconds */
unsigned int transition_latency;
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-15 6:57 [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation Jianyong Wu
@ 2026-09-15 9:32 ` Hongyan Xia
2026-09-15 12:46 ` Jianyong Wu
2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
1 sibling, 1 reply; 8+ messages in thread
From: Hongyan Xia @ 2026-09-15 9:32 UTC (permalink / raw)
To: Jianyong Wu, rafael, viresh.kumar, kprateek.nayak, vincent.guittot
Cc: linux-pm, linux-kernel, ray.huang, mario.limonciello, perry.yuan,
zhanjie9, zhenglifeng1, pierre.gondois, sumitg,
srinivas.pandruvada, lenb, zhongqiu.han, jianyong.wu, wangfengyu,
zhongyuan, huangsj
On 9/15/2026 2:57 PM, Jianyong Wu wrote:
> Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
> back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
> frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
>
> However, cpuinfo.max_freq may include boost frequencies and therefore
> does not necessarily represent the maximum sustainable frequency. On
> some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
> the frequency table only contains non-boost frequencies. Consequently,
> cpufreq pressure remains nonzero even without an additional frequency
> limit.
>
> Furthermore, drivers may update cpuinfo.max_freq when boost is enabled
> or disabled. With a fixed policy limit below the maximum non-boost
> frequency, this changes the pressure reference and hence the reported
> pressure, although the non-boost frequency limit remains unchanged.
>
> Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a reference
> frequency excluding boost. Populate it from the nominal frequency in
> amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
> intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
>
> Use this value when arch_scale_freq_ref() returns zero. Preserve the
> existing cpuinfo.max_freq fallback for drivers that leave the new field
> at zero.
Actually, what remaining platforms are out there that can hit this path?
From a quick look I think no x86 or Arm platforms can hit the fallback.
> Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
> passive modes. With no additional frequency limit, pressure is zero.
> With a fixed limit below the non-boost reference frequency, pressure
> remains unchanged across boost transitions.
>
> Fixes: d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq")
> Signed-off-by: Jianyong Wu <wujianyong@hygon.cn>
Looks okay to me.
Reviewed-by: Hongyan Xia <hongyan.xia@transsion.com>
> ---
> [...]
^ permalink raw reply [flat|nested] 8+ messages in thread* RE: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-15 9:32 ` Hongyan Xia
@ 2026-09-15 12:46 ` Jianyong Wu
0 siblings, 0 replies; 8+ messages in thread
From: Jianyong Wu @ 2026-09-15 12:46 UTC (permalink / raw)
To: Hongyan Xia
Cc: linux-pm, linux-kernel, ray.huang, mario.limonciello, perry.yuan,
zhanjie9, zhenglifeng1, pierre.gondois, sumitg,
srinivas.pandruvada, lenb, zhongqiu.han, jianyong.wu,
Fengyu Wang, Yuan Zhong, Huangsj, rafael, viresh.kumar,
kprateek.nayak, vincent.guittot
Hi Hongyan,
> -----Original Message-----
> From: Hongyan Xia <hongyan.xia@transsion.com>
> Sent: Tuesday, September 15, 2026 5:33 PM
> To: Jianyong Wu <wujianyong@hygon.cn>; rafael@kernel.org;
> viresh.kumar@linaro.org; kprateek.nayak@amd.com;
> vincent.guittot@linaro.org
> Cc: linux-pm@vger.kernel.org; linux-kernel@vger.kernel.org;
> ray.huang@amd.com; mario.limonciello@amd.com; perry.yuan@amd.com;
> zhanjie9@hisilicon.com; zhenglifeng1@huawei.com;
> pierre.gondois@arm.com; sumitg@nvidia.com;
> srinivas.pandruvada@linux.intel.com; lenb@kernel.org;
> zhongqiu.han@oss.qualcomm.com; jianyong.wu@outlook.com; Fengyu
> Wang <wangfengyu@hygon.cn>; Yuan Zhong <zhongyuan@hygon.cn>;
> Huangsj <huangsj@hygon.cn>
> Subject: Re: [PATCH] cpufreq: Use a non-boost reference frequency for
> pressure calculation
>
> On 9/15/2026 2:57 PM, Jianyong Wu wrote:
> > Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
> > back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
> > frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
> >
> > However, cpuinfo.max_freq may include boost frequencies and therefore
> > does not necessarily represent the maximum sustainable frequency. On
> > some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
> > the frequency table only contains non-boost frequencies. Consequently,
> > cpufreq pressure remains nonzero even without an additional frequency
> > limit.
> >
> > Furthermore, drivers may update cpuinfo.max_freq when boost is
> enabled
> > or disabled. With a fixed policy limit below the maximum non-boost
> > frequency, this changes the pressure reference and hence the reported
> > pressure, although the non-boost frequency limit remains unchanged.
> >
> > Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a
> reference
> > frequency excluding boost. Populate it from the nominal frequency in
> > amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
> > intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
> >
> > Use this value when arch_scale_freq_ref() returns zero. Preserve the
> > existing cpuinfo.max_freq fallback for drivers that leave the new field
> > at zero.
>
> Actually, what remaining platforms are out there that can hit this path?
> From a quick look I think no x86 or Arm platforms can hit the fallback.
>
Thanks for review!
There are many cpufreq drivers, and I don't have access to hardware covering
all of them. This patch therefore limits the changes to drivers relevant to
the reported issue.
Some legacy x86 drivers, such as pt-clockmod, do not populate the new field
and still use the fallback. The fallback preserves their existing behavior.
Support for the new field in other drivers can be added separately, after
verifying each driver's frequency semantics and validating the changes on
the relevant hardware.
Thanks
Jianyong
> > Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
> > passive modes. With no additional frequency limit, pressure is zero.
> > With a fixed limit below the non-boost reference frequency, pressure
> > remains unchanged across boost transitions.
> >
> > Fixes: d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
> back to cpuinfo.max_freq")
> > Signed-off-by: Jianyong Wu <wujianyong@hygon.cn>
>
> Looks okay to me.
>
> Reviewed-by: Hongyan Xia <hongyan.xia@transsion.com>
>
> > ---
> > [...]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-15 6:57 [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation Jianyong Wu
2026-09-15 9:32 ` Hongyan Xia
@ 2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
2026-09-17 18:34 ` Mario Limonciello
2026-09-18 4:08 ` Jianyong Wu
1 sibling, 2 replies; 8+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-09-17 17:38 UTC (permalink / raw)
To: Jianyong Wu
Cc: viresh.kumar, kprateek.nayak, vincent.guittot, linux-pm,
linux-kernel, ray.huang, mario.limonciello, perry.yuan, zhanjie9,
zhenglifeng1, pierre.gondois, sumitg, srinivas.pandruvada,
hongyan.xia, zhongqiu.han, jianyong.wu, wangfengyu, zhongyuan,
huangsj, Ricardo Neri
On Tue, Sep 15, 2026 at 9:03 AM Jianyong Wu <wujianyong@hygon.cn> wrote:
>
> Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
> back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
> frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
>
> However, cpuinfo.max_freq may include boost frequencies and therefore
> does not necessarily represent the maximum sustainable frequency.
And then it really matters what is sustainable and for how long.
> On some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
> the frequency table only contains non-boost frequencies.
In which case selecting freq_table[0] may give the processor a license
to go to the turbo (or boost) frequency range.
> Consequently, cpufreq pressure remains nonzero even without an additional
> frequency limit.
So when and where does this matter?
> Furthermore, drivers may update cpuinfo.max_freq when boost is enabled
> or disabled. With a fixed policy limit below the maximum non-boost
> frequency, this changes the pressure reference and hence the reported
> pressure, although the non-boost frequency limit remains unchanged.
If the capacity is updated though along with the cpuinfo.max_freq
change, then this is all fine because the pressure is then computed
relative to the new capacity. intel_pstate does that.
> Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a reference
> frequency excluding boost. Populate it from the nominal frequency in
> amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
> intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
>
> Use this value when arch_scale_freq_ref() returns zero. Preserve the
> existing cpuinfo.max_freq fallback for drivers that leave the new field
> at zero.
>
> Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
> passive modes. With no additional frequency limit, pressure is zero.
> With a fixed limit below the non-boost reference frequency, pressure
> remains unchanged across boost transitions.
Which may not be what is intended.
> Fixes: d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq")
> Signed-off-by: Jianyong Wu <wujianyong@hygon.cn>
> ---
> The earlier fix was incorrect and has been abandoned. This patch takes
> a different approach.
>
> Previous discussion: https://lore.kernel.org/all/SI2PR04MB4931A8BA0EF213B0238BD9E4E3BD2@SI2PR04MB4931.apcprd04.prod.outlook.com/
>
> drivers/cpufreq/acpi-cpufreq.c | 3 +++
> drivers/cpufreq/amd-pstate.c | 2 ++
> drivers/cpufreq/cppc_cpufreq.c | 3 ++-
> drivers/cpufreq/cpufreq.c | 4 +++-
> drivers/cpufreq/intel_pstate.c | 2 ++
> include/linux/cpufreq.h | 2 ++
> 6 files changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
> index 21639d9ac753..e7b22456ebb8 100644
> --- a/drivers/cpufreq/acpi-cpufreq.c
> +++ b/drivers/cpufreq/acpi-cpufreq.c
> @@ -856,6 +856,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
> }
> freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
>
> + /* Init max sustainable cpu frequency */
> + policy->cpuinfo.max_sustainable_freq = freq_table[0].frequency;
> +
> max_boost_ratio = get_max_boost_ratio(cpu, &nominal_freq);
> if (max_boost_ratio) {
> unsigned int freq = nominal_freq;
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index 3a6b4b224a66..6fc28bb1499b 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -1085,6 +1085,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
> perf.lowest_perf);
> policy->cpuinfo.max_freq = cpudata->max_freq;
>
> + policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
> policy->driver_data = cpudata;
> ret = amd_pstate_cppc_enable(policy);
> if (ret)
> @@ -1912,6 +1913,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
> policy->cpuinfo.min_freq = perf_to_freq(perf, cpudata->nominal_freq,
> perf.lowest_perf);
> policy->cpuinfo.max_freq = cpudata->max_freq;
> + policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
> policy->driver_data = cpudata;
>
> ret = amd_pstate_cppc_enable(policy);
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 6fe0e972952a..f803fcdca483 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -682,7 +682,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
> policy->cpuinfo.min_freq = cppc_perf_to_khz(caps, caps->lowest_perf);
> policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, policy->boost_enabled ?
> caps->highest_perf : caps->nominal_perf);
> -
> + policy->cpuinfo.max_sustainable_freq =
> + cppc_perf_to_khz(caps, caps->nominal_perf);
> policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
> policy->shared_type = cpu_data->shared_type;
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index b898b6544069..c1d54a22265d 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -2587,7 +2587,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
> cpu = cpumask_first(policy->related_cpus);
> max_freq = arch_scale_freq_ref(cpu);
> if (!max_freq)
> - max_freq = policy->cpuinfo.max_freq;
> + max_freq = policy->cpuinfo.max_sustainable_freq ?
> + policy->cpuinfo.max_sustainable_freq :
> + policy->cpuinfo.max_freq;
>
> capped_freq = policy->max;
>
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index 6e984c114d96..daef7e99fead 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -1474,6 +1474,7 @@ static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,
>
> policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
> cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
> + policy->cpuinfo.max_sustainable_freq = cpudata->pstate.max_freq;
>
> refresh_frequency_limits(policy);
> }
> @@ -3052,6 +3053,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
> policy->cpuinfo.min_freq = cpu->pstate.min_freq;
> policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
> cpu->pstate.max_freq : cpu->pstate.turbo_freq;
> + policy->cpuinfo.max_sustainable_freq = cpu->pstate.max_freq;
>
> intel_pstate_init_acpi_perf_limits(policy);
>
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index ae9d1ce4f49c..aa3f60a167be 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -45,6 +45,8 @@ enum cpufreq_table_sorting {
> struct cpufreq_cpuinfo {
> unsigned int max_freq;
> unsigned int min_freq;
> + /* Maximum sustainable frequency excluding boost, or 0 if unknown. */
> + unsigned int max_sustainable_freq;
>
> /* in 10^(-9) s = nanoseconds */
> unsigned int transition_latency;
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
@ 2026-09-17 18:34 ` Mario Limonciello
2026-09-18 5:59 ` Jianyong Wu
2026-09-18 4:08 ` Jianyong Wu
1 sibling, 1 reply; 8+ messages in thread
From: Mario Limonciello @ 2026-09-17 18:34 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel), Jianyong Wu
Cc: viresh.kumar, kprateek.nayak, vincent.guittot, linux-pm,
linux-kernel, ray.huang, perry.yuan, zhanjie9, zhenglifeng1,
pierre.gondois, sumitg, srinivas.pandruvada, hongyan.xia,
zhongqiu.han, jianyong.wu, wangfengyu, zhongyuan, huangsj,
Ricardo Neri
On 9/17/26 12:38, Rafael J. Wysocki (Intel) wrote:
> On Tue, Sep 15, 2026 at 9:03 AM Jianyong Wu <wujianyong@hygon.cn> wrote:
>>
>> Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
>> back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
>> frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
>>
>> However, cpuinfo.max_freq may include boost frequencies and therefore
>> does not necessarily represent the maximum sustainable frequency.
>
> And then it really matters what is sustainable and for how long.
>
>> On some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
>> the frequency table only contains non-boost frequencies.
>
> In which case selecting freq_table[0] may give the processor a license
> to go to the turbo (or boost) frequency range.
>
>> Consequently, cpufreq pressure remains nonzero even without an additional
>> frequency limit.
>
> So when and where does this matter?
>
>> Furthermore, drivers may update cpuinfo.max_freq when boost is enabled
>> or disabled. With a fixed policy limit below the maximum non-boost
>> frequency, this changes the pressure reference and hence the reported
>> pressure, although the non-boost frequency limit remains unchanged.
>
> If the capacity is updated though along with the cpuinfo.max_freq
> change, then this is all fine because the pressure is then computed
> relative to the new capacity. intel_pstate does that.
>
>> Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a reference
>> frequency excluding boost. Populate it from the nominal frequency in
>> amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
>> intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
>>
>> Use this value when arch_scale_freq_ref() returns zero. Preserve the
>> existing cpuinfo.max_freq fallback for drivers that leave the new field
>> at zero.
>>
>> Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
>> passive modes. With no additional frequency limit, pressure is zero.
>> With a fixed limit below the non-boost reference frequency, pressure
>> remains unchanged across boost transitions.
>
> Which may not be what is intended.
>
>> Fixes: d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq")
>> Signed-off-by: Jianyong Wu <wujianyong@hygon.cn>
>> ---
>> The earlier fix was incorrect and has been abandoned. This patch takes
>> a different approach.
>>
>> Previous discussion: https://lore.kernel.org/all/SI2PR04MB4931A8BA0EF213B0238BD9E4E3BD2@SI2PR04MB4931.apcprd04.prod.outlook.com/
>>
>> drivers/cpufreq/acpi-cpufreq.c | 3 +++
>> drivers/cpufreq/amd-pstate.c | 2 ++
>> drivers/cpufreq/cppc_cpufreq.c | 3 ++-
>> drivers/cpufreq/cpufreq.c | 4 +++-
>> drivers/cpufreq/intel_pstate.c | 2 ++
>> include/linux/cpufreq.h | 2 ++
>> 6 files changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
>> index 21639d9ac753..e7b22456ebb8 100644
>> --- a/drivers/cpufreq/acpi-cpufreq.c
>> +++ b/drivers/cpufreq/acpi-cpufreq.c
>> @@ -856,6 +856,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
>> }
>> freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
>>
>> + /* Init max sustainable cpu frequency */
>> + policy->cpuinfo.max_sustainable_freq = freq_table[0].frequency;
>> +
Maybe I'm missing something, but it sounds to me like it would make
sense to just:
policy->cpuinfo.nominal_freq = freq_table[0].frequency
and then use cpuinfo.nominal_freq everywhere, no?
>> max_boost_ratio = get_max_boost_ratio(cpu, &nominal_freq);
>> if (max_boost_ratio) {
>> unsigned int freq = nominal_freq;
>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>> index 3a6b4b224a66..6fc28bb1499b 100644
>> --- a/drivers/cpufreq/amd-pstate.c
>> +++ b/drivers/cpufreq/amd-pstate.c
>> @@ -1085,6 +1085,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
>> perf.lowest_perf);
>> policy->cpuinfo.max_freq = cpudata->max_freq;
>>
>> + policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
>> policy->driver_data = cpudata;
>> ret = amd_pstate_cppc_enable(policy);
>> if (ret)
>> @@ -1912,6 +1913,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
>> policy->cpuinfo.min_freq = perf_to_freq(perf, cpudata->nominal_freq,
>> perf.lowest_perf);
>> policy->cpuinfo.max_freq = cpudata->max_freq;
>> + policy->cpuinfo.max_sustainable_freq = cpudata->nominal_freq;
>> policy->driver_data = cpudata;
>>
>> ret = amd_pstate_cppc_enable(policy);
>> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
>> index 6fe0e972952a..f803fcdca483 100644
>> --- a/drivers/cpufreq/cppc_cpufreq.c
>> +++ b/drivers/cpufreq/cppc_cpufreq.c
>> @@ -682,7 +682,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
>> policy->cpuinfo.min_freq = cppc_perf_to_khz(caps, caps->lowest_perf);
>> policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, policy->boost_enabled ?
>> caps->highest_perf : caps->nominal_perf);
>> -
>> + policy->cpuinfo.max_sustainable_freq =
>> + cppc_perf_to_khz(caps, caps->nominal_perf);
>> policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
>> policy->shared_type = cpu_data->shared_type;
>>
>> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
>> index b898b6544069..c1d54a22265d 100644
>> --- a/drivers/cpufreq/cpufreq.c
>> +++ b/drivers/cpufreq/cpufreq.c
>> @@ -2587,7 +2587,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
>> cpu = cpumask_first(policy->related_cpus);
>> max_freq = arch_scale_freq_ref(cpu);
>> if (!max_freq)
>> - max_freq = policy->cpuinfo.max_freq;
>> + max_freq = policy->cpuinfo.max_sustainable_freq ?
>> + policy->cpuinfo.max_sustainable_freq :
>> + policy->cpuinfo.max_freq;
>>
>> capped_freq = policy->max;
>>
>> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
>> index 6e984c114d96..daef7e99fead 100644
>> --- a/drivers/cpufreq/intel_pstate.c
>> +++ b/drivers/cpufreq/intel_pstate.c
>> @@ -1474,6 +1474,7 @@ static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,
>>
>> policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
>> cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
>> + policy->cpuinfo.max_sustainable_freq = cpudata->pstate.max_freq;
>>
>> refresh_frequency_limits(policy);
>> }
>> @@ -3052,6 +3053,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
>> policy->cpuinfo.min_freq = cpu->pstate.min_freq;
>> policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
>> cpu->pstate.max_freq : cpu->pstate.turbo_freq;
>> + policy->cpuinfo.max_sustainable_freq = cpu->pstate.max_freq;
>>
>> intel_pstate_init_acpi_perf_limits(policy);
>>
>> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
>> index ae9d1ce4f49c..aa3f60a167be 100644
>> --- a/include/linux/cpufreq.h
>> +++ b/include/linux/cpufreq.h
>> @@ -45,6 +45,8 @@ enum cpufreq_table_sorting {
>> struct cpufreq_cpuinfo {
>> unsigned int max_freq;
>> unsigned int min_freq;
>> + /* Maximum sustainable frequency excluding boost, or 0 if unknown. */
>> + unsigned int max_sustainable_freq;
>>
>> /* in 10^(-9) s = nanoseconds */
>> unsigned int transition_latency;
>> --
>> 2.34.1
>>
>>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-17 18:34 ` Mario Limonciello
@ 2026-09-18 5:59 ` Jianyong Wu
0 siblings, 0 replies; 8+ messages in thread
From: Jianyong Wu @ 2026-09-18 5:59 UTC (permalink / raw)
To: Mario Limonciello, Rafael J. Wysocki (Intel)
Cc: viresh.kumar, kprateek.nayak, vincent.guittot, linux-pm,
linux-kernel, ray.huang, perry.yuan, zhanjie9, zhenglifeng1,
pierre.gondois, sumitg, srinivas.pandruvada, hongyan.xia,
zhongqiu.han, wangfengyu, zhongyuan, huangsj, Ricardo Neri,
wujianyong
On 9/17/26 13:34, Mario Limonciello wrote:
>
> Maybe I'm missing something, but it sounds to me like it would make
> sense to just:
>
> policy->cpuinfo.nominal_freq = freq_table[0].frequency
>
> and then use cpuinfo.nominal_freq everywhere, no?
I think "nominal_freq" is better than "max_sustainable_freq". I can
change it if this solution is accepted.
Thanks
Jianyong
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
2026-09-17 18:34 ` Mario Limonciello
@ 2026-09-18 4:08 ` Jianyong Wu
2026-09-18 18:19 ` Rafael J. Wysocki
1 sibling, 1 reply; 8+ messages in thread
From: Jianyong Wu @ 2026-09-18 4:08 UTC (permalink / raw)
To: Rafael J. Wysocki (Intel), Vincent Guittot
Cc: viresh.kumar, kprateek.nayak, linux-pm, linux-kernel, ray.huang,
mario.limonciello, perry.yuan, zhanjie9, zhenglifeng1,
pierre.gondois, sumitg, srinivas.pandruvada, hongyan.xia,
zhongqiu.han, Fengyu Wang, Yuan Zhong, Huangsj, Ricardo Neri
Hi Rafael,
>
> On Sep 18, 2026, at 01:38, Rafael J. Wysocki (Intel) <rafael@kernel.org> wrote:
> On Tue, Sep 15, 2026 at 9:03 AM Jianyong Wu <wujianyong@hygon.cn> wrote:
>>
>> Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
>> back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
>> frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
>>
>> However, cpuinfo.max_freq may include boost frequencies and therefore
>> does not necessarily represent the maximum sustainable frequency.
>
> And then it really matters what is sustainable and for how long.
I think it's confusing to say "sustainable freq" in cpufreq part. I mean the maximum
cpu frequency below boost here. For acpi-cpufreq, it’s P0. For amd-pstate, it’s
nominal frequency. But I can't find a better word.
>
>> On some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
>> the frequency table only contains non-boost frequencies.
>
> In which case selecting freq_table[0] may give the processor a license
> to go to the turbo (or boost) frequency range.
Yeah, selecting freq_table[0] may also mean cpu can go to boost frequency.
But the value doesn't denote that. freq_table[0] is assigned to policy->max which
is compared with policy->cpuinfo.max_freq. The difference between them makes
the cpu pressure which is not intended.
>
>> Consequently, cpufreq pressure remains nonzero even without an additional
>> frequency limit.
>
> So when and where does this matter?
I test it on amd, intel and hygon box. Once acpi-cpufreq is used, the unexpected
cpu pressure appears when there is no cpu frequency capped and boost is enabled.
The wrong cpu pressure affects load balancing. For example, Cache aware
scheduling wants to aggregate task in a LLC using 50% of the whole LLC capacity.
Before commit d2d5c129d07e, everything is OK. But with that commit and using
acpi-cpufreq and with boost on, cache aware scheduling can’t aggregate
task to occupy 50% of the LLC by default as the cpu capacity in the LLC is reduced.
>
>> Furthermore, drivers may update cpuinfo.max_freq when boost is enabled
>> or disabled. With a fixed policy limit below the maximum non-boost
>> frequency, this changes the pressure reference and hence the reported
>> pressure, although the non-boost frequency limit remains unchanged.
>
> If the capacity is updated though along with the cpuinfo.max_freq
> change, then this is all fine because the pressure is then computed
> relative to the new capacity. intel_pstate does that.
This follows Vincent. Reference Vincent’s words [1]:
"As long as the reference frequency used in cpufreq_update_pressure
remains fixed whetever boost is enabled or not this is ok. We don't
want the pressure to change when boost is enabled or disabled only
when policy->max changes."
If intel_pstate let the cpu pressure vary with the boost on or off, what
about acpi-cpufreq. It’s not easy to do the same thing there. I think it
is better to give a uniform behavior across different cpufreq driver.
[1] https://lore.kernel.org/all/CAKfTPtBji8dkr5ixhtZjkyrWLA68TF-KHLrNYWoewPWLyuUd4A@mail.gmail.com/
>
>> Add max_sustainable_freq to struct cpufreq_cpuinfo to provide a reference
>> frequency excluding boost. Populate it from the nominal frequency in
>> amd-pstate and cppc_cpufreq, the maximum non-turbo frequency in
>> intel_pstate, and the highest frequency-table entry in acpi-cpufreq.
>>
>> Use this value when arch_scale_freq_ref() returns zero. Preserve the
>> existing cpuinfo.max_freq fallback for drivers that leave the new field
>> at zero.
>>
>> Tested with acpi-cpufreq, intel_pstate, and amd-pstate in active and
>> passive modes. With no additional frequency limit, pressure is zero.
>> With a fixed limit below the non-boost reference frequency, pressure
>> remains unchanged across boost transitions.
>
> Which may not be what is intended.
Same as above: IMO, with a fixed cap, the pressure should not change
just because boost is toggled.
Thanks
Jianyong
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
2026-09-18 4:08 ` Jianyong Wu
@ 2026-09-18 18:19 ` Rafael J. Wysocki
0 siblings, 0 replies; 8+ messages in thread
From: Rafael J. Wysocki @ 2026-09-18 18:19 UTC (permalink / raw)
To: Jianyong Wu, Ricardo Neri
Cc: Vincent Guittot, viresh.kumar, kprateek.nayak, linux-pm,
linux-kernel, ray.huang, mario.limonciello, perry.yuan, zhanjie9,
zhenglifeng1, pierre.gondois, sumitg, srinivas.pandruvada,
hongyan.xia, zhongqiu.han, Fengyu Wang, Yuan Zhong, Huangsj
On Friday, September 18, 2026 6:08:49 AM Central European Summer Time Jianyong Wu wrote:
> Hi Rafael,
>
> >
> > On Sep 18, 2026, at 01:38, Rafael J. Wysocki (Intel) <rafael@kernel.org> wrote:
> > On Tue, Sep 15, 2026 at 9:03 AM Jianyong Wu <wujianyong@hygon.cn> wrote:
> >>
> >> Commit d2d5c129d07e ("cpufreq: Make cpufreq_update_pressure() fall
> >> back to cpuinfo.max_freq") introduced cpuinfo.max_freq as the reference
> >> frequency for cpufreq pressure when arch_scale_freq_ref() returns zero.
> >>
> >> However, cpuinfo.max_freq may include boost frequencies and therefore
> >> does not necessarily represent the maximum sustainable frequency.
> >
> > And then it really matters what is sustainable and for how long.
>
> I think it's confusing to say "sustainable freq" in cpufreq part. I mean the maximum
> cpu frequency below boost here. For acpi-cpufreq, it’s P0. For amd-pstate, it’s
> nominal frequency. But I can't find a better word.
>
> >
> >> On some systems using acpi-cpufreq, cpuinfo.max_freq includes boost while
> >> the frequency table only contains non-boost frequencies.
> >
> > In which case selecting freq_table[0] may give the processor a license
> > to go to the turbo (or boost) frequency range.
>
> Yeah, selecting freq_table[0] may also mean cpu can go to boost frequency.
> But the value doesn't denote that. freq_table[0] is assigned to policy->max which
> is compared with policy->cpuinfo.max_freq. The difference between them makes
> the cpu pressure which is not intended.
>
> >
> >> Consequently, cpufreq pressure remains nonzero even without an additional
> >> frequency limit.
> >
> > So when and where does this matter?
>
> I test it on amd, intel and hygon box. Once acpi-cpufreq is used, the unexpected
> cpu pressure appears when there is no cpu frequency capped and boost is enabled.
>
> The wrong cpu pressure affects load balancing. For example, Cache aware
> scheduling wants to aggregate task in a LLC using 50% of the whole LLC capacity.
> Before commit d2d5c129d07e, everything is OK. But with that commit and using
> acpi-cpufreq and with boost on, cache aware scheduling can’t aggregate
> task to occupy 50% of the LLC by default as the cpu capacity in the LLC is reduced.
So actually the problem is that now the pressure is applied when it is not
expected to be applied in general.
Clearly, the scheduler assumes that the pressure will be zero when
arch_scale_freq_ref() is zero and the commit in question violates that
assumption.
This actually has a little to do with boost and making it depend on boost
doesn't really help. In fact, the reason for making the change was some
inadequate behavior when intel_pstate ran with asym capacity, so something
like the patch below (completely untested) can be used to limit the scope
of it to the case in question.
Can you please check if it helps?
Ricardo, can you please test this one too?
Thanks!
---
drivers/cpufreq/cpufreq.c | 4 ++--
drivers/cpufreq/intel_pstate.c | 12 ++++++++++++
include/linux/cpufreq.h | 3 +++
3 files changed, 17 insertions(+), 2 deletions(-)
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2590,8 +2590,8 @@ static void cpufreq_update_pressure(stru
cpu = cpumask_first(policy->related_cpus);
max_freq = arch_scale_freq_ref(cpu);
- if (!max_freq)
- max_freq = policy->cpuinfo.max_freq;
+ if (!max_freq && cpufreq_driver->scale_freq_ref)
+ max_freq = cpufreq_driver->scale_freq_ref(policy);
capped_freq = policy->max;
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1135,6 +1135,16 @@ static bool hybrid_clear_max_perf_cpu(vo
return ret;
}
+static unsigned int intel_pstate_scale_freq_ref(struct cpufreq_policy *policy)
+{
+ struct cpudata *cpu = all_cpu_data[policy->cpu];
+
+ if (cpu && cpu->capacity_perf)
+ return policy->cpuinfo.max_freq;
+
+ return 0;
+}
+
static void intel_pstate_update_freq_limits(struct cpudata *cpu)
{
int scaling = cpu->pstate.scaling;
@@ -3088,6 +3098,7 @@ static struct cpufreq_driver intel_pstat
.offline = intel_pstate_cpu_offline,
.online = intel_pstate_cpu_online,
.update_limits = intel_pstate_update_limits,
+ .scale_freq_ref = intel_pstate_scale_freq_ref,
.name = "intel_pstate",
};
@@ -3411,6 +3422,7 @@ static struct cpufreq_driver intel_cpufr
.suspend = intel_cpufreq_suspend,
.resume = intel_pstate_resume,
.update_limits = intel_pstate_update_limits,
+ .scale_freq_ref = intel_pstate_scale_freq_ref,
.name = "intel_cpufreq",
};
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -420,6 +420,9 @@ struct cpufreq_driver {
/* Will be called after the driver is fully initialized */
void (*ready)(struct cpufreq_policy *policy);
+ /* Return the capacity reference frequency for policy. */
+ unsigned int (*scale_freq_ref)(struct cpufreq_policy *policy);
+
struct freq_attr **attr;
/* platform specific boost support code */
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-18 18:19 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 6:57 [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation Jianyong Wu
2026-09-15 9:32 ` Hongyan Xia
2026-09-15 12:46 ` Jianyong Wu
2026-09-17 17:38 ` Rafael J. Wysocki (Intel)
2026-09-17 18:34 ` Mario Limonciello
2026-09-18 5:59 ` Jianyong Wu
2026-09-18 4:08 ` Jianyong Wu
2026-09-18 18:19 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®