aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorHanjun Guo <hanjun.guo@linaro.org>2014-07-18 06:02:54 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-07-21 07:50:58 -0400
commit46ba51ea8f8639da32c55744b35479fdfb4e7232 (patch)
treea1544217bd2406bb63eca797c7206acb9313e6d2 /drivers/acpi
parentb50154d53e668314542ef9a592accc37137a8f65 (diff)
ACPI / processor: Introduce ARCH_MIGHT_HAVE_ACPI_PDC
The use of _PDC is deprecated in ACPI 3.0 in favor of _OSC, as ARM platform is supported only in ACPI 5.0 or higher version, _PDC will not be used in ARM platform, so make Make _PDC only for platforms with Intel CPUs. Introduce ARCH_MIGHT_HAVE_ACPI_PDC and move _PDC related code in ACPI processor driver into a single file processor_pdc.c, make x86 and ia64 select it when ACPI is enabled. This patch also use pr_* to replace printk to fix the checkpatch warning and factor acpi_processor_alloc_pdc() a little bit to avoid duplicate pr_err() code. Suggested-by: Robert Richter <rric@kernel.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig3
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/internal.h5
-rw-r--r--drivers/acpi/processor_core.c198
-rw-r--r--drivers/acpi/processor_pdc.c206
5 files changed, 215 insertions, 198 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 970524c54bfa..3f5f745bbbea 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -45,6 +45,9 @@ if ACPI
45config ACPI_LEGACY_TABLES_LOOKUP 45config ACPI_LEGACY_TABLES_LOOKUP
46 bool 46 bool
47 47
48config ARCH_MIGHT_HAVE_ACPI_PDC
49 bool
50
48config ACPI_SLEEP 51config ACPI_SLEEP
49 bool 52 bool
50 depends on SUSPEND || HIBERNATION 53 depends on SUSPEND || HIBERNATION
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index ea55e0179f81..505d4d79fe3e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -36,6 +36,7 @@ acpi-y += scan.o
36acpi-y += resource.o 36acpi-y += resource.o
37acpi-y += acpi_processor.o 37acpi-y += acpi_processor.o
38acpi-y += processor_core.o 38acpi-y += processor_core.o
39acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
39acpi-y += ec.o 40acpi-y += ec.o
40acpi-$(CONFIG_ACPI_DOCK) += dock.o 41acpi-$(CONFIG_ACPI_DOCK) += dock.o
41acpi-y += pci_root.o pci_link.o pci_irq.o 42acpi-y += pci_root.o pci_link.o pci_irq.o
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 7de5b603f272..64ee3eed18de 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -108,7 +108,12 @@ int acpi_power_transition(struct acpi_device *device, int state);
108int acpi_device_update_power(struct acpi_device *device, int *state_p); 108int acpi_device_update_power(struct acpi_device *device, int *state_p);
109 109
110int acpi_wakeup_device_init(void); 110int acpi_wakeup_device_init(void);
111
112#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
111void acpi_early_processor_set_pdc(void); 113void acpi_early_processor_set_pdc(void);
114#else
115static inline void acpi_early_processor_set_pdc(void) {}
116#endif
112 117
113/* -------------------------------------------------------------------------- 118/* --------------------------------------------------------------------------
114 Embedded Controller 119 Embedded Controller
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 71e2065639a6..00f48d13a516 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -4,17 +4,11 @@
4 * 4 *
5 * Alex Chiang <achiang@hp.com> 5 * Alex Chiang <achiang@hp.com>
6 * - Unified x86/ia64 implementations 6 * - Unified x86/ia64 implementations
7 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
8 * - Added _PDC for platforms with Intel CPUs
9 */ 7 */
10#include <linux/export.h> 8#include <linux/export.h>
11#include <linux/dmi.h>
12#include <linux/slab.h>
13#include <linux/acpi.h> 9#include <linux/acpi.h>
14#include <acpi/processor.h> 10#include <acpi/processor.h>
15 11
16#include "internal.h"
17
18#define _COMPONENT ACPI_PROCESSOR_COMPONENT 12#define _COMPONENT ACPI_PROCESSOR_COMPONENT
19ACPI_MODULE_NAME("processor_core"); 13ACPI_MODULE_NAME("processor_core");
20 14
@@ -208,195 +202,3 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
208 return acpi_map_cpuid(apic_id, acpi_id); 202 return acpi_map_cpuid(apic_id, acpi_id);
209} 203}
210EXPORT_SYMBOL_GPL(acpi_get_cpuid); 204EXPORT_SYMBOL_GPL(acpi_get_cpuid);
211
212static bool __init processor_physically_present(acpi_handle handle)
213{
214 int cpuid, type;
215 u32 acpi_id;
216 acpi_status status;
217 acpi_object_type acpi_type;
218 unsigned long long tmp;
219 union acpi_object object = { 0 };
220 struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
221
222 status = acpi_get_type(handle, &acpi_type);
223 if (ACPI_FAILURE(status))
224 return false;
225
226 switch (acpi_type) {
227 case ACPI_TYPE_PROCESSOR:
228 status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
229 if (ACPI_FAILURE(status))
230 return false;
231 acpi_id = object.processor.proc_id;
232 break;
233 case ACPI_TYPE_DEVICE:
234 status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
235 if (ACPI_FAILURE(status))
236 return false;
237 acpi_id = tmp;
238 break;
239 default:
240 return false;
241 }
242
243 type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
244 cpuid = acpi_get_cpuid(handle, type, acpi_id);
245
246 if (cpuid == -1)
247 return false;
248
249 return true;
250}
251
252static void acpi_set_pdc_bits(u32 *buf)
253{
254 buf[0] = ACPI_PDC_REVISION_ID;
255 buf[1] = 1;
256
257 /* Enable coordination with firmware's _TSD info */
258 buf[2] = ACPI_PDC_SMP_T_SWCOORD;
259
260 /* Twiddle arch-specific bits needed for _PDC */
261 arch_acpi_set_pdc_bits(buf);
262}
263
264static struct acpi_object_list *acpi_processor_alloc_pdc(void)
265{
266 struct acpi_object_list *obj_list;
267 union acpi_object *obj;
268 u32 *buf;
269
270 /* allocate and initialize pdc. It will be used later. */
271 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
272 if (!obj_list) {
273 printk(KERN_ERR "Memory allocation error\n");
274 return NULL;
275 }
276
277 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
278 if (!obj) {
279 printk(KERN_ERR "Memory allocation error\n");
280 kfree(obj_list);
281 return NULL;
282 }
283
284 buf = kmalloc(12, GFP_KERNEL);
285 if (!buf) {
286 printk(KERN_ERR "Memory allocation error\n");
287 kfree(obj);
288 kfree(obj_list);
289 return NULL;
290 }
291
292 acpi_set_pdc_bits(buf);
293
294 obj->type = ACPI_TYPE_BUFFER;
295 obj->buffer.length = 12;
296 obj->buffer.pointer = (u8 *) buf;
297 obj_list->count = 1;
298 obj_list->pointer = obj;
299
300 return obj_list;
301}
302
303/*
304 * _PDC is required for a BIOS-OS handshake for most of the newer
305 * ACPI processor features.
306 */
307static acpi_status
308acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
309{
310 acpi_status status = AE_OK;
311
312 if (boot_option_idle_override == IDLE_NOMWAIT) {
313 /*
314 * If mwait is disabled for CPU C-states, the C2C3_FFH access
315 * mode will be disabled in the parameter of _PDC object.
316 * Of course C1_FFH access mode will also be disabled.
317 */
318 union acpi_object *obj;
319 u32 *buffer = NULL;
320
321 obj = pdc_in->pointer;
322 buffer = (u32 *)(obj->buffer.pointer);
323 buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
324
325 }
326 status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
327
328 if (ACPI_FAILURE(status))
329 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
330 "Could not evaluate _PDC, using legacy perf. control.\n"));
331
332 return status;
333}
334
335void acpi_processor_set_pdc(acpi_handle handle)
336{
337 struct acpi_object_list *obj_list;
338
339 if (arch_has_acpi_pdc() == false)
340 return;
341
342 obj_list = acpi_processor_alloc_pdc();
343 if (!obj_list)
344 return;
345
346 acpi_processor_eval_pdc(handle, obj_list);
347
348 kfree(obj_list->pointer->buffer.pointer);
349 kfree(obj_list->pointer);
350 kfree(obj_list);
351}
352
353static acpi_status __init
354early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
355{
356 if (processor_physically_present(handle) == false)
357 return AE_OK;
358
359 acpi_processor_set_pdc(handle);
360 return AE_OK;
361}
362
363#if defined(CONFIG_X86) || defined(CONFIG_IA64)
364static int __init set_no_mwait(const struct dmi_system_id *id)
365{
366 pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n",
367 id->ident);
368 boot_option_idle_override = IDLE_NOMWAIT;
369 return 0;
370}
371
372static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
373 {
374 set_no_mwait, "Extensa 5220", {
375 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
376 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
377 DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
378 DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
379 {},
380};
381
382static void __init processor_dmi_check(void)
383{
384 /*
385 * Check whether the system is DMI table. If yes, OSPM
386 * should not use mwait for CPU-states.
387 */
388 dmi_check_system(processor_idle_dmi_table);
389}
390#else
391static inline void processor_dmi_check(void) {}
392#endif
393
394void __init acpi_early_processor_set_pdc(void)
395{
396 processor_dmi_check();
397
398 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
399 ACPI_UINT32_MAX,
400 early_init_pdc, NULL, NULL, NULL);
401 acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
402}
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
new file mode 100644
index 000000000000..e5dd80800930
--- /dev/null
+++ b/drivers/acpi/processor_pdc.c
@@ -0,0 +1,206 @@
1/*
2 * Copyright (C) 2005 Intel Corporation
3 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
4 *
5 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
6 * - Added _PDC for platforms with Intel CPUs
7 */
8
9#define pr_fmt(fmt) "ACPI: " fmt
10
11#include <linux/dmi.h>
12#include <linux/slab.h>
13#include <linux/acpi.h>
14#include <acpi/processor.h>
15
16#include "internal.h"
17
18#define _COMPONENT ACPI_PROCESSOR_COMPONENT
19ACPI_MODULE_NAME("processor_pdc");
20
21static bool __init processor_physically_present(acpi_handle handle)
22{
23 int cpuid, type;
24 u32 acpi_id;
25 acpi_status status;
26 acpi_object_type acpi_type;
27 unsigned long long tmp;
28 union acpi_object object = { 0 };
29 struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
30
31 status = acpi_get_type(handle, &acpi_type);
32 if (ACPI_FAILURE(status))
33 return false;
34
35 switch (acpi_type) {
36 case ACPI_TYPE_PROCESSOR:
37 status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
38 if (ACPI_FAILURE(status))
39 return false;
40 acpi_id = object.processor.proc_id;
41 break;
42 case ACPI_TYPE_DEVICE:
43 status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
44 if (ACPI_FAILURE(status))
45 return false;
46 acpi_id = tmp;
47 break;
48 default:
49 return false;
50 }
51
52 type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
53 cpuid = acpi_get_cpuid(handle, type, acpi_id);
54
55 if (cpuid == -1)
56 return false;
57
58 return true;
59}
60
61static void acpi_set_pdc_bits(u32 *buf)
62{
63 buf[0] = ACPI_PDC_REVISION_ID;
64 buf[1] = 1;
65
66 /* Enable coordination with firmware's _TSD info */
67 buf[2] = ACPI_PDC_SMP_T_SWCOORD;
68
69 /* Twiddle arch-specific bits needed for _PDC */
70 arch_acpi_set_pdc_bits(buf);
71}
72
73static struct acpi_object_list *acpi_processor_alloc_pdc(void)
74{
75 struct acpi_object_list *obj_list;
76 union acpi_object *obj;
77 u32 *buf;
78
79 /* allocate and initialize pdc. It will be used later. */
80 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
81 if (!obj_list)
82 goto out;
83
84 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
85 if (!obj) {
86 kfree(obj_list);
87 goto out;
88 }
89
90 buf = kmalloc(12, GFP_KERNEL);
91 if (!buf) {
92 kfree(obj);
93 kfree(obj_list);
94 goto out;
95 }
96
97 acpi_set_pdc_bits(buf);
98
99 obj->type = ACPI_TYPE_BUFFER;
100 obj->buffer.length = 12;
101 obj->buffer.pointer = (u8 *) buf;
102 obj_list->count = 1;
103 obj_list->pointer = obj;
104
105 return obj_list;
106out:
107 pr_err("Memory allocation error\n");
108 return NULL;
109}
110
111/*
112 * _PDC is required for a BIOS-OS handshake for most of the newer
113 * ACPI processor features.
114 */
115static acpi_status
116acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
117{
118 acpi_status status = AE_OK;
119
120 if (boot_option_idle_override == IDLE_NOMWAIT) {
121 /*
122 * If mwait is disabled for CPU C-states, the C2C3_FFH access
123 * mode will be disabled in the parameter of _PDC object.
124 * Of course C1_FFH access mode will also be disabled.
125 */
126 union acpi_object *obj;
127 u32 *buffer = NULL;
128
129 obj = pdc_in->pointer;
130 buffer = (u32 *)(obj->buffer.pointer);
131 buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
132
133 }
134 status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
135
136 if (ACPI_FAILURE(status))
137 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
138 "Could not evaluate _PDC, using legacy perf. control.\n"));
139
140 return status;
141}
142
143void acpi_processor_set_pdc(acpi_handle handle)
144{
145 struct acpi_object_list *obj_list;
146
147 if (arch_has_acpi_pdc() == false)
148 return;
149
150 obj_list = acpi_processor_alloc_pdc();
151 if (!obj_list)
152 return;
153
154 acpi_processor_eval_pdc(handle, obj_list);
155
156 kfree(obj_list->pointer->buffer.pointer);
157 kfree(obj_list->pointer);
158 kfree(obj_list);
159}
160
161static acpi_status __init
162early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
163{
164 if (processor_physically_present(handle) == false)
165 return AE_OK;
166
167 acpi_processor_set_pdc(handle);
168 return AE_OK;
169}
170
171static int __init set_no_mwait(const struct dmi_system_id *id)
172{
173 pr_notice("%s detected - disabling mwait for CPU C-states\n",
174 id->ident);
175 boot_option_idle_override = IDLE_NOMWAIT;
176 return 0;
177}
178
179static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
180 {
181 set_no_mwait, "Extensa 5220", {
182 DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
183 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
184 DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
185 DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
186 {},
187};
188
189static void __init processor_dmi_check(void)
190{
191 /*
192 * Check whether the system is DMI table. If yes, OSPM
193 * should not use mwait for CPU-states.
194 */
195 dmi_check_system(processor_idle_dmi_table);
196}
197
198void __init acpi_early_processor_set_pdc(void)
199{
200 processor_dmi_check();
201
202 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
203 ACPI_UINT32_MAX,
204 early_init_pdc, NULL, NULL, NULL);
205 acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
206}