[PATCH v2 2/2] cpufreq: acpi-cpufreq: fix P-state index mismatch in get_cur_freq_on_cpu()
lirongqing <[email protected]>
| Newsgroups | org.kernel.vger.linux-pm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Li RongQing <[email protected]> get_cur_freq_on_cpu() reads the cached frequency as policy->freq_table[to_perf_data(data)->state], mixing two different index spaces: perf->state indexes perf->states[], while policy->freq_table[] is built with duplicate frequencies removed and stores the original P-state index in freq_table[].driver_data. Once any _PSS entry has been skipped the two arrays no longer line up, so the cached frequency used to detect a "BIOS changed frequency behind our back" event could be taken from the wrong table slot. Look up the freq_table entry whose driver_data matches perf->state instead of indexing freq_table[] with perf->state directly. Fixes: 8cee1eed8e78 ("cpufreq: ACPI: Remove freq_table from acpi_cpufreq_data") Reported-by: Zhongqiu Han <[email protected]> Signed-off-by: Li RongQing <[email protected]> --- drivers/cpufreq/acpi-cpufreq.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 1abe9ab..61ede49c 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 cpufreq_frequency_table *pos; struct acpi_cpufreq_data *data; struct cpufreq_policy *policy; unsigned int freq; @@ -368,7 +369,13 @@ 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; + cached_freq = 0; + cpufreq_for_each_entry(pos, policy->freq_table) + if (pos->driver_data == to_perf_data(data)->state) { + cached_freq = pos->frequency; + break; + } + freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data)); if (freq != cached_freq) { /* -- 2.9.4