Re: [PATCH v3 2/2] cpufreq: acpi-cpufreq: fix P-state index mismatch in get_cur_freq_on_cpu()

Zhongqiu Han <[email protected]>
Newsgroups org.kernel.vger.linux-pm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 8/20/2026 10:07 AM, lirongqing wrote:
> From: Li RongQing <[email protected]>
> 
> get_cur_freq_on_cpu() uses perf->state, which is an index into
> perf->states[], to index policy->freq_table[]. However, freq_table[]
> is built by filtering _PSS entries with duplicate frequencies, so its

To be precise for applying if needed.

"However, freq_table[] is built by filtering _PSS entries with duplicate
frequencies"

-->

"However, freq_table[] is built by filtering _PSS entries that are not
lower in frequency than the previous one."

> index space no longer matches perf->states[]. The original P-state
> index for each remaining freq_table entry is stored in driver_data.
> 
> Once an entry has been skipped, using perf->state as an index into
> freq_table[] can therefore select the frequency of a different
> P-state.
> 
> The reported current frequency itself remains correct because it is
> obtained from extract_freq(). The mismatch only affects the cached
> frequency used by get_cur_freq_on_cpu() to detect a firmware frequency
> change behind our back, through data->resume.

Just for applying if needed, deleting "through data->resume."


> 
> If the wrong table entry contains a frequency different from the one
> the CPU is actually running at, the check falsely detects a frequency
> change and sets data->resume. The next ->target() call then performs a
> redundant control-register write even if the requested P-state is
> already the current P-state.
> 
> Conversely, if the wrong table entry happens to contain the frequency
> to which firmware has changed the CPU, the frequency change is missed
> and data->resume remains clear. A subsequent ->target() call for the
> P-state that the cpufreq core believes to be current can then
> short-circuit without rewriting the control register, leaving the CPU
> at the firmware-selected frequency until a different P-state is
> requested.
> 
> Fix this by taking the cached frequency directly from
> perf->states[perf->state].core_frequency. perf->state and
> perf->states[] use the same P-state index space, and converting
> core_frequency to kHz yields the same value stored in the corresponding
> freq_table entry during initialization.
> 
> Fixes: e56a727b023d ("[CPUFREQ] Make acpi-cpufreq more robust against BIOS freq changes behind our back.")
> Reported-by: Zhongqiu Han <[email protected]>
> Suggested-by: Zhongqiu Han <[email protected]>
> Signed-off-by: Li RongQing <[email protected]>

Reviewed-by: Zhongqiu Han <[email protected]>


> ---
>   drivers/cpufreq/acpi-cpufreq.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
> index a797bb2..3313c74 100644
> --- a/drivers/cpufreq/acpi-cpufreq.c
> +++ b/drivers/cpufreq/acpi-cpufreq.c
> @@ -353,6 +353,7 @@ static u32 get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *dat
>   
>   static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
>   {
> +	struct acpi_processor_performance *perf;
>   	struct acpi_cpufreq_data *data;
>   	struct cpufreq_policy *policy;
>   	unsigned int freq;
> @@ -368,7 +369,9 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
>   	if (unlikely(!data || !policy->freq_table))
>   		return 0;
>   
> -	cached_freq = policy->freq_table[to_perf_data(data)->state].frequency;
> +	perf = to_perf_data(data);
> +	cached_freq = perf->states[perf->state].core_frequency * 1000;
> +
>   	freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data));
>   	if (freq != cached_freq) {
>   		/*


-- 
Thx and BRs,
Zhongqiu Han
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.