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