[PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation

Jianyong Wu posted 1 patch 1 week, 3 days ago
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(-)
[PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Jianyong Wu 1 week, 3 days ago
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
Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Rafael J. Wysocki (Intel) 1 week ago
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
>
>
Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Jianyong Wu 1 week ago
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

Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Rafael J. Wysocki 6 days, 13 hours ago
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 */
RE: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Jianyong Wu 3 days, 23 hours ago

On Fri, Sep 18, 2026, Rafael J. Wysocki wrote:
> So actually the problem is that now the pressure is applied when it is not
> expected to be applied in general.
> 
Yes.

> 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?

Yes it helps.

I tested it on Hygon and an AMD system using acpi-cpufreq. The cpu
pressure is zero again, and cache aware scheduling can once more
aggregate tasks up to 50% of the LLC capacity, as it did before
d2d5c129d07e.

Tested-by: Jianyong Wu <wujianyong@hygon.cn>

Thanks
Jianyong
Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Mario Limonciello 1 week ago

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
>>
>>

Re: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Hongyan Xia 1 week, 2 days ago
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>

> ---
> [...]
RE: [PATCH] cpufreq: Use a non-boost reference frequency for pressure calculation
Posted by Jianyong Wu 1 week, 2 days ago
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>
> 
> > ---
> > [...]