aboutsummaryrefslogtreecommitdiff
path: root/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 17:50:22 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 17:50:22 -0700
commit2ee8099f2c2bc74a7c2fac7f83e12a5d651681d3 (patch)
tree433ebb87a3d5d02e7df3700c846ac9af632c55f3 /arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
parentc03efdb202a4882f426ce49766859af4058c9b8a (diff)
parent24669f7d00d387799fc6a39452ab22d7f078f043 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq: [CPUFREQ] sw_any_bug_dmi_table can be used on resume, so it isn't initdata [CPUFREQ] Fix some more CPU hotplug locking. [CPUFREQ] Workaround for BIOS bug in software coordination of frequency [CPUFREQ] Longhaul - Add voltage scaling to driver [CPUFREQ] Fix sparse warning in ondemand [CPUFREQ] make drivers/cpufreq/cpufreq_ondemand.c:powersave_bias_target() static [CPUFREQ] Longhaul - Add ignore_latency option [CPUFREQ] Longhaul - Disable arbiter [CPUFREQ][2/2] ondemand: updated add powersave_bias tunable [CPUFREQ][1/2] ondemand: updated tune for hardware coordination [CPUFREQ] Fix typo.
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index b77f1358bd7..7a9325349e9 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -23,6 +23,7 @@
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <acpi/processor.h>
#endif
@@ -377,6 +378,35 @@ static int centrino_cpu_early_init_acpi(void)
return 0;
}
+
+/*
+ * Some BIOSes do SW_ANY coordination internally, either set it up in hw
+ * or do it in BIOS firmware and won't inform about it to OS. If not
+ * detected, this has a side effect of making CPU run at a different speed
+ * than OS intended it to run at. Detect it and handle it cleanly.
+ */
+static int bios_with_sw_any_bug;
+static int __init sw_any_bug_found(struct dmi_system_id *d)
+{
+ bios_with_sw_any_bug = 1;
+ return 0;
+}
+
+
+static struct dmi_system_id sw_any_bug_dmi_table[] = {
+ {
+ .callback = sw_any_bug_found,
+ .ident = "Supermicro Server X6DLP",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+ DMI_MATCH(DMI_BIOS_VERSION, "080010"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
+ },
+ },
+ { }
+};
+
+
/*
* centrino_cpu_init_acpi - register with ACPI P-States library
*
@@ -398,14 +428,24 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
dprintk(PFX "obtaining ACPI data failed\n");
return -EIO;
}
+
policy->shared_type = p->shared_type;
/*
* Will let policy->cpus know about dependency only when software
* coordination is required.
*/
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
- policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+ policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
policy->cpus = p->shared_cpu_map;
+ }
+
+#ifdef CONFIG_SMP
+ dmi_check_system(sw_any_bug_dmi_table);
+ if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+ policy->cpus = cpu_core_map[cpu];
+ }
+#endif
/* verify the acpi_data */
if (p->state_count <= 1) {