From 2d8a3a209b35f8301c86e7962f636a372a0d7cad Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 6 Jan 2012 15:56:31 +0100 Subject: powernow-k8: Avoid Pstate MSR accesses on systems supporting CPB commit 201bf0f129e1715a33568d1563d9a75b840ab4d3 upstream. Due to CPB we can't directly map SW Pstates to Pstate MSRs. Get rid of the paranoia check. (assuming that the ACPI Pstate information is correct.) Signed-off-by: Andreas Herrmann Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/powernow-k8.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index bce576d..e0329f9 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -926,23 +926,24 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, invalidate_entry(powernow_table, i); continue; } - rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); - if (!(hi & HW_PSTATE_VALID_MASK)) { - pr_debug("invalid pstate %d, ignoring\n", index); - invalidate_entry(powernow_table, i); - continue; - } - - powernow_table[i].index = index; - /* Frequency may be rounded for these */ if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || boot_cpu_data.x86 == 0x11) { + + rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); + if (!(hi & HW_PSTATE_VALID_MASK)) { + pr_debug("invalid pstate %d, ignoring\n", index); + invalidate_entry(powernow_table, i); + continue; + } + powernow_table[i].frequency = freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); } else powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; + + powernow_table[i].index = index; } return 0; } -- cgit v1.1 From 323a479328cbc2fb5cf647790f7414ca570a577b Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 6 Jan 2012 15:57:55 +0100 Subject: powernow-k8: Fix indexing issue commit a8eb28480e9b637cc78b9aa5e08612ba97e1317a 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: Andreas Herrmann Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/powernow-k8.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index e0329f9..ad683ec 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -54,6 +54,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); static int cpu_family = CPU_OPTERON; +/* array to map SW pstate number to acpi state */ +static u32 ps_to_as[8]; + /* core performance boost */ static bool cpb_capable, cpb_enabled; static struct msr __percpu *msrs; @@ -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, - u32 pstate) + u32 pstate) { - return data[pstate].frequency; + return data[ps_to_as[pstate]].frequency; } /* Return the vco fid for an input fid @@ -926,6 +929,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, invalidate_entry(powernow_table, i); continue; } + + ps_to_as[index] = i; + /* Frequency may be rounded for these */ if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || boot_cpu_data.x86 == 0x11) { @@ -1190,7 +1196,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, powernow_k8_acpi_pst_values(data, newstate); if (cpu_family == CPU_HW_PSTATE) - ret = transition_frequency_pstate(data, newstate); + ret = transition_frequency_pstate(data, + data->powernow_table[newstate].index); else ret = transition_frequency_fidvid(data, newstate); if (ret) { @@ -1203,7 +1210,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, if (cpu_family == CPU_HW_PSTATE) pol->cur = find_khz_freq_from_pstate(data->powernow_table, - newstate); + data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); ret = 0; -- cgit v1.1