aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-04-10 11:06:39 -0400
committerLen Brown <len.brown@intel.com>2008-04-22 14:29:24 -0400
commit53cf174409a24e8388e1d554d27436275fc81fe7 (patch)
tree52883d192ba1b4bd978a8ca9d30af1e533679e70 /drivers/acpi
parent1c12a7dde1752f2c40fe170cabff463a0b362720 (diff)
ACPICA: Fix for Alias operator to see target child objects
Fixed a problem with the Alias operator when the target of the alias is a named ASL operator that opens a new scope -- Scope, Device, PowerResource, Processor, and ThermalZone. In these cases, any children of the original operator could not be accessed via the alias, potentially causing unexpected AE_NOT_FOUND exceptions. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/executer/excreate.c20
-rw-r--r--drivers/acpi/namespace/nsaccess.c96
2 files changed, 75 insertions, 41 deletions
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 6e9a23e47fef..b3914395851b 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -96,6 +96,9 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
96 * to the original Node. 96 * to the original Node.
97 */ 97 */
98 switch (target_node->type) { 98 switch (target_node->type) {
99
100 /* For these types, the sub-object can change dynamically via a Store */
101
99 case ACPI_TYPE_INTEGER: 102 case ACPI_TYPE_INTEGER:
100 case ACPI_TYPE_STRING: 103 case ACPI_TYPE_STRING:
101 case ACPI_TYPE_BUFFER: 104 case ACPI_TYPE_BUFFER:
@@ -103,9 +106,18 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
103 case ACPI_TYPE_BUFFER_FIELD: 106 case ACPI_TYPE_BUFFER_FIELD:
104 107
105 /* 108 /*
109 * These types open a new scope, so we need the NS node in order to access
110 * any children.
111 */
112 case ACPI_TYPE_DEVICE:
113 case ACPI_TYPE_POWER:
114 case ACPI_TYPE_PROCESSOR:
115 case ACPI_TYPE_THERMAL:
116 case ACPI_TYPE_LOCAL_SCOPE:
117
118 /*
106 * The new alias has the type ALIAS and points to the original 119 * The new alias has the type ALIAS and points to the original
107 * NS node, not the object itself. This is because for these 120 * NS node, not the object itself.
108 * types, the object can change dynamically via a Store.
109 */ 121 */
110 alias_node->type = ACPI_TYPE_LOCAL_ALIAS; 122 alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
111 alias_node->object = 123 alias_node->object =
@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
115 case ACPI_TYPE_METHOD: 127 case ACPI_TYPE_METHOD:
116 128
117 /* 129 /*
118 * The new alias has the type ALIAS and points to the original 130 * Control method aliases need to be differentiated
119 * NS node, not the object itself. This is because for these
120 * types, the object can change dynamically via a Store.
121 */ 131 */
122 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; 132 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
123 alias_node->object = 133 alias_node->object =
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 32a01673cae8..54852fbfc878 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -581,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
581 return_ACPI_STATUS(status); 581 return_ACPI_STATUS(status);
582 } 582 }
583 583
584 /* 584 /* More segments to follow? */
585 * Sanity typecheck of the target object: 585
586 * 586 if (num_segments > 0) {
587 * If 1) This is the last segment (num_segments == 0) 587 /*
588 * 2) And we are looking for a specific type 588 * If we have an alias to an object that opens a scope (such as a
589 * (Not checking for TYPE_ANY) 589 * device or processor), we need to dereference the alias here so that
590 * 3) Which is not an alias 590 * we can access any children of the original node (via the remaining
591 * 4) Which is not a local type (TYPE_SCOPE) 591 * segments).
592 * 5) And the type of target object is known (not TYPE_ANY) 592 */
593 * 6) And target object does not match what we are looking for 593 if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) {
594 * 594 if (acpi_ns_opens_scope
595 * Then we have a type mismatch. Just warn and ignore it. 595 (((struct acpi_namespace_node *)this_node->
596 */ 596 object)->type)) {
597 if ((num_segments == 0) && 597 this_node =
598 (type_to_check_for != ACPI_TYPE_ANY) && 598 (struct acpi_namespace_node *)
599 (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && 599 this_node->object;
600 (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && 600 }
601 (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && 601 }
602 (this_node->type != ACPI_TYPE_ANY) &&
603 (this_node->type != type_to_check_for)) {
604
605 /* Complain about a type mismatch */
606
607 ACPI_WARNING((AE_INFO,
608 "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
609 ACPI_CAST_PTR(char, &simple_name),
610 acpi_ut_get_type_name(this_node->type),
611 acpi_ut_get_type_name
612 (type_to_check_for)));
613 } 602 }
614 603
615 /* 604 /* Special handling for the last segment (num_segments == 0) */
616 * If this is the last name segment and we are not looking for a 605
617 * specific type, but the type of found object is known, use that type 606 else {
618 * to see if it opens a scope. 607 /*
619 */ 608 * Sanity typecheck of the target object:
620 if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) { 609 *
621 type = this_node->type; 610 * If 1) This is the last segment (num_segments == 0)
611 * 2) And we are looking for a specific type
612 * (Not checking for TYPE_ANY)
613 * 3) Which is not an alias
614 * 4) Which is not a local type (TYPE_SCOPE)
615 * 5) And the type of target object is known (not TYPE_ANY)
616 * 6) And target object does not match what we are looking for
617 *
618 * Then we have a type mismatch. Just warn and ignore it.
619 */
620 if ((type_to_check_for != ACPI_TYPE_ANY) &&
621 (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
622 (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS)
623 && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE)
624 && (this_node->type != ACPI_TYPE_ANY)
625 && (this_node->type != type_to_check_for)) {
626
627 /* Complain about a type mismatch */
628
629 ACPI_WARNING((AE_INFO,
630 "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
631 ACPI_CAST_PTR(char, &simple_name),
632 acpi_ut_get_type_name(this_node->
633 type),
634 acpi_ut_get_type_name
635 (type_to_check_for)));
636 }
637
638 /*
639 * If this is the last name segment and we are not looking for a
640 * specific type, but the type of found object is known, use that type
641 * to (later) see if it opens a scope.
642 */
643 if (type == ACPI_TYPE_ANY) {
644 type = this_node->type;
645 }
622 } 646 }
623 647
624 /* Point to next name segment and make this node current */ 648 /* Point to next name segment and make this node current */