aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_pdc.c
diff options
context:
space:
mode:
authorAlex Chiang <achiang@hp.com>2009-12-20 14:19:09 -0500
committerLen Brown <len.brown@intel.com>2009-12-22 03:24:08 -0500
commit78f1699659963fff97975df44db6d5dbe7218e55 (patch)
tree929291454d6d86a523c9b3881eb8cc40d65a11fc /drivers/acpi/processor_pdc.c
parent55639353a0035052d9ea6cfe4dde0ac7fcbb2c9f (diff)
ACPI: processor: call _PDC early
We discovered that at least one machine (HP Envy), methods in the DSDT attempt to call external methods defined in a dynamically loaded SSDT. Unfortunately, the DSDT methods we are trying to call are part of the EC initialization, which happens very early, and the the dynamic SSDT is only loaded when a processor _PDC method runs much later. This results in namespace lookup errors for the (as of yet) undefined methods. Since Windows doesn't have any issues with this machine, we take it as a hint that they must be evaluating _PDC much earlier than we are. Thus, the proper thing for Linux to do should be to match the Windows implementation more closely. Provide a mechanism to call _PDC before we enable the EC. Doing so loads the dynamic tables, and allows the EC to be enabled correctly. The ACPI processor driver will still evaluate _PDC in its .add() method to cover the hotplug case. Resolves: http://bugzilla.kernel.org/show_bug.cgi?id=14824 Cc: ming.m.lin@intel.com Signed-off-by: Alex Chiang <achiang@hp.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/processor_pdc.c')
-rw-r--r--drivers/acpi/processor_pdc.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
new file mode 100644
index 000000000000..b416c32dda04
--- /dev/null
+++ b/drivers/acpi/processor_pdc.c
@@ -0,0 +1,108 @@
1#include <linux/dmi.h>
2
3#include <acpi/acpi_drivers.h>
4#include <acpi/processor.h>
5
6#include "internal.h"
7
8#define PREFIX "ACPI: "
9#define _COMPONENT ACPI_PROCESSOR_COMPONENT
10ACPI_MODULE_NAME("processor_pdc");
11
12static int set_no_mwait(const struct dmi_system_id *id)
13{
14 printk(KERN_NOTICE PREFIX "%s detected - "
15 "disabling mwait for CPU C-states\n", id->ident);
16 idle_nomwait = 1;
17 return 0;
18}
19
20static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
21 {
22 set_no_mwait, "IFL91 board", {
23 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
24 DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
25 DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
26 DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
27 {
28 set_no_mwait, "Extensa 5220", {
29 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
30 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
31 DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
32 DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
33 {},
34};
35
36/*
37 * _PDC is required for a BIOS-OS handshake for most of the newer
38 * ACPI processor features.
39 */
40static int acpi_processor_eval_pdc(struct acpi_processor *pr)
41{
42 struct acpi_object_list *pdc_in = pr->pdc;
43 acpi_status status = AE_OK;
44
45 if (!pdc_in)
46 return status;
47 if (idle_nomwait) {
48 /*
49 * If mwait is disabled for CPU C-states, the C2C3_FFH access
50 * mode will be disabled in the parameter of _PDC object.
51 * Of course C1_FFH access mode will also be disabled.
52 */
53 union acpi_object *obj;
54 u32 *buffer = NULL;
55
56 obj = pdc_in->pointer;
57 buffer = (u32 *)(obj->buffer.pointer);
58 buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
59
60 }
61 status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
62
63 if (ACPI_FAILURE(status))
64 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
65 "Could not evaluate _PDC, using legacy perf. control.\n"));
66
67 return status;
68}
69
70void acpi_processor_set_pdc(struct acpi_processor *pr)
71{
72 arch_acpi_processor_init_pdc(pr);
73 acpi_processor_eval_pdc(pr);
74 arch_acpi_processor_cleanup_pdc(pr);
75}
76EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
77
78static acpi_status
79early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
80{
81 struct acpi_processor pr;
82
83 pr.handle = handle;
84
85 /* x86 implementation looks at pr.id to determine some
86 * CPU capabilites. We can just hard code to 0 since we're
87 * assuming the CPUs in the system are homogenous and all
88 * have the same capabilities.
89 */
90 pr.id = 0;
91
92 acpi_processor_set_pdc(&pr);
93
94 return AE_OK;
95}
96
97void acpi_early_processor_set_pdc(void)
98{
99 /*
100 * Check whether the system is DMI table. If yes, OSPM
101 * should not use mwait for CPU-states.
102 */
103 dmi_check_system(processor_idle_dmi_table);
104
105 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
106 ACPI_UINT32_MAX,
107 early_init_pdc, NULL, NULL, NULL);
108}