diff options
author | Bob Moore <robert.moore@intel.com> | 2009-03-18 22:12:13 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-27 12:11:05 -0400 |
commit | 31fbc073a35a017e34840deb9e865a701e986002 (patch) | |
tree | 03bbda99bc136f9f7ff98c67aa83621f6181c7ad /drivers/acpi/acpica/tbfadt.c | |
parent | f28ad2c3daf0691081d91488df4d9d101e1a2b5d (diff) |
ACPICA: FADT: Favor 32-bit register addresses for compatibility
Use the 32-bit register addresses whenever they are non-zero. This
means that the 32-bit addresses are favored over the 64-bit
(GAS) addresses. The 64-bit addresses are only used if the 32-bit
addresses are zero. This change provides compatibility with all
versions of Windows. The worst case that this solves is when both
the 32-bit and 64-bit addresses are non-zero, but only the 32-bit
addresses are actually valid. This appears to happen in some
BIOSes because in this case, Windows uses the 32-bit addresses.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/tbfadt.c')
-rw-r--r-- | drivers/acpi/acpica/tbfadt.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index ff89cfee0e7e..f87bfb259ef6 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c | |||
@@ -320,29 +320,35 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |||
320 | * RETURN: None | 320 | * RETURN: None |
321 | * | 321 | * |
322 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | 322 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. |
323 | * Expand all 32-bit addresses to 64-bit. | 323 | * Expand 32-bit addresses to 64-bit as necessary. |
324 | * | 324 | * |
325 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), | 325 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), |
326 | * and must contain a copy of the actual FADT. | 326 | * and must contain a copy of the actual FADT. |
327 | * | 327 | * |
328 | * ACPICA will use the "X" fields of the FADT for all addresses. | 328 | * Notes on 64-bit register addresses: |
329 | * | 329 | * |
330 | * "X" fields are optional extensions to the original V1.0 fields. Even if | 330 | * After this FADT conversion, later ACPICA code will only use the 64-bit "X" |
331 | * they are present in the structure, they can be optionally not used by | 331 | * fields of the FADT for all ACPI register addresses. |
332 | * setting them to zero. Therefore, we must selectively expand V1.0 fields | ||
333 | * if the corresponding X field is zero. | ||
334 | * | 332 | * |
335 | * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding | 333 | * The 64-bit "X" fields are optional extensions to the original 32-bit FADT |
336 | * "X" fields. | 334 | * V1.0 fields. Even if they are present in the FADT, they are optional and |
335 | * are unused if the BIOS sets them to zero. Therefore, we must copy/expand | ||
336 | * 32-bit V1.0 fields if the corresponding X field is zero. | ||
337 | * | 337 | * |
338 | * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by | 338 | * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the |
339 | * expanding the corresponding ACPI 1.0 field. | 339 | * corresponding "X" fields in the internal FADT. |
340 | * | ||
341 | * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded | ||
342 | * to the corresponding 64-bit X fields. For compatibility with other ACPI | ||
343 | * implementations, we ignore the 64-bit field if the 32-bit field is valid, | ||
344 | * regardless of whether the host OS is 32-bit or 64-bit. | ||
340 | * | 345 | * |
341 | ******************************************************************************/ | 346 | ******************************************************************************/ |
342 | 347 | ||
343 | static void acpi_tb_convert_fadt(void) | 348 | static void acpi_tb_convert_fadt(void) |
344 | { | 349 | { |
345 | struct acpi_generic_address *target64; | 350 | struct acpi_generic_address *address64; |
351 | u32 address32; | ||
346 | u32 i; | 352 | u32 i; |
347 | 353 | ||
348 | /* Update the local FADT table header length */ | 354 | /* Update the local FADT table header length */ |
@@ -391,29 +397,51 @@ static void acpi_tb_convert_fadt(void) | |||
391 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" | 397 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" |
392 | * generic address structures as necessary. Later code will always use | 398 | * generic address structures as necessary. Later code will always use |
393 | * the 64-bit address structures. | 399 | * the 64-bit address structures. |
400 | * | ||
401 | * March 2009: | ||
402 | * We now always use the 32-bit address if it is valid (non-null). This | ||
403 | * is not in accordance with the ACPI specification which states that | ||
404 | * the 64-bit address supersedes the 32-bit version, but we do this for | ||
405 | * compatibility with other ACPI implementations. Most notably, in the | ||
406 | * case where both the 32 and 64 versions are non-null, we use the 32-bit | ||
407 | * version. This is the only address that is guaranteed to have been | ||
408 | * tested by the BIOS manufacturer. | ||
394 | */ | 409 | */ |
395 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | 410 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
396 | target64 = | 411 | address32 = *ACPI_ADD_PTR(u32, |
397 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, | 412 | &acpi_gbl_FADT, |
398 | fadt_info_table[i].address64); | 413 | fadt_info_table[i].address32); |
399 | 414 | ||
400 | /* Expand only if the 64-bit X target is null */ | 415 | address64 = ACPI_ADD_PTR(struct acpi_generic_address, |
416 | &acpi_gbl_FADT, | ||
417 | fadt_info_table[i].address64); | ||
401 | 418 | ||
402 | if (!target64->address) { | 419 | /* |
420 | * If both 32- and 64-bit addresses are valid (non-zero), | ||
421 | * they must match. | ||
422 | */ | ||
423 | if (address64->address && address32 && | ||
424 | (address64->address != (u64) address32)) { | ||
425 | ACPI_ERROR((AE_INFO, | ||
426 | "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 32", | ||
427 | fadt_info_table[i].name, address32, | ||
428 | ACPI_FORMAT_UINT64(address64->address))); | ||
429 | } | ||
403 | 430 | ||
404 | /* The space_id is always I/O for the 32-bit legacy address fields */ | 431 | /* Always use 32-bit address if it is valid (non-null) */ |
405 | 432 | ||
406 | acpi_tb_init_generic_address(target64, | 433 | if (address32) { |
434 | /* | ||
435 | * Copy the 32-bit address to the 64-bit GAS structure. The | ||
436 | * Space ID is always I/O for 32-bit legacy address fields | ||
437 | */ | ||
438 | acpi_tb_init_generic_address(address64, | ||
407 | ACPI_ADR_SPACE_SYSTEM_IO, | 439 | ACPI_ADR_SPACE_SYSTEM_IO, |
408 | *ACPI_ADD_PTR(u8, | 440 | *ACPI_ADD_PTR(u8, |
409 | &acpi_gbl_FADT, | 441 | &acpi_gbl_FADT, |
410 | fadt_info_table | 442 | fadt_info_table |
411 | [i].length), | 443 | [i].length), |
412 | (u64) * ACPI_ADD_PTR(u32, | 444 | address32); |
413 | &acpi_gbl_FADT, | ||
414 | fadt_info_table | ||
415 | [i]. | ||
416 | address32)); | ||
417 | } | 445 | } |
418 | } | 446 | } |
419 | } | 447 | } |
@@ -530,18 +558,6 @@ static void acpi_tb_validate_fadt(void) | |||
530 | length)); | 558 | length)); |
531 | } | 559 | } |
532 | } | 560 | } |
533 | |||
534 | /* | ||
535 | * If both 32- and 64-bit addresses are valid (non-zero), | ||
536 | * they must match | ||
537 | */ | ||
538 | if (address64->address && *address32 && | ||
539 | (address64->address != (u64) * address32)) { | ||
540 | ACPI_ERROR((AE_INFO, | ||
541 | "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X", | ||
542 | name, *address32, | ||
543 | ACPI_FORMAT_UINT64(address64->address))); | ||
544 | } | ||
545 | } | 561 | } |
546 | } | 562 | } |
547 | 563 | ||