Commit 8f44619e authored by Andreas Herrmann's avatar Andreas Herrmann Committed by Greg Kroah-Hartman

powernow-k8: Fix indexing issue

commit a8eb2848 upstream.

The driver uses the pstate number from the status register as index in
its table of ACPI pstates (powernow_table). This is wrong as this is
not a 1-to-1 mapping.

For example we can have _PSS information to just utilize Pstate 0 and
Pstate 4, ie.

  powernow-k8: Core Performance Boosting: on.
  powernow-k8:    0 : pstate 0 (2200 MHz)
  powernow-k8:    1 : pstate 4 (1400 MHz)

In this example the driver's powernow_table has just 2 entries. Using
the pstate number (4) as index into this table is just plain wrong.
Signed-off-by: default avatarAndreas Herrmann <andreas.herrmann3@amd.com>
Signed-off-by: default avatarDave Jones <davej@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent af2ff521
...@@ -54,6 +54,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); ...@@ -54,6 +54,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
static int cpu_family = CPU_OPTERON; static int cpu_family = CPU_OPTERON;
/* array to map SW pstate number to acpi state */
static u32 ps_to_as[8];
/* core performance boost */ /* core performance boost */
static bool cpb_capable, cpb_enabled; static bool cpb_capable, cpb_enabled;
static struct msr __percpu *msrs; static struct msr __percpu *msrs;
...@@ -80,9 +83,9 @@ static u32 find_khz_freq_from_fid(u32 fid) ...@@ -80,9 +83,9 @@ static u32 find_khz_freq_from_fid(u32 fid)
} }
static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data, static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
u32 pstate) u32 pstate)
{ {
return data[pstate].frequency; return data[ps_to_as[pstate]].frequency;
} }
/* Return the vco fid for an input fid /* Return the vco fid for an input fid
...@@ -926,6 +929,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, ...@@ -926,6 +929,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
invalidate_entry(powernow_table, i); invalidate_entry(powernow_table, i);
continue; continue;
} }
ps_to_as[index] = i;
/* Frequency may be rounded for these */ /* Frequency may be rounded for these */
if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
|| boot_cpu_data.x86 == 0x11) { || boot_cpu_data.x86 == 0x11) {
...@@ -1190,7 +1196,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, ...@@ -1190,7 +1196,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
powernow_k8_acpi_pst_values(data, newstate); powernow_k8_acpi_pst_values(data, newstate);
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
ret = transition_frequency_pstate(data, newstate); ret = transition_frequency_pstate(data,
data->powernow_table[newstate].index);
else else
ret = transition_frequency_fidvid(data, newstate); ret = transition_frequency_fidvid(data, newstate);
if (ret) { if (ret) {
...@@ -1203,7 +1210,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, ...@@ -1203,7 +1210,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpu_family == CPU_HW_PSTATE) if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_pstate(data->powernow_table, pol->cur = find_khz_freq_from_pstate(data->powernow_table,
newstate); data->powernow_table[newstate].index);
else else
pol->cur = find_khz_freq_from_fid(data->currfid); pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0; ret = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment