aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index e6ea00edcb54..ea19d091fd41 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -32,6 +32,7 @@
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/compiler.h> 33#include <linux/compiler.h>
34#include <linux/sched.h> /* current */ 34#include <linux/sched.h> /* current */
35#include <linux/dmi.h>
35#include <asm/io.h> 36#include <asm/io.h>
36#include <asm/delay.h> 37#include <asm/delay.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -387,6 +388,33 @@ static int acpi_cpufreq_early_init_acpi(void)
387 return acpi_processor_preregister_performance(acpi_perf_data); 388 return acpi_processor_preregister_performance(acpi_perf_data);
388} 389}
389 390
391/*
392 * Some BIOSes do SW_ANY coordination internally, either set it up in hw
393 * or do it in BIOS firmware and won't inform about it to OS. If not
394 * detected, this has a side effect of making CPU run at a different speed
395 * than OS intended it to run at. Detect it and handle it cleanly.
396 */
397static int bios_with_sw_any_bug;
398
399static int __init sw_any_bug_found(struct dmi_system_id *d)
400{
401 bios_with_sw_any_bug = 1;
402 return 0;
403}
404
405static struct dmi_system_id __initdata sw_any_bug_dmi_table[] = {
406 {
407 .callback = sw_any_bug_found,
408 .ident = "Supermicro Server X6DLP",
409 .matches = {
410 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
411 DMI_MATCH(DMI_BIOS_VERSION, "080010"),
412 DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
413 },
414 },
415 { }
416};
417
390static int 418static int
391acpi_cpufreq_cpu_init ( 419acpi_cpufreq_cpu_init (
392 struct cpufreq_policy *policy) 420 struct cpufreq_policy *policy)
@@ -422,8 +450,17 @@ acpi_cpufreq_cpu_init (
422 * coordination is required. 450 * coordination is required.
423 */ 451 */
424 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || 452 if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
425 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) 453 policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
426 policy->cpus = perf->shared_cpu_map; 454 policy->cpus = perf->shared_cpu_map;
455 }
456
457#ifdef CONFIG_SMP
458 dmi_check_system(sw_any_bug_dmi_table);
459 if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
460 policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
461 policy->cpus = cpu_core_map[cpu];
462 }
463#endif
427 464
428 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { 465 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
429 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; 466 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;