diff options
author | Bob Moore <robert.moore@intel.com> | 2008-04-10 11:06:39 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-04-22 14:29:24 -0400 |
commit | 53cf174409a24e8388e1d554d27436275fc81fe7 (patch) | |
tree | 52883d192ba1b4bd978a8ca9d30af1e533679e70 | |
parent | 1c12a7dde1752f2c40fe170cabff463a0b362720 (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>
-rw-r--r-- | drivers/acpi/executer/excreate.c | 20 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsaccess.c | 96 |
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 */ |