diff options
author | Bob Moore <robert.moore@intel.com> | 2009-12-11 02:29:44 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-15 17:29:37 -0500 |
commit | d4085a3ffee8828f7f1bae7fa3cf5e58f59ba627 (patch) | |
tree | 4c2397ce902284b20c21c3b96d393707311c46d4 /drivers/acpi/acpica | |
parent | e31c32cfe52e98344dad28853c3331879f72c4b0 (diff) |
ACPICA: Predefined name repair: automatically remove null package elements
This change will automatically remove embedded and trailing NULL
package elements from returned package objects that are defined
to containe a variable number of sub-packages. The driver is then
presented with a package with no null elements to deal with.
ACPICA BZ 819.
http://www.acpica.org/bugzilla/show_bug.cgi?id=819
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/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 59 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 79 |
3 files changed, 65 insertions, 78 deletions
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 14cef45bd6c4..61edb156e8d0 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
@@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, | |||
296 | acpi_status validate_status, | 296 | acpi_status validate_status, |
297 | union acpi_operand_object **return_object_ptr); | 297 | union acpi_operand_object **return_object_ptr); |
298 | 298 | ||
299 | void | ||
300 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, | ||
301 | u8 package_type, | ||
302 | union acpi_operand_object *obj_desc); | ||
303 | |||
299 | /* | 304 | /* |
300 | * nssearch - Namespace searching and entry | 305 | * nssearch - Namespace searching and entry |
301 | */ | 306 | */ |
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 239fa2f731ca..d34fa59548f7 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -231,9 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
231 | * Note: Package may have been newly created by call above. | 231 | * Note: Package may have been newly created by call above. |
232 | */ | 232 | */ |
233 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { | 233 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { |
234 | |||
235 | /* TBD: For variable-length Packages, remove NULL elements here */ | ||
236 | |||
237 | status = acpi_ns_check_package(data, return_object_ptr); | 234 | status = acpi_ns_check_package(data, return_object_ptr); |
238 | if (ACPI_FAILURE(status)) { | 235 | if (ACPI_FAILURE(status)) { |
239 | goto exit; | 236 | goto exit; |
@@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data, | |||
439 | data->pathname, package->ret_info.type, | 436 | data->pathname, package->ret_info.type, |
440 | return_object->package.count)); | 437 | return_object->package.count)); |
441 | 438 | ||
439 | /* | ||
440 | * For variable-length Packages, we can safely remove all embedded | ||
441 | * and trailing NULL package elements | ||
442 | */ | ||
443 | acpi_ns_remove_null_elements(data, package->ret_info.type, | ||
444 | return_object); | ||
445 | |||
442 | /* Extract package count and elements array */ | 446 | /* Extract package count and elements array */ |
443 | 447 | ||
444 | elements = return_object->package.elements; | 448 | elements = return_object->package.elements; |
@@ -692,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, | |||
692 | union acpi_operand_object *sub_package; | 696 | union acpi_operand_object *sub_package; |
693 | union acpi_operand_object **sub_elements; | 697 | union acpi_operand_object **sub_elements; |
694 | acpi_status status; | 698 | acpi_status status; |
695 | u8 non_trailing_null = FALSE; | ||
696 | u32 expected_count; | 699 | u32 expected_count; |
697 | u32 i; | 700 | u32 i; |
698 | u32 j; | 701 | u32 j; |
699 | 702 | ||
700 | /* Validate each sub-Package in the parent Package */ | 703 | /* |
701 | 704 | * Validate each sub-Package in the parent Package | |
705 | * | ||
706 | * NOTE: assumes list of sub-packages contains no NULL elements. | ||
707 | * Any NULL elements should have been removed by earlier call | ||
708 | * to acpi_ns_remove_null_elements. | ||
709 | */ | ||
702 | for (i = 0; i < count; i++) { | 710 | for (i = 0; i < count; i++) { |
703 | /* | ||
704 | * Handling for NULL package elements. For now, we will simply allow | ||
705 | * a parent package with trailing NULL elements. This can happen if | ||
706 | * the package was defined to be longer than the initializer list. | ||
707 | * This is legal as per the ACPI specification. It is often used | ||
708 | * to allow for dynamic initialization of a Package. | ||
709 | * | ||
710 | * A future enhancement may be to simply truncate the package to | ||
711 | * remove the trailing NULL elements. | ||
712 | */ | ||
713 | if (!(*elements)) { | ||
714 | if (!non_trailing_null) { | ||
715 | |||
716 | /* Ensure the remaining elements are all NULL */ | ||
717 | |||
718 | for (j = 1; j < (count - i + 1); j++) { | ||
719 | if (elements[j]) { | ||
720 | non_trailing_null = TRUE; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | if (!non_trailing_null) { | ||
725 | |||
726 | /* Ignore the trailing NULL elements */ | ||
727 | |||
728 | return (AE_OK); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | /* There are trailing non-null elements, issue warning */ | ||
733 | |||
734 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | ||
735 | data->node_flags, | ||
736 | "Found NULL element at package index %u", | ||
737 | i)); | ||
738 | elements++; | ||
739 | continue; | ||
740 | } | ||
741 | |||
742 | sub_package = *elements; | 711 | sub_package = *elements; |
743 | sub_elements = sub_package->package.elements; | 712 | sub_elements = sub_package->package.elements; |
744 | 713 | ||
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index e7373eb6cfa5..f13691c1cca5 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
46 | #include "accommon.h" | 46 | #include "accommon.h" |
47 | #include "acnamesp.h" | 47 | #include "acnamesp.h" |
48 | #include "acpredef.h" | ||
48 | 49 | ||
49 | #define _COMPONENT ACPI_NAMESPACE | 50 | #define _COMPONENT ACPI_NAMESPACE |
50 | ACPI_MODULE_NAME("nsrepair2") | 51 | ACPI_MODULE_NAME("nsrepair2") |
@@ -93,9 +94,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | |||
93 | u8 sort_direction, char *sort_key_name); | 94 | u8 sort_direction, char *sort_key_name); |
94 | 95 | ||
95 | static acpi_status | 96 | static acpi_status |
96 | acpi_ns_remove_null_elements(union acpi_operand_object *package); | ||
97 | |||
98 | static acpi_status | ||
99 | acpi_ns_sort_list(union acpi_operand_object **elements, | 97 | acpi_ns_sort_list(union acpi_operand_object **elements, |
100 | u32 count, u32 index, u8 sort_direction); | 98 | u32 count, u32 index, u8 sort_direction); |
101 | 99 | ||
@@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | |||
456 | } | 454 | } |
457 | 455 | ||
458 | /* | 456 | /* |
459 | * Detect any NULL package elements and remove them from the | 457 | * NOTE: assumes list of sub-packages contains no NULL elements. |
460 | * package. | 458 | * Any NULL elements should have been removed by earlier call |
461 | * | 459 | * to acpi_ns_remove_null_elements. |
462 | * TBD: We may want to do this for all predefined names that | ||
463 | * return a variable-length package of packages. | ||
464 | */ | 460 | */ |
465 | status = acpi_ns_remove_null_elements(return_object); | ||
466 | if (status == AE_NULL_ENTRY) { | ||
467 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
468 | "%s: NULL elements removed from package\n", | ||
469 | data->pathname)); | ||
470 | |||
471 | /* Exit if package is now zero length */ | ||
472 | |||
473 | if (!return_object->package.count) { | ||
474 | return (AE_NULL_ENTRY); | ||
475 | } | ||
476 | } | ||
477 | |||
478 | outer_elements = return_object->package.elements; | 461 | outer_elements = return_object->package.elements; |
479 | outer_element_count = return_object->package.count; | 462 | outer_element_count = return_object->package.count; |
480 | if (!outer_element_count) { | 463 | if (!outer_element_count) { |
@@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | |||
544 | * | 527 | * |
545 | * FUNCTION: acpi_ns_remove_null_elements | 528 | * FUNCTION: acpi_ns_remove_null_elements |
546 | * | 529 | * |
547 | * PARAMETERS: obj_desc - A Package object | 530 | * PARAMETERS: Data - Pointer to validation data structure |
531 | * package_type - An acpi_return_package_types value | ||
532 | * obj_desc - A Package object | ||
548 | * | 533 | * |
549 | * RETURN: Status. AE_NULL_ENTRY means that one or more elements were | 534 | * RETURN: None. |
550 | * removed. | ||
551 | * | 535 | * |
552 | * DESCRIPTION: Remove all NULL package elements and update the package count. | 536 | * DESCRIPTION: Remove all NULL package elements from packages that contain |
537 | * a variable number of sub-packages. | ||
553 | * | 538 | * |
554 | *****************************************************************************/ | 539 | *****************************************************************************/ |
555 | 540 | ||
556 | static acpi_status | 541 | void |
557 | acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) | 542 | acpi_ns_remove_null_elements(struct acpi_predefined_data *data, |
543 | u8 package_type, | ||
544 | union acpi_operand_object *obj_desc) | ||
558 | { | 545 | { |
559 | union acpi_operand_object **source; | 546 | union acpi_operand_object **source; |
560 | union acpi_operand_object **dest; | 547 | union acpi_operand_object **dest; |
561 | acpi_status status = AE_OK; | ||
562 | u32 count; | 548 | u32 count; |
563 | u32 new_count; | 549 | u32 new_count; |
564 | u32 i; | 550 | u32 i; |
565 | 551 | ||
552 | ACPI_FUNCTION_NAME(ns_remove_null_elements); | ||
553 | |||
554 | /* | ||
555 | * PTYPE1 packages contain no subpackages. | ||
556 | * PTYPE2 packages contain a variable number of sub-packages. We can | ||
557 | * safely remove all NULL elements from the PTYPE2 packages. | ||
558 | */ | ||
559 | switch (package_type) { | ||
560 | case ACPI_PTYPE1_FIXED: | ||
561 | case ACPI_PTYPE1_VAR: | ||
562 | case ACPI_PTYPE1_OPTION: | ||
563 | return; | ||
564 | |||
565 | case ACPI_PTYPE2: | ||
566 | case ACPI_PTYPE2_COUNT: | ||
567 | case ACPI_PTYPE2_PKG_COUNT: | ||
568 | case ACPI_PTYPE2_FIXED: | ||
569 | case ACPI_PTYPE2_MIN: | ||
570 | case ACPI_PTYPE2_REV_FIXED: | ||
571 | break; | ||
572 | |||
573 | default: | ||
574 | return; | ||
575 | } | ||
576 | |||
566 | count = obj_desc->package.count; | 577 | count = obj_desc->package.count; |
567 | new_count = count; | 578 | new_count = count; |
568 | 579 | ||
569 | source = obj_desc->package.elements; | 580 | source = obj_desc->package.elements; |
570 | dest = source; | 581 | dest = source; |
571 | 582 | ||
572 | /* Examine all elements of the package object */ | 583 | /* Examine all elements of the package object, remove nulls */ |
573 | 584 | ||
574 | for (i = 0; i < count; i++) { | 585 | for (i = 0; i < count; i++) { |
575 | if (!*source) { | 586 | if (!*source) { |
576 | status = AE_NULL_ENTRY; | ||
577 | new_count--; | 587 | new_count--; |
578 | } else { | 588 | } else { |
579 | *dest = *source; | 589 | *dest = *source; |
@@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) | |||
582 | source++; | 592 | source++; |
583 | } | 593 | } |
584 | 594 | ||
585 | if (status == AE_NULL_ENTRY) { | 595 | /* Update parent package if any null elements were removed */ |
596 | |||
597 | if (new_count < count) { | ||
598 | ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, | ||
599 | "%s: Found and removed %u NULL elements\n", | ||
600 | data->pathname, (count - new_count))); | ||
586 | 601 | ||
587 | /* NULL terminate list and update the package count */ | 602 | /* NULL terminate list and update the package count */ |
588 | 603 | ||
589 | *dest = NULL; | 604 | *dest = NULL; |
590 | obj_desc->package.count = new_count; | 605 | obj_desc->package.count = new_count; |
591 | } | 606 | } |
592 | |||
593 | return (status); | ||
594 | } | 607 | } |
595 | 608 | ||
596 | /****************************************************************************** | 609 | /****************************************************************************** |