aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>2005-10-23 16:31:00 -0400
committerLen Brown <len.brown@intel.com>2005-12-01 01:30:35 -0500
commit05131ecc99ea9da7f45ba3058fe8a2c1d0ceeab8 (patch)
treedec76975406874cf677d6391302f42a6da55ac38
parentd2149b542382bfc206cb28485108f6470c979566 (diff)
[ACPI] Avoid BIOS inflicted crashes by evaluating _PDC only once
Linux invokes the AML _PDC method (Processor Driver Capabilities) to tell the BIOS what features it can handle. While the ACPI spec says nothing about the OS invoking _PDC multiple times, doing so with changing bits seems to hopelessly confuse the BIOS on multiple platforms up to and including crashing the system. Factor out the _PDC invocation so Linux invokes it only once. http://bugzilla.kernel.org/show_bug.cgi?id=5483 Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--arch/i386/kernel/acpi/Makefile2
-rw-r--r--arch/i386/kernel/acpi/cstate.c58
-rw-r--r--arch/i386/kernel/acpi/processor.c75
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c67
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c12
-rw-r--r--arch/ia64/kernel/cpufreq/Makefile5
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c51
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-processor.c67
-rw-r--r--arch/x86_64/kernel/acpi/Makefile5
-rw-r--r--arch/x86_64/kernel/acpi/processor.c72
-rw-r--r--drivers/acpi/processor_core.c28
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/processor_perflib.c2
-rw-r--r--include/acpi/pdc_intel.h4
-rw-r--r--include/acpi/processor.h22
-rw-r--r--include/asm-i386/acpi.h2
16 files changed, 243 insertions, 231 deletions
diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile
index 267ca48e1b6c..d51c7313cae8 100644
--- a/arch/i386/kernel/acpi/Makefile
+++ b/arch/i386/kernel/acpi/Makefile
@@ -3,6 +3,6 @@ obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o
3obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o 3obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
4 4
5ifneq ($(CONFIG_ACPI_PROCESSOR),) 5ifneq ($(CONFIG_ACPI_PROCESSOR),)
6obj-y += cstate.o 6obj-y += cstate.o processor.o
7endif 7endif
8 8
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 4c3036ba65df..25db49ef1770 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -14,64 +14,6 @@
14#include <acpi/processor.h> 14#include <acpi/processor.h>
15#include <asm/acpi.h> 15#include <asm/acpi.h>
16 16
17static void acpi_processor_power_init_intel_pdc(struct acpi_processor_power
18 *pow)
19{
20 struct acpi_object_list *obj_list;
21 union acpi_object *obj;
22 u32 *buf;
23
24 /* allocate and initialize pdc. It will be used later. */
25 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
26 if (!obj_list) {
27 printk(KERN_ERR "Memory allocation error\n");
28 return;
29 }
30
31 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
32 if (!obj) {
33 printk(KERN_ERR "Memory allocation error\n");
34 kfree(obj_list);
35 return;
36 }
37
38 buf = kmalloc(12, GFP_KERNEL);
39 if (!buf) {
40 printk(KERN_ERR "Memory allocation error\n");
41 kfree(obj);
42 kfree(obj_list);
43 return;
44 }
45
46 buf[0] = ACPI_PDC_REVISION_ID;
47 buf[1] = 1;
48 buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
49
50 obj->type = ACPI_TYPE_BUFFER;
51 obj->buffer.length = 12;
52 obj->buffer.pointer = (u8 *) buf;
53 obj_list->count = 1;
54 obj_list->pointer = obj;
55 pow->pdc = obj_list;
56
57 return;
58}
59
60/* Initialize _PDC data based on the CPU vendor */
61void acpi_processor_power_init_pdc(struct acpi_processor_power *pow,
62 unsigned int cpu)
63{
64 struct cpuinfo_x86 *c = cpu_data + cpu;
65
66 pow->pdc = NULL;
67 if (c->x86_vendor == X86_VENDOR_INTEL)
68 acpi_processor_power_init_intel_pdc(pow);
69
70 return;
71}
72
73EXPORT_SYMBOL(acpi_processor_power_init_pdc);
74
75/* 17/*
76 * Initialize bm_flags based on the CPU cache properties 18 * Initialize bm_flags based on the CPU cache properties
77 * On SMP it depends on cache configuration 19 * On SMP it depends on cache configuration
diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c
new file mode 100644
index 000000000000..9f4cc02717ec
--- /dev/null
+++ b/arch/i386/kernel/acpi/processor.c
@@ -0,0 +1,75 @@
1/*
2 * arch/i386/kernel/acpi/processor.c
3 *
4 * Copyright (C) 2005 Intel Corporation
5 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
6 * - Added _PDC for platforms with Intel CPUs
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/acpi.h>
13
14#include <acpi/processor.h>
15#include <asm/acpi.h>
16
17static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
18{
19 struct acpi_object_list *obj_list;
20 union acpi_object *obj;
21 u32 *buf;
22
23 /* allocate and initialize pdc. It will be used later. */
24 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
25 if (!obj_list) {
26 printk(KERN_ERR "Memory allocation error\n");
27 return;
28 }
29
30 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
31 if (!obj) {
32 printk(KERN_ERR "Memory allocation error\n");
33 kfree(obj_list);
34 return;
35 }
36
37 buf = kmalloc(12, GFP_KERNEL);
38 if (!buf) {
39 printk(KERN_ERR "Memory allocation error\n");
40 kfree(obj);
41 kfree(obj_list);
42 return;
43 }
44
45 buf[0] = ACPI_PDC_REVISION_ID;
46 buf[1] = 1;
47 buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
48
49 if (cpu_has(c, X86_FEATURE_EST))
50 buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
51
52 obj->type = ACPI_TYPE_BUFFER;
53 obj->buffer.length = 12;
54 obj->buffer.pointer = (u8 *) buf;
55 obj_list->count = 1;
56 obj_list->pointer = obj;
57 pr->pdc = obj_list;
58
59 return;
60}
61
62/* Initialize _PDC data based on the CPU vendor */
63void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
64{
65 unsigned int cpu = pr->id;
66 struct cpuinfo_x86 *c = cpu_data + cpu;
67
68 pr->pdc = NULL;
69 if (c->x86_vendor == X86_VENDOR_INTEL)
70 init_intel_pdc(pr, c);
71
72 return;
73}
74
75EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 871366b83b3f..31ce890865d5 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -297,68 +297,6 @@ acpi_cpufreq_guess_freq (
297} 297}
298 298
299 299
300/*
301 * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
302 * of this driver
303 * @perf: processor-specific acpi_io_data struct
304 * @cpu: CPU being initialized
305 *
306 * To avoid issues with legacy OSes, some BIOSes require to be informed of
307 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
308 * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
309 * driver/acpi/processor.c
310 */
311static void
312acpi_processor_cpu_init_pdc_est(
313 struct acpi_processor_performance *perf,
314 unsigned int cpu,
315 struct acpi_object_list *obj_list
316 )
317{
318 union acpi_object *obj;
319 u32 *buf;
320 struct cpuinfo_x86 *c = cpu_data + cpu;
321 dprintk("acpi_processor_cpu_init_pdc_est\n");
322
323 if (!cpu_has(c, X86_FEATURE_EST))
324 return;
325
326 /* Initialize pdc. It will be used later. */
327 if (!obj_list)
328 return;
329
330 if (!(obj_list->count && obj_list->pointer))
331 return;
332
333 obj = obj_list->pointer;
334 if ((obj->buffer.length == 12) && obj->buffer.pointer) {
335 buf = (u32 *)obj->buffer.pointer;
336 buf[0] = ACPI_PDC_REVISION_ID;
337 buf[1] = 1;
338 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
339 perf->pdc = obj_list;
340 }
341 return;
342}
343
344
345/* CPU specific PDC initialization */
346static void
347acpi_processor_cpu_init_pdc(
348 struct acpi_processor_performance *perf,
349 unsigned int cpu,
350 struct acpi_object_list *obj_list
351 )
352{
353 struct cpuinfo_x86 *c = cpu_data + cpu;
354 dprintk("acpi_processor_cpu_init_pdc\n");
355 perf->pdc = NULL;
356 if (cpu_has(c, X86_FEATURE_EST))
357 acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
358 return;
359}
360
361
362static int 300static int
363acpi_cpufreq_cpu_init ( 301acpi_cpufreq_cpu_init (
364 struct cpufreq_policy *policy) 302 struct cpufreq_policy *policy)
@@ -373,9 +311,6 @@ acpi_cpufreq_cpu_init (
373 struct acpi_object_list arg_list = {1, &arg0}; 311 struct acpi_object_list arg_list = {1, &arg0};
374 312
375 dprintk("acpi_cpufreq_cpu_init\n"); 313 dprintk("acpi_cpufreq_cpu_init\n");
376 /* setup arg_list for _PDC settings */
377 arg0.buffer.length = 12;
378 arg0.buffer.pointer = (u8 *) arg0_buf;
379 314
380 data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); 315 data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
381 if (!data) 316 if (!data)
@@ -383,9 +318,7 @@ acpi_cpufreq_cpu_init (
383 318
384 acpi_io_data[cpu] = data; 319 acpi_io_data[cpu] = data;
385 320
386 acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
387 result = acpi_processor_register_performance(&data->acpi_data, cpu); 321 result = acpi_processor_register_performance(&data->acpi_data, cpu);
388 data->acpi_data.pdc = NULL;
389 322
390 if (result) 323 if (result)
391 goto err_free; 324 goto err_free;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index edb9873e27e3..d93023438c4f 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -364,22 +364,10 @@ static struct acpi_processor_performance p;
364 */ 364 */
365static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) 365static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
366{ 366{
367 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
368 u32 arg0_buf[3];
369 struct acpi_object_list arg_list = {1, &arg0};
370 unsigned long cur_freq; 367 unsigned long cur_freq;
371 int result = 0, i; 368 int result = 0, i;
372 unsigned int cpu = policy->cpu; 369 unsigned int cpu = policy->cpu;
373 370
374 /* _PDC settings */
375 arg0.buffer.length = 12;
376 arg0.buffer.pointer = (u8 *) arg0_buf;
377 arg0_buf[0] = ACPI_PDC_REVISION_ID;
378 arg0_buf[1] = 1;
379 arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP_MSR;
380
381 p.pdc = &arg_list;
382
383 /* register with ACPI core */ 371 /* register with ACPI core */
384 if (acpi_processor_register_performance(&p, cpu)) { 372 if (acpi_processor_register_performance(&p, cpu)) {
385 dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); 373 dprintk(KERN_INFO PFX "obtaining ACPI data failed\n");
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile
index f748d34c02f0..642648361ed3 100644
--- a/arch/ia64/kernel/cpufreq/Makefile
+++ b/arch/ia64/kernel/cpufreq/Makefile
@@ -1 +1,6 @@
1obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o 1obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o
2
3ifneq ($(CONFIG_ACPI_PROCESSOR),)
4obj-y += acpi-processor.o
5endif
6
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index da4d5cf80a48..5a1bf815282d 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -269,48 +269,6 @@ acpi_cpufreq_verify (
269} 269}
270 270
271 271
272/*
273 * processor_init_pdc - let BIOS know about the SMP capabilities
274 * of this driver
275 * @perf: processor-specific acpi_io_data struct
276 * @cpu: CPU being initialized
277 *
278 * To avoid issues with legacy OSes, some BIOSes require to be informed of
279 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
280 * accordingly. Actual call to _PDC is done in driver/acpi/processor.c
281 */
282static void
283processor_init_pdc (
284 struct acpi_processor_performance *perf,
285 unsigned int cpu,
286 struct acpi_object_list *obj_list
287 )
288{
289 union acpi_object *obj;
290 u32 *buf;
291
292 dprintk("processor_init_pdc\n");
293
294 perf->pdc = NULL;
295 /* Initialize pdc. It will be used later. */
296 if (!obj_list)
297 return;
298
299 if (!(obj_list->count && obj_list->pointer))
300 return;
301
302 obj = obj_list->pointer;
303 if ((obj->buffer.length == 12) && obj->buffer.pointer) {
304 buf = (u32 *)obj->buffer.pointer;
305 buf[0] = ACPI_PDC_REVISION_ID;
306 buf[1] = 1;
307 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
308 perf->pdc = obj_list;
309 }
310 return;
311}
312
313
314static int 272static int
315acpi_cpufreq_cpu_init ( 273acpi_cpufreq_cpu_init (
316 struct cpufreq_policy *policy) 274 struct cpufreq_policy *policy)
@@ -320,14 +278,7 @@ acpi_cpufreq_cpu_init (
320 struct cpufreq_acpi_io *data; 278 struct cpufreq_acpi_io *data;
321 unsigned int result = 0; 279 unsigned int result = 0;
322 280
323 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
324 u32 arg0_buf[3];
325 struct acpi_object_list arg_list = {1, &arg0};
326
327 dprintk("acpi_cpufreq_cpu_init\n"); 281 dprintk("acpi_cpufreq_cpu_init\n");
328 /* setup arg_list for _PDC settings */
329 arg0.buffer.length = 12;
330 arg0.buffer.pointer = (u8 *) arg0_buf;
331 282
332 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); 283 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
333 if (!data) 284 if (!data)
@@ -337,9 +288,7 @@ acpi_cpufreq_cpu_init (
337 288
338 acpi_io_data[cpu] = data; 289 acpi_io_data[cpu] = data;
339 290
340 processor_init_pdc(&data->acpi_data, cpu, &arg_list);
341 result = acpi_processor_register_performance(&data->acpi_data, cpu); 291 result = acpi_processor_register_performance(&data->acpi_data, cpu);
342 data->acpi_data.pdc = NULL;
343 292
344 if (result) 293 if (result)
345 goto err_free; 294 goto err_free;
diff --git a/arch/ia64/kernel/cpufreq/acpi-processor.c b/arch/ia64/kernel/cpufreq/acpi-processor.c
new file mode 100644
index 000000000000..e683630c8ce2
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/acpi-processor.c
@@ -0,0 +1,67 @@
1/*
2 * arch/ia64/kernel/cpufreq/processor.c
3 *
4 * Copyright (C) 2005 Intel Corporation
5 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
6 * - Added _PDC for platforms with Intel CPUs
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/acpi.h>
13
14#include <acpi/processor.h>
15#include <asm/acpi.h>
16
17static void init_intel_pdc(struct acpi_processor *pr)
18{
19 struct acpi_object_list *obj_list;
20 union acpi_object *obj;
21 u32 *buf;
22
23 /* allocate and initialize pdc. It will be used later. */
24 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
25 if (!obj_list) {
26 printk(KERN_ERR "Memory allocation error\n");
27 return;
28 }
29
30 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
31 if (!obj) {
32 printk(KERN_ERR "Memory allocation error\n");
33 kfree(obj_list);
34 return;
35 }
36
37 buf = kmalloc(12, GFP_KERNEL);
38 if (!buf) {
39 printk(KERN_ERR "Memory allocation error\n");
40 kfree(obj);
41 kfree(obj_list);
42 return;
43 }
44
45 buf[0] = ACPI_PDC_REVISION_ID;
46 buf[1] = 1;
47 buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
48
49 obj->type = ACPI_TYPE_BUFFER;
50 obj->buffer.length = 12;
51 obj->buffer.pointer = (u8 *) buf;
52 obj_list->count = 1;
53 obj_list->pointer = obj;
54 pr->pdc = obj_list;
55
56 return;
57}
58
59/* Initialize _PDC data based on the CPU vendor */
60void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
61{
62 pr->pdc = NULL;
63 init_intel_pdc(pr);
64 return;
65}
66
67EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile
index 7da9ace890bd..4fe97071f297 100644
--- a/arch/x86_64/kernel/acpi/Makefile
+++ b/arch/x86_64/kernel/acpi/Makefile
@@ -1,3 +1,8 @@
1obj-y := boot.o 1obj-y := boot.o
2boot-y := ../../../i386/kernel/acpi/boot.o 2boot-y := ../../../i386/kernel/acpi/boot.o
3obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o 3obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
4
5ifneq ($(CONFIG_ACPI_PROCESSOR),)
6obj-y += processor.o
7endif
8
diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c
new file mode 100644
index 000000000000..3bdc2baa5bb1
--- /dev/null
+++ b/arch/x86_64/kernel/acpi/processor.c
@@ -0,0 +1,72 @@
1/*
2 * arch/x86_64/kernel/acpi/processor.c
3 *
4 * Copyright (C) 2005 Intel Corporation
5 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
6 * - Added _PDC for platforms with Intel CPUs
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/acpi.h>
13
14#include <acpi/processor.h>
15#include <asm/acpi.h>
16
17static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
18{
19 struct acpi_object_list *obj_list;
20 union acpi_object *obj;
21 u32 *buf;
22
23 /* allocate and initialize pdc. It will be used later. */
24 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
25 if (!obj_list) {
26 printk(KERN_ERR "Memory allocation error\n");
27 return;
28 }
29
30 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
31 if (!obj) {
32 printk(KERN_ERR "Memory allocation error\n");
33 kfree(obj_list);
34 return;
35 }
36
37 buf = kmalloc(12, GFP_KERNEL);
38 if (!buf) {
39 printk(KERN_ERR "Memory allocation error\n");
40 kfree(obj);
41 kfree(obj_list);
42 return;
43 }
44
45 buf[0] = ACPI_PDC_REVISION_ID;
46 buf[1] = 1;
47 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
48
49 obj->type = ACPI_TYPE_BUFFER;
50 obj->buffer.length = 12;
51 obj->buffer.pointer = (u8 *) buf;
52 obj_list->count = 1;
53 obj_list->pointer = obj;
54 pr->pdc = obj_list;
55
56 return;
57}
58
59/* Initialize _PDC data based on the CPU vendor */
60void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
61{
62 unsigned int cpu = pr->id;
63 struct cpuinfo_x86 *c = cpu_data + cpu;
64
65 pr->pdc = NULL;
66 if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST))
67 init_intel_pdc(pr, c);
68
69 return;
70}
71
72EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 421792562642..66bbda78507a 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -253,31 +253,21 @@ static int acpi_processor_errata(struct acpi_processor *pr)
253 * _PDC is required for a BIOS-OS handshake for most of the newer 253 * _PDC is required for a BIOS-OS handshake for most of the newer
254 * ACPI processor features. 254 * ACPI processor features.
255 */ 255 */
256 256static int acpi_processor_set_pdc(struct acpi_processor *pr)
257int acpi_processor_set_pdc(struct acpi_processor *pr,
258 struct acpi_object_list *pdc_in)
259{ 257{
258 struct acpi_object_list *pdc_in = pr->pdc;
260 acpi_status status = AE_OK; 259 acpi_status status = AE_OK;
261 u32 arg0_buf[3];
262 union acpi_object arg0 = { ACPI_TYPE_BUFFER };
263 struct acpi_object_list no_object = { 1, &arg0 };
264 struct acpi_object_list *pdc;
265 260
266 ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); 261 ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
267 262
268 arg0.buffer.length = 12; 263 if (!pdc_in)
269 arg0.buffer.pointer = (u8 *) arg0_buf; 264 return_VALUE(status);
270 arg0_buf[0] = ACPI_PDC_REVISION_ID;
271 arg0_buf[1] = 0;
272 arg0_buf[2] = 0;
273
274 pdc = (pdc_in) ? pdc_in : &no_object;
275 265
276 status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); 266 status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
277 267
278 if ((ACPI_FAILURE(status)) && (pdc_in)) 268 if (ACPI_FAILURE(status))
279 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 269 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
280 "Error evaluating _PDC, using legacy perf. control...\n")); 270 "Could not evaluate _PDC, using legacy perf. control...\n"));
281 271
282 return_VALUE(status); 272 return_VALUE(status);
283} 273}
@@ -574,6 +564,10 @@ static int acpi_processor_start(struct acpi_device *device)
574 "Error installing device notify handler\n")); 564 "Error installing device notify handler\n"));
575 } 565 }
576 566
567 /* _PDC call should be done before doing anything else (if reqd.). */
568 arch_acpi_processor_init_pdc(pr);
569 acpi_processor_set_pdc(pr);
570
577 acpi_processor_power_init(pr, device); 571 acpi_processor_power_init(pr, device);
578 572
579 if (pr->flags.throttling) { 573 if (pr->flags.throttling) {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 70d8a6ec0920..1915c377bfc6 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -1014,8 +1014,6 @@ int acpi_processor_power_init(struct acpi_processor *pr,
1014 } 1014 }
1015 } 1015 }
1016 1016
1017 acpi_processor_power_init_pdc(&(pr->power), pr->id);
1018 acpi_processor_set_pdc(pr, pr->power.pdc);
1019 acpi_processor_get_power_info(pr); 1017 acpi_processor_get_power_info(pr);
1020 1018
1021 /* 1019 /*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 22c7bb66c200..532370734c68 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -315,8 +315,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
315 if (!pr || !pr->performance || !pr->handle) 315 if (!pr || !pr->performance || !pr->handle)
316 return_VALUE(-EINVAL); 316 return_VALUE(-EINVAL);
317 317
318 acpi_processor_set_pdc(pr, pr->performance->pdc);
319
320 status = acpi_get_handle(pr->handle, "_PCT", &handle); 318 status = acpi_get_handle(pr->handle, "_PCT", &handle);
321 if (ACPI_FAILURE(status)) { 319 if (ACPI_FAILURE(status)) {
322 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 320 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index 91f4a12a99a1..3fa81d55cd0c 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -15,9 +15,7 @@
15#define ACPI_PDC_C_C1_FFH (0x0100) 15#define ACPI_PDC_C_C1_FFH (0x0100)
16 16
17#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ 17#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
18 ACPI_PDC_C_C1_HALT) 18 ACPI_PDC_C_C1_HALT | \
19
20#define ACPI_PDC_EST_CAPABILITY_SMP_MSR (ACPI_PDC_EST_CAPABILITY_SMP | \
21 ACPI_PDC_P_FFH) 19 ACPI_PDC_P_FFH)
22 20
23#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ 21#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 7a00d5089de9..82a9b7d430ec 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -62,9 +62,6 @@ struct acpi_processor_power {
62 u32 bm_activity; 62 u32 bm_activity;
63 int count; 63 int count;
64 struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; 64 struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
65
66 /* the _PDC objects passed by the driver, if any */
67 struct acpi_object_list *pdc;
68}; 65};
69 66
70/* Performance Management */ 67/* Performance Management */
@@ -96,8 +93,6 @@ struct acpi_processor_performance {
96 unsigned int state_count; 93 unsigned int state_count;
97 struct acpi_processor_px *states; 94 struct acpi_processor_px *states;
98 95
99 /* the _PDC objects passed by the driver, if any */
100 struct acpi_object_list *pdc;
101}; 96};
102 97
103/* Throttling Control */ 98/* Throttling Control */
@@ -151,6 +146,9 @@ struct acpi_processor {
151 struct acpi_processor_performance *performance; 146 struct acpi_processor_performance *performance;
152 struct acpi_processor_throttling throttling; 147 struct acpi_processor_throttling throttling;
153 struct acpi_processor_limit limit; 148 struct acpi_processor_limit limit;
149
150 /* the _PDC objects for this processor, if any */
151 struct acpi_object_list *pdc;
154}; 152};
155 153
156struct acpi_processor_errata { 154struct acpi_processor_errata {
@@ -178,22 +176,12 @@ int acpi_processor_notify_smm(struct module *calling_module);
178extern struct acpi_processor *processors[NR_CPUS]; 176extern struct acpi_processor *processors[NR_CPUS];
179extern struct acpi_processor_errata errata; 177extern struct acpi_processor_errata errata;
180 178
181int acpi_processor_set_pdc(struct acpi_processor *pr, 179void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
182 struct acpi_object_list *pdc_in);
183 180
184#ifdef ARCH_HAS_POWER_PDC_INIT 181#ifdef ARCH_HAS_POWER_INIT
185void acpi_processor_power_init_pdc(struct acpi_processor_power *pow,
186 unsigned int cpu);
187void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, 182void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
188 unsigned int cpu); 183 unsigned int cpu);
189#else 184#else
190static inline void acpi_processor_power_init_pdc(struct acpi_processor_power
191 *pow, unsigned int cpu)
192{
193 pow->pdc = NULL;
194 return;
195}
196
197static inline void acpi_processor_power_init_bm_check(struct 185static inline void acpi_processor_power_init_bm_check(struct
198 acpi_processor_flags 186 acpi_processor_flags
199 *flags, unsigned int cpu) 187 *flags, unsigned int cpu)
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index df4ed323aa4d..55059abf9c95 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -179,7 +179,7 @@ extern void acpi_reserve_bootmem(void);
179 179
180extern u8 x86_acpiid_to_apicid[]; 180extern u8 x86_acpiid_to_apicid[];
181 181
182#define ARCH_HAS_POWER_PDC_INIT 1 182#define ARCH_HAS_POWER_INIT 1
183 183
184#endif /*__KERNEL__*/ 184#endif /*__KERNEL__*/
185 185