diff options
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 114 | ||||
-rw-r--r-- | drivers/acpi/acpica/rscalc.c | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/rscreate.c | 27 |
4 files changed, 99 insertions, 54 deletions
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 600268d33aa8..8d59ac2399e0 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -158,7 +158,12 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node, | |||
158 | info->parent_package = *return_object_ptr; | 158 | info->parent_package = *return_object_ptr; |
159 | status = acpi_ns_check_package(info, return_object_ptr); | 159 | status = acpi_ns_check_package(info, return_object_ptr); |
160 | if (ACPI_FAILURE(status)) { | 160 | if (ACPI_FAILURE(status)) { |
161 | goto exit; | 161 | |
162 | /* We might be able to fix an operand type error (_PRT) */ | ||
163 | |||
164 | if (status != AE_AML_OPERAND_TYPE) { | ||
165 | goto exit; | ||
166 | } | ||
162 | } | 167 | } |
163 | } | 168 | } |
164 | 169 | ||
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index daac8daeaa9f..aca9bdf74e1f 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c | |||
@@ -87,6 +87,10 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, | |||
87 | union acpi_operand_object **return_object_ptr); | 87 | union acpi_operand_object **return_object_ptr); |
88 | 88 | ||
89 | static acpi_status | 89 | static acpi_status |
90 | acpi_ns_repair_PRT(struct acpi_evaluate_info *info, | ||
91 | union acpi_operand_object **return_object_ptr); | ||
92 | |||
93 | static acpi_status | ||
90 | acpi_ns_repair_PSS(struct acpi_evaluate_info *info, | 94 | acpi_ns_repair_PSS(struct acpi_evaluate_info *info, |
91 | union acpi_operand_object **return_object_ptr); | 95 | union acpi_operand_object **return_object_ptr); |
92 | 96 | ||
@@ -121,6 +125,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements, | |||
121 | * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs | 125 | * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs |
122 | * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs | 126 | * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs |
123 | * _HID: Strings: uppercase all, remove any leading asterisk | 127 | * _HID: Strings: uppercase all, remove any leading asterisk |
128 | * _PRT: Fix reversed source_name and source_index | ||
124 | * _PSS: Sort the list descending by Power | 129 | * _PSS: Sort the list descending by Power |
125 | * _TSS: Sort the list descending by Power | 130 | * _TSS: Sort the list descending by Power |
126 | * | 131 | * |
@@ -137,6 +142,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { | |||
137 | {"_FDE", acpi_ns_repair_FDE}, | 142 | {"_FDE", acpi_ns_repair_FDE}, |
138 | {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ | 143 | {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ |
139 | {"_HID", acpi_ns_repair_HID}, | 144 | {"_HID", acpi_ns_repair_HID}, |
145 | {"_PRT", acpi_ns_repair_PRT}, | ||
140 | {"_PSS", acpi_ns_repair_PSS}, | 146 | {"_PSS", acpi_ns_repair_PSS}, |
141 | {"_TSS", acpi_ns_repair_TSS}, | 147 | {"_TSS", acpi_ns_repair_TSS}, |
142 | {{0, 0, 0, 0}, NULL} /* Table terminator */ | 148 | {{0, 0, 0, 0}, NULL} /* Table terminator */ |
@@ -488,7 +494,7 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, | |||
488 | 494 | ||
489 | /****************************************************************************** | 495 | /****************************************************************************** |
490 | * | 496 | * |
491 | * FUNCTION: acpi_ns_repair_TSS | 497 | * FUNCTION: acpi_ns_repair_PRT |
492 | * | 498 | * |
493 | * PARAMETERS: info - Method execution information block | 499 | * PARAMETERS: info - Method execution information block |
494 | * return_object_ptr - Pointer to the object returned from the | 500 | * return_object_ptr - Pointer to the object returned from the |
@@ -496,38 +502,54 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, | |||
496 | * | 502 | * |
497 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | 503 | * RETURN: Status. AE_OK if object is OK or was repaired successfully |
498 | * | 504 | * |
499 | * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list | 505 | * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed |
500 | * descending by the power dissipation values. | 506 | * source_name and source_index field, a common BIOS bug. |
501 | * | 507 | * |
502 | *****************************************************************************/ | 508 | *****************************************************************************/ |
503 | 509 | ||
504 | static acpi_status | 510 | static acpi_status |
505 | acpi_ns_repair_TSS(struct acpi_evaluate_info *info, | 511 | acpi_ns_repair_PRT(struct acpi_evaluate_info *info, |
506 | union acpi_operand_object **return_object_ptr) | 512 | union acpi_operand_object **return_object_ptr) |
507 | { | 513 | { |
508 | union acpi_operand_object *return_object = *return_object_ptr; | 514 | union acpi_operand_object *package_object = *return_object_ptr; |
509 | acpi_status status; | 515 | union acpi_operand_object **top_object_list; |
510 | struct acpi_namespace_node *node; | 516 | union acpi_operand_object **sub_object_list; |
517 | union acpi_operand_object *obj_desc; | ||
518 | u32 element_count; | ||
519 | u32 index; | ||
511 | 520 | ||
512 | /* | 521 | /* Each element in the _PRT package is a subpackage */ |
513 | * We can only sort the _TSS return package if there is no _PSS in the | ||
514 | * same scope. This is because if _PSS is present, the ACPI specification | ||
515 | * dictates that the _TSS Power Dissipation field is to be ignored, and | ||
516 | * therefore some BIOSs leave garbage values in the _TSS Power field(s). | ||
517 | * In this case, it is best to just return the _TSS package as-is. | ||
518 | * (May, 2011) | ||
519 | */ | ||
520 | status = acpi_ns_get_node(info->node, "^_PSS", | ||
521 | ACPI_NS_NO_UPSEARCH, &node); | ||
522 | if (ACPI_SUCCESS(status)) { | ||
523 | return (AE_OK); | ||
524 | } | ||
525 | 522 | ||
526 | status = acpi_ns_check_sorted_list(info, return_object, 5, 1, | 523 | top_object_list = package_object->package.elements; |
527 | ACPI_SORT_DESCENDING, | 524 | element_count = package_object->package.count; |
528 | "PowerDissipation"); | ||
529 | 525 | ||
530 | return (status); | 526 | for (index = 0; index < element_count; index++) { |
527 | sub_object_list = (*top_object_list)->package.elements; | ||
528 | |||
529 | /* | ||
530 | * If the BIOS has erroneously reversed the _PRT source_name (index 2) | ||
531 | * and the source_index (index 3), fix it. _PRT is important enough to | ||
532 | * workaround this BIOS error. This also provides compatibility with | ||
533 | * other ACPI implementations. | ||
534 | */ | ||
535 | obj_desc = sub_object_list[3]; | ||
536 | if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { | ||
537 | sub_object_list[3] = sub_object_list[2]; | ||
538 | sub_object_list[2] = obj_desc; | ||
539 | info->return_flags |= ACPI_OBJECT_REPAIRED; | ||
540 | |||
541 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, | ||
542 | info->node_flags, | ||
543 | "PRT[%X]: Fixed reversed SourceName and SourceIndex", | ||
544 | index)); | ||
545 | } | ||
546 | |||
547 | /* Point to the next union acpi_operand_object in the top level package */ | ||
548 | |||
549 | top_object_list++; | ||
550 | } | ||
551 | |||
552 | return (AE_OK); | ||
531 | } | 553 | } |
532 | 554 | ||
533 | /****************************************************************************** | 555 | /****************************************************************************** |
@@ -601,6 +623,50 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info, | |||
601 | 623 | ||
602 | /****************************************************************************** | 624 | /****************************************************************************** |
603 | * | 625 | * |
626 | * FUNCTION: acpi_ns_repair_TSS | ||
627 | * | ||
628 | * PARAMETERS: info - Method execution information block | ||
629 | * return_object_ptr - Pointer to the object returned from the | ||
630 | * evaluation of a method or object | ||
631 | * | ||
632 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
633 | * | ||
634 | * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list | ||
635 | * descending by the power dissipation values. | ||
636 | * | ||
637 | *****************************************************************************/ | ||
638 | |||
639 | static acpi_status | ||
640 | acpi_ns_repair_TSS(struct acpi_evaluate_info *info, | ||
641 | union acpi_operand_object **return_object_ptr) | ||
642 | { | ||
643 | union acpi_operand_object *return_object = *return_object_ptr; | ||
644 | acpi_status status; | ||
645 | struct acpi_namespace_node *node; | ||
646 | |||
647 | /* | ||
648 | * We can only sort the _TSS return package if there is no _PSS in the | ||
649 | * same scope. This is because if _PSS is present, the ACPI specification | ||
650 | * dictates that the _TSS Power Dissipation field is to be ignored, and | ||
651 | * therefore some BIOSs leave garbage values in the _TSS Power field(s). | ||
652 | * In this case, it is best to just return the _TSS package as-is. | ||
653 | * (May, 2011) | ||
654 | */ | ||
655 | status = acpi_ns_get_node(info->node, "^_PSS", | ||
656 | ACPI_NS_NO_UPSEARCH, &node); | ||
657 | if (ACPI_SUCCESS(status)) { | ||
658 | return (AE_OK); | ||
659 | } | ||
660 | |||
661 | status = acpi_ns_check_sorted_list(info, return_object, 5, 1, | ||
662 | ACPI_SORT_DESCENDING, | ||
663 | "PowerDissipation"); | ||
664 | |||
665 | return (status); | ||
666 | } | ||
667 | |||
668 | /****************************************************************************** | ||
669 | * | ||
604 | * FUNCTION: acpi_ns_check_sorted_list | 670 | * FUNCTION: acpi_ns_check_sorted_list |
605 | * | 671 | * |
606 | * PARAMETERS: info - Method execution information block | 672 | * PARAMETERS: info - Method execution information block |
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 608ebb56b671..b62a0f4f4f9b 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c | |||
@@ -652,8 +652,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, | |||
652 | 652 | ||
653 | name_found = FALSE; | 653 | name_found = FALSE; |
654 | 654 | ||
655 | for (table_index = 0; table_index < 4 && !name_found; | 655 | for (table_index = 0; |
656 | table_index++) { | 656 | table_index < package_element->package.count |
657 | && !name_found; table_index++) { | ||
657 | if (*sub_object_list && /* Null object allowed */ | 658 | if (*sub_object_list && /* Null object allowed */ |
658 | ((ACPI_TYPE_STRING == | 659 | ((ACPI_TYPE_STRING == |
659 | (*sub_object_list)->common.type) || | 660 | (*sub_object_list)->common.type) || |
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index f8b55b426c9d..65f3e1c5b598 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c | |||
@@ -273,17 +273,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, | |||
273 | */ | 273 | */ |
274 | user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); | 274 | user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); |
275 | 275 | ||
276 | /* Each element of the top-level package must also be a package */ | ||
277 | |||
278 | if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) { | ||
279 | ACPI_ERROR((AE_INFO, | ||
280 | "(PRT[%u]) Need sub-package, found %s", | ||
281 | index, | ||
282 | acpi_ut_get_object_type_name | ||
283 | (*top_object_list))); | ||
284 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
285 | } | ||
286 | |||
287 | /* Each sub-package must be of length 4 */ | 276 | /* Each sub-package must be of length 4 */ |
288 | 277 | ||
289 | if ((*top_object_list)->package.count != 4) { | 278 | if ((*top_object_list)->package.count != 4) { |
@@ -327,22 +316,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, | |||
327 | user_prt->pin = (u32) obj_desc->integer.value; | 316 | user_prt->pin = (u32) obj_desc->integer.value; |
328 | 317 | ||
329 | /* | 318 | /* |
330 | * If the BIOS has erroneously reversed the _PRT source_name (index 2) | ||
331 | * and the source_index (index 3), fix it. _PRT is important enough to | ||
332 | * workaround this BIOS error. This also provides compatibility with | ||
333 | * other ACPI implementations. | ||
334 | */ | ||
335 | obj_desc = sub_object_list[3]; | ||
336 | if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { | ||
337 | sub_object_list[3] = sub_object_list[2]; | ||
338 | sub_object_list[2] = obj_desc; | ||
339 | |||
340 | ACPI_WARNING((AE_INFO, | ||
341 | "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", | ||
342 | index)); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * 3) Third subobject: Dereference the PRT.source_name | 319 | * 3) Third subobject: Dereference the PRT.source_name |
347 | * The name may be unresolved (slack mode), so allow a null object | 320 | * The name may be unresolved (slack mode), so allow a null object |
348 | */ | 321 | */ |