aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-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 }