aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-04-10 11:06:44 -0400
committerLen Brown <len.brown@intel.com>2008-04-22 23:01:51 -0400
commitcca97b81564c5edbc8700ebb64fc2b4e13dfa51f (patch)
treecf997613fe23d04d05be41d727602016e0a1e350 /drivers/acpi/dispatcher
parent66e2c0bcc5f6b8454d9091f6ba9ef4090abca4fd (diff)
ACPICA: Fix for some local named nodes not marked temporary and to disallow duplicates
Fixed a problem with the CreateField, CreateXXXField (Bit, Byte, Word, Dword, Qword), Field, BankField, and IndexField operators when invoked from inside an executing control method. In this case, these operators created namespace nodes that were incorrectly left marked as permanent nodes instead of temporary nodes. This could cause a problem if there is race condition between an exiting control method and a running namespace walk. (Reported by Linn Crosetto). Fixed a problem where the CreateField and CreateXXXField operators would incorrectly allow duplicate names (the name of the field) with no exception generated. 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/dispatcher')
-rw-r--r--drivers/acpi/dispatcher/dsfield.c121
-rw-r--r--drivers/acpi/dispatcher/dswload.c6
2 files changed, 79 insertions, 48 deletions
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index e87f6bfbfa5c..0befcff19f5a 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
89 89
90 ACPI_FUNCTION_TRACE(ds_create_buffer_field); 90 ACPI_FUNCTION_TRACE(ds_create_buffer_field);
91 91
92 /* Get the name_string argument */ 92 /*
93 93 * Get the name_string argument (name of the new buffer_field)
94 */
94 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { 95 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
96
97 /* For create_field, name is the 4th argument */
98
95 arg = acpi_ps_get_arg(op, 3); 99 arg = acpi_ps_get_arg(op, 3);
96 } else { 100 } else {
97 /* Create Bit/Byte/Word/Dword field */ 101 /* For all other create_xXXField operators, name is the 3rd argument */
98 102
99 arg = acpi_ps_get_arg(op, 2); 103 arg = acpi_ps_get_arg(op, 2);
100 } 104 }
@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
107 node = walk_state->deferred_node; 111 node = walk_state->deferred_node;
108 status = AE_OK; 112 status = AE_OK;
109 } else { 113 } else {
110 /* 114 /* Execute flag should always be set when this function is entered */
111 * During the load phase, we want to enter the name of the field into 115
112 * the namespace. During the execute phase (when we evaluate the size 116 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
113 * operand), we want to lookup the name 117 return_ACPI_STATUS(AE_AML_INTERNAL);
114 */
115 if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
116 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
117 } else {
118 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
119 ACPI_NS_ERROR_IF_FOUND;
120 } 118 }
121 119
122 /* 120 /* Creating new namespace node, should not already exist */
123 * Enter the name_string into the namespace 121
124 */ 122 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
123 ACPI_NS_ERROR_IF_FOUND;
124
125 /* Mark node temporary if we are executing a method */
126
127 if (walk_state->method_node) {
128 flags |= ACPI_NS_TEMPORARY;
129 }
130
131 /* Enter the name_string into the namespace */
132
125 status = 133 status =
126 acpi_ns_lookup(walk_state->scope_info, 134 acpi_ns_lookup(walk_state->scope_info,
127 arg->common.value.string, ACPI_TYPE_ANY, 135 arg->common.value.string, ACPI_TYPE_ANY,
128 ACPI_IMODE_LOAD_PASS1, flags, walk_state, 136 ACPI_IMODE_LOAD_PASS1, flags, walk_state,
129 &(node)); 137 &node);
130 if (ACPI_FAILURE(status)) { 138 if (ACPI_FAILURE(status)) {
131 ACPI_ERROR_NAMESPACE(arg->common.value.string, status); 139 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
132 return_ACPI_STATUS(status); 140 return_ACPI_STATUS(status);
@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
136 /* 144 /*
137 * We could put the returned object (Node) on the object stack for later, 145 * We could put the returned object (Node) on the object stack for later,
138 * but for now, we will put it in the "op" object that the parser uses, 146 * but for now, we will put it in the "op" object that the parser uses,
139 * so we can get it again at the end of this scope 147 * so we can get it again at the end of this scope.
140 */ 148 */
141 op->common.node = node; 149 op->common.node = node;
142 150
143 /* 151 /*
144 * If there is no object attached to the node, this node was just created 152 * If there is no object attached to the node, this node was just created
145 * and we need to create the field object. Otherwise, this was a lookup 153 * and we need to create the field object. Otherwise, this was a lookup
146 * of an existing node and we don't want to create the field object again. 154 * of an existing node and we don't want to create the field object again.
147 */ 155 */
148 obj_desc = acpi_ns_get_attached_object(node); 156 obj_desc = acpi_ns_get_attached_object(node);
@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
164 } 172 }
165 173
166 /* 174 /*
167 * Remember location in AML stream of the field unit 175 * Remember location in AML stream of the field unit opcode and operands --
168 * opcode and operands -- since the buffer and index 176 * since the buffer and index operands must be evaluated.
169 * operands must be evaluated.
170 */ 177 */
171 second_desc = obj_desc->common.next_object; 178 second_desc = obj_desc->common.next_object;
172 second_desc->extra.aml_start = op->named.data; 179 second_desc->extra.aml_start = op->named.data;
@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
261 268
262 case AML_INT_NAMEDFIELD_OP: 269 case AML_INT_NAMEDFIELD_OP:
263 270
264 /* Lookup the name */ 271 /* Lookup the name, it should already exist */
265 272
266 status = acpi_ns_lookup(walk_state->scope_info, 273 status = acpi_ns_lookup(walk_state->scope_info,
267 (char *)&arg->named.name, 274 (char *)&arg->named.name,
@@ -272,19 +279,16 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
272 if (ACPI_FAILURE(status)) { 279 if (ACPI_FAILURE(status)) {
273 ACPI_ERROR_NAMESPACE((char *)&arg->named.name, 280 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
274 status); 281 status);
275 if (status != AE_ALREADY_EXISTS) { 282 return_ACPI_STATUS(status);
276 return_ACPI_STATUS(status);
277 }
278
279 /* Already exists, ignore error */
280 } else { 283 } else {
281 arg->common.node = info->field_node; 284 arg->common.node = info->field_node;
282 info->field_bit_length = arg->common.value.size; 285 info->field_bit_length = arg->common.value.size;
283 286
284 /* 287 /*
285 * If there is no object attached to the node, this node was just created 288 * If there is no object attached to the node, this node was
286 * and we need to create the field object. Otherwise, this was a lookup 289 * just created and we need to create the field object.
287 * of an existing node and we don't want to create the field object again. 290 * Otherwise, this was a lookup of an existing node and we
291 * don't want to create the field object again.
288 */ 292 */
289 if (!acpi_ns_get_attached_object 293 if (!acpi_ns_get_attached_object
290 (info->field_node)) { 294 (info->field_node)) {
@@ -409,18 +413,23 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
409 413
410 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); 414 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
411 415
412 /* 416 /* Execute flag should always be set when this function is entered */
413 * During the load phase, we want to enter the name of the field into 417
414 * the namespace. During the execute phase (when we evaluate the bank_value 418 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
415 * operand), we want to lookup the name. 419 if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
416 */ 420
417 if (walk_state->deferred_node) { 421 /* bank_field Op is deferred, just return OK */
418 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; 422
419 } else { 423 return_ACPI_STATUS(AE_OK);
420 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 424 }
421 ACPI_NS_ERROR_IF_FOUND; 425
426 return_ACPI_STATUS(AE_AML_INTERNAL);
422 } 427 }
423 428
429 /*
430 * Get the field_list argument for this opcode. This is the start of the
431 * list of field elements.
432 */
424 switch (walk_state->opcode) { 433 switch (walk_state->opcode) {
425 case AML_FIELD_OP: 434 case AML_FIELD_OP:
426 arg = acpi_ps_get_arg(op, 2); 435 arg = acpi_ps_get_arg(op, 2);
@@ -441,18 +450,34 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
441 return_ACPI_STATUS(AE_BAD_PARAMETER); 450 return_ACPI_STATUS(AE_BAD_PARAMETER);
442 } 451 }
443 452
453 if (!arg) {
454 return_ACPI_STATUS(AE_AML_NO_OPERAND);
455 }
456
457 /* Creating new namespace node(s), should not already exist */
458
459 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
460 ACPI_NS_ERROR_IF_FOUND;
461
462 /* Mark node(s) temporary if we are executing a method */
463
464 if (walk_state->method_node) {
465 flags |= ACPI_NS_TEMPORARY;
466 }
467
444 /* 468 /*
445 * Walk the list of entries in the field_list 469 * Walk the list of entries in the field_list
446 */ 470 */
447 while (arg) { 471 while (arg) {
448 472 /*
449 /* Ignore OFFSET and ACCESSAS terms here */ 473 * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
450 474 * field names in order to enter them into the namespace.
475 */
451 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { 476 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
452 status = acpi_ns_lookup(walk_state->scope_info, 477 status = acpi_ns_lookup(walk_state->scope_info,
453 (char *)&arg->named.name, 478 (char *)&arg->named.name, type,
454 type, ACPI_IMODE_LOAD_PASS1, 479 ACPI_IMODE_LOAD_PASS1, flags,
455 flags, walk_state, &node); 480 walk_state, &node);
456 if (ACPI_FAILURE(status)) { 481 if (ACPI_FAILURE(status)) {
457 ACPI_ERROR_NAMESPACE((char *)&arg->named.name, 482 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
458 status); 483 status);
@@ -468,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
468 arg->common.node = node; 493 arg->common.node = node;
469 } 494 }
470 495
471 /* Move to next field in the list */ 496 /* Get the next field element in the list */
472 497
473 arg = arg->common.next; 498 arg = arg->common.next;
474 } 499 }
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index ec68c1df3932..775b18390c36 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -776,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
776 acpi_ns_lookup(walk_state->scope_info, buffer_ptr, 776 acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
777 object_type, ACPI_IMODE_LOAD_PASS2, flags, 777 object_type, ACPI_IMODE_LOAD_PASS2, flags,
778 walk_state, &node); 778 walk_state, &node);
779
780 if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
781 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
782 "***New Node [%4.4s] %p is temporary\n",
783 acpi_ut_get_node_name(node), node));
784 }
779 break; 785 break;
780 } 786 }
781 787