diff options
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c')
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 39 |
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 | */ | ||
397 | static int bios_with_sw_any_bug; | ||
398 | |||
399 | static int __init sw_any_bug_found(struct dmi_system_id *d) | ||
400 | { | ||
401 | bios_with_sw_any_bug = 1; | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static 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 | |||
390 | static int | 418 | static int |
391 | acpi_cpufreq_cpu_init ( | 419 | acpi_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; |