aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-12-30 14:06:06 -0500
committerLen Brown <len.brown@intel.com>2008-12-31 01:17:09 -0500
commit06f5541960d02d5e0ddd8fd5c9a1554d85d94fa9 (patch)
tree2a86b61dd4e63d6a74450198c13f8c7430be9e69 /drivers
parent1685bd404dc2ecce2fdae6410e85ded2f2c0136d (diff)
ACPICA: FADT parsing changes and fixes
1) Update the register lengths for the PM1 event blocks. The length must be divided by two in order to use these to access the status registers. 2) Add run-time option to use default register lengths to override a faulty FADT. 3) Add warning message if any of the X64 address structures contain a length that does not match the legacy length earlier in the FADT. 4) Move all FADT warning messages into the ValidateFadt function. 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')
-rw-r--r--drivers/acpi/tables/tbfadt.c125
1 files changed, 105 insertions, 20 deletions
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index 57e089faff1f..b4ce2074c91f 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -51,7 +51,7 @@ ACPI_MODULE_NAME("tbfadt")
51/* Local prototypes */ 51/* Local prototypes */
52static inline void 52static inline void
53acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 53acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
54 u8 byte_width, u64 address); 54 u8 space_id, u8 byte_width, u64 address);
55 55
56static void acpi_tb_convert_fadt(void); 56static void acpi_tb_convert_fadt(void);
57 57
@@ -125,7 +125,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
125 125
126static inline void 126static inline void
127acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 127acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
128 u8 byte_width, u64 address) 128 u8 space_id, u8 byte_width, u64 address)
129{ 129{
130 130
131 /* 131 /*
@@ -136,10 +136,10 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
136 136
137 /* All other fields are byte-wide */ 137 /* All other fields are byte-wide */
138 138
139 generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; 139 generic_address->space_id = space_id;
140 generic_address->bit_width = byte_width << 3; 140 generic_address->bit_width = (u8)ACPI_MUL_8(byte_width);
141 generic_address->bit_offset = 0; 141 generic_address->bit_offset = 0;
142 generic_address->access_width = 0; 142 generic_address->access_width = 0; /* Access width ANY */
143} 143}
144 144
145/******************************************************************************* 145/*******************************************************************************
@@ -226,7 +226,8 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
226 */ 226 */
227 if (length > sizeof(struct acpi_table_fadt)) { 227 if (length > sizeof(struct acpi_table_fadt)) {
228 ACPI_WARNING((AE_INFO, 228 ACPI_WARNING((AE_INFO,
229 "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX", 229 "FADT (revision %u) is longer than ACPI 2.0 version, "
230 "truncating length 0x%X to 0x%zX",
230 table->revision, (unsigned)length, 231 table->revision, (unsigned)length,
231 sizeof(struct acpi_table_fadt))); 232 sizeof(struct acpi_table_fadt)));
232 } 233 }
@@ -245,7 +246,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
245 * 2) Validate some of the important values within the FADT 246 * 2) Validate some of the important values within the FADT
246 */ 247 */
247 acpi_tb_convert_fadt(); 248 acpi_tb_convert_fadt();
248 acpi_tb_validate_fadt();
249} 249}
250 250
251/******************************************************************************* 251/*******************************************************************************
@@ -337,7 +337,11 @@ static void acpi_tb_convert_fadt(void)
337 /* Expand only if the X target is null */ 337 /* Expand only if the X target is null */
338 338
339 if (!target->address) { 339 if (!target->address) {
340
341 /* The space_id is always I/O for the legacy address fields */
342
340 acpi_tb_init_generic_address(target, 343 acpi_tb_init_generic_address(target,
344 ACPI_ADR_SPACE_SYSTEM_IO,
341 *ACPI_ADD_PTR(u8, 345 *ACPI_ADD_PTR(u8,
342 &acpi_gbl_FADT, 346 &acpi_gbl_FADT,
343 fadt_info_table 347 fadt_info_table
@@ -350,6 +354,25 @@ static void acpi_tb_convert_fadt(void)
350 } 354 }
351 } 355 }
352 356
357 /* Validate FADT values now, before we make any changes */
358
359 acpi_tb_validate_fadt();
360
361 /*
362 * Get the length of the individual PM1 registers. Each register is
363 * defined to be the event block length / 2.
364 */
365 pm1_register_length = (u8)ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
366
367 /*
368 * Adjust the lengths of the PM1 Event Blocks so that they can be used to
369 * access the PM1 status register(s).
370 */
371 acpi_gbl_FADT.xpm1a_event_block.bit_width =
372 (u8)ACPI_MUL_8(pm1_register_length);
373 acpi_gbl_FADT.xpm1b_event_block.bit_width =
374 (u8)ACPI_MUL_8(pm1_register_length);
375
353 /* 376 /*
354 * Calculate separate GAS structs for the PM1 Enable registers. 377 * Calculate separate GAS structs for the PM1 Enable registers.
355 * These addresses do not appear (directly) in the FADT, so it is 378 * These addresses do not appear (directly) in the FADT, so it is
@@ -370,11 +393,11 @@ static void acpi_tb_convert_fadt(void)
370 " PM1_EVT_LEN (%u)\n", 393 " PM1_EVT_LEN (%u)\n",
371 acpi_gbl_FADT.xpm1a_event_block.bit_width, 394 acpi_gbl_FADT.xpm1a_event_block.bit_width,
372 acpi_gbl_FADT.pm1_event_length); 395 acpi_gbl_FADT.pm1_event_length);
373 pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
374 396
375 /* The PM1A register block is required */ 397 /* The PM1A register block is required */
376 398
377 acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, 399 acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
400 acpi_gbl_FADT.xpm1a_event_block.space_id,
378 pm1_register_length, 401 pm1_register_length,
379 (acpi_gbl_FADT.xpm1a_event_block.address + 402 (acpi_gbl_FADT.xpm1a_event_block.address +
380 pm1_register_length)); 403 pm1_register_length));
@@ -393,6 +416,7 @@ static void acpi_tb_convert_fadt(void)
393 acpi_gbl_FADT.xpm1b_event_block.bit_width, 416 acpi_gbl_FADT.xpm1b_event_block.bit_width,
394 acpi_gbl_FADT.pm1_event_length); 417 acpi_gbl_FADT.pm1_event_length);
395 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, 418 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
419 acpi_gbl_FADT.xpm1b_event_block.space_id,
396 pm1_register_length, 420 pm1_register_length,
397 (acpi_gbl_FADT.xpm1b_event_block. 421 (acpi_gbl_FADT.xpm1b_event_block.
398 address + pm1_register_length)); 422 address + pm1_register_length));
@@ -401,6 +425,30 @@ static void acpi_tb_convert_fadt(void)
401 acpi_gbl_FADT.xpm1b_event_block.space_id; 425 acpi_gbl_FADT.xpm1b_event_block.space_id;
402 426
403 } 427 }
428
429 if (acpi_gbl_use_default_register_widths) {
430 /*
431 * Optionally, use the default sizes for the ACPI registers.
432 * Some FADTs do not have the correct length(s).
433 *
434 * Note: Xpm1a_event_block and Xpm1b_event_block are used to access the PM1
435 * status registers. The PM1 enable registers are created above.
436 */
437 acpi_gbl_xpm1a_enable.bit_width = ACPI_PM1_REGISTER_WIDTH;
438 acpi_gbl_xpm1b_enable.bit_width = ACPI_PM1_REGISTER_WIDTH;
439
440 acpi_gbl_FADT.xpm1a_event_block.bit_width =
441 ACPI_PM1_REGISTER_WIDTH;
442 acpi_gbl_FADT.xpm1b_event_block.bit_width =
443 ACPI_PM1_REGISTER_WIDTH;
444 acpi_gbl_FADT.xpm1a_control_block.bit_width =
445 ACPI_PM1_REGISTER_WIDTH;
446 acpi_gbl_FADT.xpm1b_control_block.bit_width =
447 ACPI_PM1_REGISTER_WIDTH;
448 acpi_gbl_FADT.xpm2_control_block.bit_width =
449 ACPI_PM2_REGISTER_WIDTH;
450 acpi_gbl_FADT.xpm_timer_block.bit_width = ACPI_PM_TIMER_WIDTH;
451 }
404} 452}
405 453
406/****************************************************************************** 454/******************************************************************************
@@ -425,26 +473,63 @@ static void acpi_tb_convert_fadt(void)
425 473
426static void acpi_tb_validate_fadt(void) 474static void acpi_tb_validate_fadt(void)
427{ 475{
476 char *name;
428 u32 *address32; 477 u32 *address32;
429 struct acpi_generic_address *address64; 478 struct acpi_generic_address *address64;
430 u8 length; 479 u8 length;
431 u32 i; 480 u32 i;
432 481
433 /* Examine all of the 64-bit extended address fields (X fields) */ 482 /*
483 * Check for FACS and DSDT address mismatches. An address mismatch between
484 * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
485 * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
486 */
487 if (acpi_gbl_FADT.facs &&
488 (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
489 ACPI_WARNING((AE_INFO,
490 "32/64 FACS address mismatch in FADT - "
491 "two FACS tables! %8.8X/%8.8X%8.8X",
492 acpi_gbl_FADT.facs,
493 ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));
494 }
434 495
435 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { 496 if (acpi_gbl_FADT.dsdt &&
497 (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
498 ACPI_WARNING((AE_INFO,
499 "32/64 DSDT address mismatch in FADT - "
500 "two DSDT tables! %8.8X/%8.8X%8.8X",
501 acpi_gbl_FADT.dsdt,
502 ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));
503 }
436 504
437 /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ 505 /* Examine all of the 64-bit extended address fields (X fields) */
438 506
439 address64 = 507 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
440 ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, 508 /*
441 fadt_info_table[i].target); 509 * Generate pointers to the 32-bit and 64-bit addresses, get the
510 * register length (width), and the register name
511 */
512 address64 = ACPI_ADD_PTR(struct acpi_generic_address,
513 &acpi_gbl_FADT,
514 fadt_info_table[i].target);
442 address32 = 515 address32 =
443 ACPI_ADD_PTR(u32, &acpi_gbl_FADT, 516 ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
444 fadt_info_table[i].source); 517 fadt_info_table[i].source);
445 length = 518 length =
446 *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, 519 *ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
447 fadt_info_table[i].length); 520 fadt_info_table[i].length);
521 name = fadt_info_table[i].name;
522
523 /*
524 * For each extended field, check for length mismatch between the
525 * legacy length field and the corresonding 64-bit X length field.
526 */
527 if (address64 && (address64->bit_width != ACPI_MUL_8(length))) {
528 ACPI_WARNING((AE_INFO,
529 "32/64X bit length mismatch in %s: %d/%d",
530 name, ACPI_MUL_8(length),
531 address64->bit_width));
532 }
448 533
449 if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { 534 if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
450 /* 535 /*
@@ -453,8 +538,8 @@ static void acpi_tb_validate_fadt(void)
453 */ 538 */
454 if (!address64->address || !length) { 539 if (!address64->address || !length) {
455 ACPI_ERROR((AE_INFO, 540 ACPI_ERROR((AE_INFO,
456 "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", 541 "Required field %s has zero address and/or length: %8.8X%8.8X/%X",
457 fadt_info_table[i].name, 542 name,
458 ACPI_FORMAT_UINT64(address64-> 543 ACPI_FORMAT_UINT64(address64->
459 address), 544 address),
460 length)); 545 length));
@@ -467,8 +552,8 @@ static void acpi_tb_validate_fadt(void)
467 if ((address64->address && !length) 552 if ((address64->address && !length)
468 || (!address64->address && length)) { 553 || (!address64->address && length)) {
469 ACPI_WARNING((AE_INFO, 554 ACPI_WARNING((AE_INFO,
470 "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", 555 "Optional field %s has zero address or length: %8.8X%8.8X/%X",
471 fadt_info_table[i].name, 556 name,
472 ACPI_FORMAT_UINT64(address64-> 557 ACPI_FORMAT_UINT64(address64->
473 address), 558 address),
474 length)); 559 length));
@@ -480,8 +565,8 @@ static void acpi_tb_validate_fadt(void)
480 if (address64->address && *address32 && 565 if (address64->address && *address32 &&
481 (address64->address != (u64) * address32)) { 566 (address64->address != (u64) * address32)) {
482 ACPI_ERROR((AE_INFO, 567 ACPI_ERROR((AE_INFO,
483 "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", 568 "32/64X address mismatch in %s: [%8.8X] [%8.8X%8.8X], using 64X",
484 fadt_info_table[i].name, *address32, 569 name, *address32,
485 ACPI_FORMAT_UINT64(address64->address))); 570 ACPI_FORMAT_UINT64(address64->address)));
486 } 571 }
487 } 572 }