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

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]>
> 
> When policy->freq_table is built in acpi_cpufreq_cpu_init(), entries
> with duplicate frequencies are skipped. For each remaining entry,

To be precise for applying if needed.

"entries with duplicate frequencies are skipped.

-->

entries that are not lower in frequency than the previous one are
skipped."


> freq_table[].driver_data stores the original ACPI P-state index, so the
> index space of freq_table no longer matches perf->states[].
> 
> extract_io() currently walks perf->states[] with index i and uses the
> same i to index policy->freq_table[i]. When duplicate frequencies
> exist, this can associate a P-state status with the frequency of a
> different P-state. It can also access an invalid or sentinel entry in
> freq_table when the number of entries in perf->states[] is greater than
> the number of entries remaining in the frequency table.
> 
> extract_io() is used on ACPI_ADR_SPACE_SYSTEM_IO platforms by the
> frequency verification path, which is enabled by the
> acpi_pstate_strict module parameter. With the mismatched lookup,
> check_freqs() can fail to match the frequency of the P-state that
> drv_write() has already programmed. It then retries the check for all
> iterations before returning -EAGAIN, 

Small nit, just for applying if needed.

"It then retries the check for all iterations before returning -EAGAIN,"

-->

"It then sleeps through all 100 iterations - at least
~1 ms of usleep_range() plus 100 cross-CPU calls and I/O port reads, all
with policy->rwsem held, and .target_index() returns -EAGAIN,"


leaving perf->state at its
> previous value while the hardware is running at the newly requested
> P-state.
> 
> The cpufreq core consequently keeps policy->cur at the old frequency.
> Since __cpufreq_driver_target() returns early when the requested
> frequency equals policy->cur, the driver is not called again for that
> frequency and the control register is not rewritten. The hardware can
> therefore remain at a frequency that differs from the frequency known
> to the cpufreq core.
> 
> Fix this by iterating over policy->freq_table and using
> pos->driver_data as the original ACPI P-state index when accessing
> perf->states[], as extract_msr() already does.
> 
> Fixes: fe27cb358835 ("[CPUFREQ][2/8] acpi: reorganize code to make MSR support addition easier")
> Signed-off-by: Li RongQing <[email protected]>

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

> ---
>   drivers/cpufreq/acpi-cpufreq.c | 9 ++++-----
>   1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
> index 10ea603..a797bb2 100644
> --- a/drivers/cpufreq/acpi-cpufreq.c
> +++ b/drivers/cpufreq/acpi-cpufreq.c
> @@ -197,14 +197,13 @@ static unsigned extract_io(struct cpufreq_policy *policy, u32 value)
>   {
>   	struct acpi_cpufreq_data *data = policy->driver_data;
>   	struct acpi_processor_performance *perf;
> -	int i;
> +	struct cpufreq_frequency_table *pos;
>   
>   	perf = to_perf_data(data);
>   
> -	for (i = 0; i < perf->state_count; i++) {
> -		if (value == perf->states[i].status)
> -			return policy->freq_table[i].frequency;
> -	}
> +	cpufreq_for_each_entry(pos, policy->freq_table)
> +		if (value == perf->states[pos->driver_data].status)
> +			return pos->frequency;
>   	return 0;
>   }
>   


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