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