aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpica/nspredef.c7
-rw-r--r--drivers/acpi/acpica/nsrepair2.c114
-rw-r--r--drivers/acpi/acpica/rscalc.c5
-rw-r--r--drivers/acpi/acpica/rscreate.c27
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
89static acpi_status 89static acpi_status
90acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
91 union acpi_operand_object **return_object_ptr);
92
93static acpi_status
90acpi_ns_repair_PSS(struct acpi_evaluate_info *info, 94acpi_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
504static acpi_status 510static acpi_status
505acpi_ns_repair_TSS(struct acpi_evaluate_info *info, 511acpi_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
639static acpi_status
640acpi_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 */