diff options
author | Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | 2005-10-23 16:31:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-12-01 01:30:35 -0500 |
commit | 05131ecc99ea9da7f45ba3058fe8a2c1d0ceeab8 (patch) | |
tree | dec76975406874cf677d6391302f42a6da55ac38 /drivers/acpi/processor_core.c | |
parent | d2149b542382bfc206cb28485108f6470c979566 (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>
Diffstat (limited to 'drivers/acpi/processor_core.c')
-rw-r--r-- | drivers/acpi/processor_core.c | 28 |
1 files changed, 11 insertions, 17 deletions
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 | 256 | static int acpi_processor_set_pdc(struct acpi_processor *pr) | |
257 | int 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) { |