aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/tbfadt.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-03-18 22:12:13 -0400
committerLen Brown <len.brown@intel.com>2009-03-27 12:11:05 -0400
commit31fbc073a35a017e34840deb9e865a701e986002 (patch)
tree03bbda99bc136f9f7ff98c67aa83621f6181c7ad /drivers/acpi/acpica/tbfadt.c
parentf28ad2c3daf0691081d91488df4d9d101e1a2b5d (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.c86
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
343static void acpi_tb_convert_fadt(void) 348static 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