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 | |
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')
-rw-r--r-- | drivers/acpi/processor_core.c | 28 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 2 |
3 files changed, 11 insertions, 21 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) { |
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, |