diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/tables/tbfadt.c | 125 |
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 */ |
52 | static inline void | 52 | static inline void |
53 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 53 | acpi_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 | ||
56 | static void acpi_tb_convert_fadt(void); | 56 | static void acpi_tb_convert_fadt(void); |
57 | 57 | ||
@@ -125,7 +125,7 @@ static struct acpi_fadt_info fadt_info_table[] = { | |||
125 | 125 | ||
126 | static inline void | 126 | static inline void |
127 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 127 | acpi_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 | ||
426 | static void acpi_tb_validate_fadt(void) | 474 | static 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 | } |