diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 337 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswload.c | 132 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsdump.c | 4 | ||||
-rw-r--r-- | drivers/acpi/utilities/utglobal.c | 9 | ||||
-rw-r--r-- | drivers/acpi/utilities/utmisc.c | 79 |
5 files changed, 338 insertions, 223 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 36c1ca0b9adb..58ad00b31ee9 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -53,133 +53,6 @@ ACPI_MODULE_NAME("dsmethod") | |||
53 | 53 | ||
54 | /******************************************************************************* | 54 | /******************************************************************************* |
55 | * | 55 | * |
56 | * FUNCTION: acpi_ds_parse_method | ||
57 | * | ||
58 | * PARAMETERS: Node - Method node | ||
59 | * | ||
60 | * RETURN: Status | ||
61 | * | ||
62 | * DESCRIPTION: Parse the AML that is associated with the method. | ||
63 | * | ||
64 | * MUTEX: Assumes parser is locked | ||
65 | * | ||
66 | ******************************************************************************/ | ||
67 | acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) | ||
68 | { | ||
69 | acpi_status status; | ||
70 | union acpi_operand_object *obj_desc; | ||
71 | union acpi_parse_object *op; | ||
72 | struct acpi_walk_state *walk_state; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); | ||
75 | |||
76 | /* Parameter Validation */ | ||
77 | |||
78 | if (!node) { | ||
79 | return_ACPI_STATUS(AE_NULL_ENTRY); | ||
80 | } | ||
81 | |||
82 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
83 | "**** Parsing [%4.4s] **** named_obj=%p\n", | ||
84 | acpi_ut_get_node_name(node), node)); | ||
85 | |||
86 | /* Extract the method object from the method Node */ | ||
87 | |||
88 | obj_desc = acpi_ns_get_attached_object(node); | ||
89 | if (!obj_desc) { | ||
90 | return_ACPI_STATUS(AE_NULL_OBJECT); | ||
91 | } | ||
92 | |||
93 | /* Create a mutex for the method if there is a concurrency limit */ | ||
94 | |||
95 | if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && | ||
96 | (!obj_desc->method.semaphore)) { | ||
97 | status = acpi_os_create_semaphore(obj_desc->method.concurrency, | ||
98 | obj_desc->method.concurrency, | ||
99 | &obj_desc->method.semaphore); | ||
100 | if (ACPI_FAILURE(status)) { | ||
101 | return_ACPI_STATUS(status); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Allocate a new parser op to be the root of the parsed | ||
107 | * method tree | ||
108 | */ | ||
109 | op = acpi_ps_alloc_op(AML_METHOD_OP); | ||
110 | if (!op) { | ||
111 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
112 | } | ||
113 | |||
114 | /* Init new op with the method name and pointer back to the Node */ | ||
115 | |||
116 | acpi_ps_set_name(op, node->name.integer); | ||
117 | op->common.node = node; | ||
118 | |||
119 | /* | ||
120 | * Get a new owner_id for objects created by this method. Namespace | ||
121 | * objects (such as Operation Regions) can be created during the | ||
122 | * first pass parse. | ||
123 | */ | ||
124 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); | ||
125 | if (ACPI_FAILURE(status)) { | ||
126 | goto cleanup; | ||
127 | } | ||
128 | |||
129 | /* Create and initialize a new walk state */ | ||
130 | |||
131 | walk_state = | ||
132 | acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, | ||
133 | NULL); | ||
134 | if (!walk_state) { | ||
135 | status = AE_NO_MEMORY; | ||
136 | goto cleanup2; | ||
137 | } | ||
138 | |||
139 | status = acpi_ds_init_aml_walk(walk_state, op, node, | ||
140 | obj_desc->method.aml_start, | ||
141 | obj_desc->method.aml_length, NULL, 1); | ||
142 | if (ACPI_FAILURE(status)) { | ||
143 | acpi_ds_delete_walk_state(walk_state); | ||
144 | goto cleanup2; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Parse the method, first pass | ||
149 | * | ||
150 | * The first pass load is where newly declared named objects are added into | ||
151 | * the namespace. Actual evaluation of the named objects (what would be | ||
152 | * called a "second pass") happens during the actual execution of the | ||
153 | * method so that operands to the named objects can take on dynamic | ||
154 | * run-time values. | ||
155 | */ | ||
156 | status = acpi_ps_parse_aml(walk_state); | ||
157 | if (ACPI_FAILURE(status)) { | ||
158 | goto cleanup2; | ||
159 | } | ||
160 | |||
161 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
162 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", | ||
163 | acpi_ut_get_node_name(node), node, op)); | ||
164 | |||
165 | /* | ||
166 | * Delete the parse tree. We simply re-parse the method for every | ||
167 | * execution since there isn't much overhead (compared to keeping lots | ||
168 | * of parse trees around) | ||
169 | */ | ||
170 | acpi_ns_delete_namespace_subtree(node); | ||
171 | acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); | ||
172 | |||
173 | cleanup2: | ||
174 | acpi_ut_release_owner_id(&obj_desc->method.owner_id); | ||
175 | |||
176 | cleanup: | ||
177 | acpi_ps_delete_parse_tree(op); | ||
178 | return_ACPI_STATUS(status); | ||
179 | } | ||
180 | |||
181 | /******************************************************************************* | ||
182 | * | ||
183 | * FUNCTION: acpi_ds_begin_method_execution | 56 | * FUNCTION: acpi_ds_begin_method_execution |
184 | * | 57 | * |
185 | * PARAMETERS: method_node - Node of the method | 58 | * PARAMETERS: method_node - Node of the method |
@@ -193,7 +66,6 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) | |||
193 | * for clearance to execute. | 66 | * for clearance to execute. |
194 | * | 67 | * |
195 | ******************************************************************************/ | 68 | ******************************************************************************/ |
196 | |||
197 | acpi_status | 69 | acpi_status |
198 | acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | 70 | acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, |
199 | union acpi_operand_object *obj_desc, | 71 | union acpi_operand_object *obj_desc, |
@@ -545,16 +417,54 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
545 | } | 417 | } |
546 | } | 418 | } |
547 | 419 | ||
420 | /* | ||
421 | * There are no more threads executing this method. Perform | ||
422 | * additional cleanup. | ||
423 | * | ||
424 | * The method Node is stored in the walk state | ||
425 | */ | ||
426 | method_node = walk_state->method_node; | ||
427 | |||
428 | /* Lock namespace for possible update */ | ||
429 | |||
430 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
431 | if (ACPI_FAILURE(status)) { | ||
432 | goto exit; | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * Delete any namespace entries created immediately underneath | ||
437 | * the method | ||
438 | */ | ||
439 | if (method_node->child) { | ||
440 | acpi_ns_delete_namespace_subtree(method_node); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Delete any namespace entries created anywhere else within | ||
445 | * the namespace by the execution of this method | ||
446 | */ | ||
447 | acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method. | ||
448 | owner_id); | ||
449 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
450 | |||
451 | /* Are there any other threads currently executing this method? */ | ||
452 | |||
548 | if (walk_state->method_desc->method.thread_count) { | 453 | if (walk_state->method_desc->method.thread_count) { |
454 | /* | ||
455 | * Additional threads. Do not release the owner_id in this case, | ||
456 | * we immediately reuse it for the next thread executing this method | ||
457 | */ | ||
549 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 458 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
550 | "*** Not deleting method namespace, there are still %d threads\n", | 459 | "*** Completed execution of one thread, %d threads remaining\n", |
551 | walk_state->method_desc->method. | 460 | walk_state->method_desc->method. |
552 | thread_count)); | 461 | thread_count)); |
553 | } else { /* This is the last executing thread */ | 462 | } else { |
463 | /* This is the only executing thread for this method */ | ||
554 | 464 | ||
555 | /* | 465 | /* |
556 | * Support to dynamically change a method from not_serialized to | 466 | * Support to dynamically change a method from not_serialized to |
557 | * Serialized if it appears that the method is written foolishly and | 467 | * Serialized if it appears that the method is incorrectly written and |
558 | * does not support multiple thread execution. The best example of this | 468 | * does not support multiple thread execution. The best example of this |
559 | * is if such a method creates namespace objects and blocks. A second | 469 | * is if such a method creates namespace objects and blocks. A second |
560 | * thread will fail with an AE_ALREADY_EXISTS exception | 470 | * thread will fail with an AE_ALREADY_EXISTS exception |
@@ -570,34 +480,8 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
570 | semaphore); | 480 | semaphore); |
571 | } | 481 | } |
572 | 482 | ||
573 | /* | 483 | /* No more threads, we can free the owner_id */ |
574 | * There are no more threads executing this method. Perform | ||
575 | * additional cleanup. | ||
576 | * | ||
577 | * The method Node is stored in the walk state | ||
578 | */ | ||
579 | method_node = walk_state->method_node; | ||
580 | |||
581 | /* | ||
582 | * Delete any namespace entries created immediately underneath | ||
583 | * the method | ||
584 | */ | ||
585 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | ||
586 | if (ACPI_FAILURE(status)) { | ||
587 | goto exit; | ||
588 | } | ||
589 | |||
590 | if (method_node->child) { | ||
591 | acpi_ns_delete_namespace_subtree(method_node); | ||
592 | } | ||
593 | 484 | ||
594 | /* | ||
595 | * Delete any namespace entries created anywhere else within | ||
596 | * the namespace | ||
597 | */ | ||
598 | acpi_ns_delete_namespace_by_owner(walk_state->method_desc-> | ||
599 | method.owner_id); | ||
600 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | ||
601 | acpi_ut_release_owner_id(&walk_state->method_desc->method. | 485 | acpi_ut_release_owner_id(&walk_state->method_desc->method. |
602 | owner_id); | 486 | owner_id); |
603 | } | 487 | } |
@@ -606,3 +490,140 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) | |||
606 | (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); | 490 | (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); |
607 | return_VOID; | 491 | return_VOID; |
608 | } | 492 | } |
493 | |||
494 | #ifdef ACPI_INIT_PARSE_METHODS | ||
495 | /* | ||
496 | * Note 11/2005: Removed this code to parse all methods during table | ||
497 | * load because it causes problems if there are any errors during the | ||
498 | * parse. Also, it seems like overkill and we probably don't want to | ||
499 | * abort a table load because of an issue with a single method. | ||
500 | */ | ||
501 | |||
502 | /******************************************************************************* | ||
503 | * | ||
504 | * FUNCTION: acpi_ds_parse_method | ||
505 | * | ||
506 | * PARAMETERS: Node - Method node | ||
507 | * | ||
508 | * RETURN: Status | ||
509 | * | ||
510 | * DESCRIPTION: Parse the AML that is associated with the method. | ||
511 | * | ||
512 | * MUTEX: Assumes parser is locked | ||
513 | * | ||
514 | ******************************************************************************/ | ||
515 | |||
516 | acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) | ||
517 | { | ||
518 | acpi_status status; | ||
519 | union acpi_operand_object *obj_desc; | ||
520 | union acpi_parse_object *op; | ||
521 | struct acpi_walk_state *walk_state; | ||
522 | |||
523 | ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); | ||
524 | |||
525 | /* Parameter Validation */ | ||
526 | |||
527 | if (!node) { | ||
528 | return_ACPI_STATUS(AE_NULL_ENTRY); | ||
529 | } | ||
530 | |||
531 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
532 | "**** Parsing [%4.4s] **** named_obj=%p\n", | ||
533 | acpi_ut_get_node_name(node), node)); | ||
534 | |||
535 | /* Extract the method object from the method Node */ | ||
536 | |||
537 | obj_desc = acpi_ns_get_attached_object(node); | ||
538 | if (!obj_desc) { | ||
539 | return_ACPI_STATUS(AE_NULL_OBJECT); | ||
540 | } | ||
541 | |||
542 | /* Create a mutex for the method if there is a concurrency limit */ | ||
543 | |||
544 | if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && | ||
545 | (!obj_desc->method.semaphore)) { | ||
546 | status = acpi_os_create_semaphore(obj_desc->method.concurrency, | ||
547 | obj_desc->method.concurrency, | ||
548 | &obj_desc->method.semaphore); | ||
549 | if (ACPI_FAILURE(status)) { | ||
550 | return_ACPI_STATUS(status); | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Allocate a new parser op to be the root of the parsed | ||
556 | * method tree | ||
557 | */ | ||
558 | op = acpi_ps_alloc_op(AML_METHOD_OP); | ||
559 | if (!op) { | ||
560 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
561 | } | ||
562 | |||
563 | /* Init new op with the method name and pointer back to the Node */ | ||
564 | |||
565 | acpi_ps_set_name(op, node->name.integer); | ||
566 | op->common.node = node; | ||
567 | |||
568 | /* | ||
569 | * Get a new owner_id for objects created by this method. Namespace | ||
570 | * objects (such as Operation Regions) can be created during the | ||
571 | * first pass parse. | ||
572 | */ | ||
573 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); | ||
574 | if (ACPI_FAILURE(status)) { | ||
575 | goto cleanup; | ||
576 | } | ||
577 | |||
578 | /* Create and initialize a new walk state */ | ||
579 | |||
580 | walk_state = | ||
581 | acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, | ||
582 | NULL); | ||
583 | if (!walk_state) { | ||
584 | status = AE_NO_MEMORY; | ||
585 | goto cleanup2; | ||
586 | } | ||
587 | |||
588 | status = acpi_ds_init_aml_walk(walk_state, op, node, | ||
589 | obj_desc->method.aml_start, | ||
590 | obj_desc->method.aml_length, NULL, 1); | ||
591 | if (ACPI_FAILURE(status)) { | ||
592 | acpi_ds_delete_walk_state(walk_state); | ||
593 | goto cleanup2; | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * Parse the method, first pass | ||
598 | * | ||
599 | * The first pass load is where newly declared named objects are added into | ||
600 | * the namespace. Actual evaluation of the named objects (what would be | ||
601 | * called a "second pass") happens during the actual execution of the | ||
602 | * method so that operands to the named objects can take on dynamic | ||
603 | * run-time values. | ||
604 | */ | ||
605 | status = acpi_ps_parse_aml(walk_state); | ||
606 | if (ACPI_FAILURE(status)) { | ||
607 | goto cleanup2; | ||
608 | } | ||
609 | |||
610 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
611 | "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", | ||
612 | acpi_ut_get_node_name(node), node, op)); | ||
613 | |||
614 | /* | ||
615 | * Delete the parse tree. We simply re-parse the method for every | ||
616 | * execution since there isn't much overhead (compared to keeping lots | ||
617 | * of parse trees around) | ||
618 | */ | ||
619 | acpi_ns_delete_namespace_subtree(node); | ||
620 | acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); | ||
621 | |||
622 | cleanup2: | ||
623 | acpi_ut_release_owner_id(&obj_desc->method.owner_id); | ||
624 | |||
625 | cleanup: | ||
626 | acpi_ps_delete_parse_tree(op); | ||
627 | return_ACPI_STATUS(status); | ||
628 | } | ||
629 | #endif | ||
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 89d318cbc8a3..44d4f4bb2f92 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c | |||
@@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
127 | char *path; | 127 | char *path; |
128 | u32 flags; | 128 | u32 flags; |
129 | 129 | ||
130 | ACPI_FUNCTION_NAME("ds_load1_begin_op"); | 130 | ACPI_FUNCTION_TRACE("ds_load1_begin_op"); |
131 | 131 | ||
132 | op = walk_state->op; | 132 | op = walk_state->op; |
133 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | 133 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, |
@@ -138,14 +138,14 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
138 | if (op) { | 138 | if (op) { |
139 | if (!(walk_state->op_info->flags & AML_NAMED)) { | 139 | if (!(walk_state->op_info->flags & AML_NAMED)) { |
140 | *out_op = op; | 140 | *out_op = op; |
141 | return (AE_OK); | 141 | return_ACPI_STATUS(AE_OK); |
142 | } | 142 | } |
143 | 143 | ||
144 | /* Check if this object has already been installed in the namespace */ | 144 | /* Check if this object has already been installed in the namespace */ |
145 | 145 | ||
146 | if (op->common.node) { | 146 | if (op->common.node) { |
147 | *out_op = op; | 147 | *out_op = op; |
148 | return (AE_OK); | 148 | return_ACPI_STATUS(AE_OK); |
149 | } | 149 | } |
150 | } | 150 | } |
151 | 151 | ||
@@ -188,7 +188,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
188 | #endif | 188 | #endif |
189 | if (ACPI_FAILURE(status)) { | 189 | if (ACPI_FAILURE(status)) { |
190 | ACPI_REPORT_NSERROR(path, status); | 190 | ACPI_REPORT_NSERROR(path, status); |
191 | return (status); | 191 | return_ACPI_STATUS(status); |
192 | } | 192 | } |
193 | 193 | ||
194 | /* | 194 | /* |
@@ -235,7 +235,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
235 | 235 | ||
236 | ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path)); | 236 | ACPI_REPORT_ERROR(("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n", acpi_ut_get_type_name(node->type), path)); |
237 | 237 | ||
238 | return (AE_AML_OPERAND_TYPE); | 238 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
239 | } | 239 | } |
240 | break; | 240 | break; |
241 | 241 | ||
@@ -257,6 +257,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
257 | * buffer_field, or Package), the name of the object is already | 257 | * buffer_field, or Package), the name of the object is already |
258 | * in the namespace. | 258 | * in the namespace. |
259 | */ | 259 | */ |
260 | |||
260 | if (walk_state->deferred_node) { | 261 | if (walk_state->deferred_node) { |
261 | /* This name is already in the namespace, get the node */ | 262 | /* This name is already in the namespace, get the node */ |
262 | 263 | ||
@@ -265,6 +266,16 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
265 | break; | 266 | break; |
266 | } | 267 | } |
267 | 268 | ||
269 | /* | ||
270 | * If we are executing a method, do not create any namespace objects | ||
271 | * during the load phase, only during execution. | ||
272 | */ | ||
273 | if (walk_state->method_node) { | ||
274 | node = NULL; | ||
275 | status = AE_OK; | ||
276 | break; | ||
277 | } | ||
278 | |||
268 | flags = ACPI_NS_NO_UPSEARCH; | 279 | flags = ACPI_NS_NO_UPSEARCH; |
269 | if ((walk_state->opcode != AML_SCOPE_OP) && | 280 | if ((walk_state->opcode != AML_SCOPE_OP) && |
270 | (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { | 281 | (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { |
@@ -290,7 +301,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
290 | &(node)); | 301 | &(node)); |
291 | if (ACPI_FAILURE(status)) { | 302 | if (ACPI_FAILURE(status)) { |
292 | ACPI_REPORT_NSERROR(path, status); | 303 | ACPI_REPORT_NSERROR(path, status); |
293 | return (status); | 304 | return_ACPI_STATUS(status); |
294 | } | 305 | } |
295 | break; | 306 | break; |
296 | } | 307 | } |
@@ -302,28 +313,29 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
302 | 313 | ||
303 | op = acpi_ps_alloc_op(walk_state->opcode); | 314 | op = acpi_ps_alloc_op(walk_state->opcode); |
304 | if (!op) { | 315 | if (!op) { |
305 | return (AE_NO_MEMORY); | 316 | return_ACPI_STATUS(AE_NO_MEMORY); |
306 | } | 317 | } |
307 | } | 318 | } |
308 | 319 | ||
309 | /* Initialize */ | 320 | /* Initialize the op */ |
310 | |||
311 | op->named.name = node->name.integer; | ||
312 | 321 | ||
313 | #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) | 322 | #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) |
314 | op->named.path = ACPI_CAST_PTR(u8, path); | 323 | op->named.path = ACPI_CAST_PTR(u8, path); |
315 | #endif | 324 | #endif |
316 | 325 | ||
317 | /* | 326 | if (node) { |
318 | * Put the Node in the "op" object that the parser uses, so we | 327 | /* |
319 | * can get it again quickly when this scope is closed | 328 | * Put the Node in the "op" object that the parser uses, so we |
320 | */ | 329 | * can get it again quickly when this scope is closed |
321 | op->common.node = node; | 330 | */ |
331 | op->common.node = node; | ||
332 | op->named.name = node->name.integer; | ||
333 | } | ||
334 | |||
322 | acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), | 335 | acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), |
323 | op); | 336 | op); |
324 | |||
325 | *out_op = op; | 337 | *out_op = op; |
326 | return (status); | 338 | return_ACPI_STATUS(status); |
327 | } | 339 | } |
328 | 340 | ||
329 | /******************************************************************************* | 341 | /******************************************************************************* |
@@ -339,13 +351,13 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
339 | * | 351 | * |
340 | ******************************************************************************/ | 352 | ******************************************************************************/ |
341 | 353 | ||
342 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | 354 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) |
343 | { | 355 | { |
344 | union acpi_parse_object *op; | 356 | union acpi_parse_object *op; |
345 | acpi_object_type object_type; | 357 | acpi_object_type object_type; |
346 | acpi_status status = AE_OK; | 358 | acpi_status status = AE_OK; |
347 | 359 | ||
348 | ACPI_FUNCTION_NAME("ds_load1_end_op"); | 360 | ACPI_FUNCTION_TRACE("ds_load1_end_op"); |
349 | 361 | ||
350 | op = walk_state->op; | 362 | op = walk_state->op; |
351 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | 363 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, |
@@ -354,7 +366,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
354 | /* We are only interested in opcodes that have an associated name */ | 366 | /* We are only interested in opcodes that have an associated name */ |
355 | 367 | ||
356 | if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { | 368 | if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { |
357 | return (AE_OK); | 369 | return_ACPI_STATUS(AE_OK); |
358 | } | 370 | } |
359 | 371 | ||
360 | /* Get the object type to determine if we should pop the scope */ | 372 | /* Get the object type to determine if we should pop the scope */ |
@@ -363,21 +375,37 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
363 | 375 | ||
364 | #ifndef ACPI_NO_METHOD_EXECUTION | 376 | #ifndef ACPI_NO_METHOD_EXECUTION |
365 | if (walk_state->op_info->flags & AML_FIELD) { | 377 | if (walk_state->op_info->flags & AML_FIELD) { |
366 | if (walk_state->opcode == AML_FIELD_OP || | 378 | /* |
367 | walk_state->opcode == AML_BANK_FIELD_OP || | 379 | * If we are executing a method, do not create any namespace objects |
368 | walk_state->opcode == AML_INDEX_FIELD_OP) { | 380 | * during the load phase, only during execution. |
369 | status = acpi_ds_init_field_objects(op, walk_state); | 381 | */ |
382 | if (!walk_state->method_node) { | ||
383 | if (walk_state->opcode == AML_FIELD_OP || | ||
384 | walk_state->opcode == AML_BANK_FIELD_OP || | ||
385 | walk_state->opcode == AML_INDEX_FIELD_OP) { | ||
386 | status = | ||
387 | acpi_ds_init_field_objects(op, walk_state); | ||
388 | } | ||
370 | } | 389 | } |
371 | return (status); | 390 | return_ACPI_STATUS(status); |
372 | } | 391 | } |
373 | 392 | ||
374 | if (op->common.aml_opcode == AML_REGION_OP) { | 393 | /* |
375 | status = acpi_ex_create_region(op->named.data, op->named.length, | 394 | * If we are executing a method, do not create any namespace objects |
376 | (acpi_adr_space_type) | 395 | * during the load phase, only during execution. |
377 | ((op->common.value.arg)->common. | 396 | */ |
378 | value.integer), walk_state); | 397 | if (!walk_state->method_node) { |
379 | if (ACPI_FAILURE(status)) { | 398 | if (op->common.aml_opcode == AML_REGION_OP) { |
380 | return (status); | 399 | status = |
400 | acpi_ex_create_region(op->named.data, | ||
401 | op->named.length, | ||
402 | (acpi_adr_space_type) | ||
403 | ((op->common.value.arg)-> | ||
404 | common.value.integer), | ||
405 | walk_state); | ||
406 | if (ACPI_FAILURE(status)) { | ||
407 | return_ACPI_STATUS(status); | ||
408 | } | ||
381 | } | 409 | } |
382 | } | 410 | } |
383 | #endif | 411 | #endif |
@@ -391,7 +419,12 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
391 | common. | 419 | common. |
392 | aml_opcode))-> | 420 | aml_opcode))-> |
393 | object_type; | 421 | object_type; |
394 | op->common.node->type = (u8) object_type; | 422 | |
423 | /* Set node type if we have a namespace node */ | ||
424 | |||
425 | if (op->common.node) { | ||
426 | op->common.node->type = (u8) object_type; | ||
427 | } | ||
395 | } | 428 | } |
396 | } | 429 | } |
397 | 430 | ||
@@ -424,7 +457,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
424 | walk_state->num_operands = 0; | 457 | walk_state->num_operands = 0; |
425 | 458 | ||
426 | if (ACPI_FAILURE(status)) { | 459 | if (ACPI_FAILURE(status)) { |
427 | return (status); | 460 | return_ACPI_STATUS(status); |
428 | } | 461 | } |
429 | } | 462 | } |
430 | } | 463 | } |
@@ -439,7 +472,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
439 | status = acpi_ds_scope_stack_pop(walk_state); | 472 | status = acpi_ds_scope_stack_pop(walk_state); |
440 | } | 473 | } |
441 | 474 | ||
442 | return (status); | 475 | return_ACPI_STATUS(status); |
443 | } | 476 | } |
444 | 477 | ||
445 | /******************************************************************************* | 478 | /******************************************************************************* |
@@ -456,8 +489,8 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state * walk_state) | |||
456 | ******************************************************************************/ | 489 | ******************************************************************************/ |
457 | 490 | ||
458 | acpi_status | 491 | acpi_status |
459 | acpi_ds_load2_begin_op(struct acpi_walk_state * walk_state, | 492 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, |
460 | union acpi_parse_object ** out_op) | 493 | union acpi_parse_object **out_op) |
461 | { | 494 | { |
462 | union acpi_parse_object *op; | 495 | union acpi_parse_object *op; |
463 | struct acpi_namespace_node *node; | 496 | struct acpi_namespace_node *node; |
@@ -840,6 +873,13 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
840 | 873 | ||
841 | case AML_TYPE_NAMED_FIELD: | 874 | case AML_TYPE_NAMED_FIELD: |
842 | 875 | ||
876 | /* | ||
877 | * If we are executing a method, initialize the field | ||
878 | */ | ||
879 | if (walk_state->method_node) { | ||
880 | status = acpi_ds_init_field_objects(op, walk_state); | ||
881 | } | ||
882 | |||
843 | switch (op->common.aml_opcode) { | 883 | switch (op->common.aml_opcode) { |
844 | case AML_INDEX_FIELD_OP: | 884 | case AML_INDEX_FIELD_OP: |
845 | 885 | ||
@@ -929,6 +969,24 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
929 | switch (op->common.aml_opcode) { | 969 | switch (op->common.aml_opcode) { |
930 | #ifndef ACPI_NO_METHOD_EXECUTION | 970 | #ifndef ACPI_NO_METHOD_EXECUTION |
931 | case AML_REGION_OP: | 971 | case AML_REGION_OP: |
972 | |||
973 | /* | ||
974 | * If we are executing a method, initialize the region | ||
975 | */ | ||
976 | if (walk_state->method_node) { | ||
977 | status = | ||
978 | acpi_ex_create_region(op->named.data, | ||
979 | op->named.length, | ||
980 | (acpi_adr_space_type) | ||
981 | ((op->common.value. | ||
982 | arg)->common.value. | ||
983 | integer), | ||
984 | walk_state); | ||
985 | if (ACPI_FAILURE(status)) { | ||
986 | return (status); | ||
987 | } | ||
988 | } | ||
989 | |||
932 | /* | 990 | /* |
933 | * The op_region is not fully parsed at this time. Only valid | 991 | * The op_region is not fully parsed at this time. Only valid |
934 | * argument is the space_id. (We must save the address of the | 992 | * argument is the space_id. (We must save the address of the |
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 9faf1d5c86ed..864c642759fa 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c | |||
@@ -212,7 +212,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, | |||
212 | /* | 212 | /* |
213 | * Now we can print out the pertinent information | 213 | * Now we can print out the pertinent information |
214 | */ | 214 | */ |
215 | acpi_os_printf(" %-12s %p ", acpi_ut_get_type_name(type), this_node); | 215 | acpi_os_printf(" %-12s %p %2.2X ", |
216 | acpi_ut_get_type_name(type), this_node, | ||
217 | this_node->owner_id); | ||
216 | 218 | ||
217 | dbg_level = acpi_dbg_level; | 219 | dbg_level = acpi_dbg_level; |
218 | acpi_dbg_level = 0; | 220 | acpi_dbg_level = 0; |
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index d6813d88a104..6828c7aefa8a 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c | |||
@@ -793,6 +793,11 @@ void acpi_ut_init_globals(void) | |||
793 | acpi_gbl_mutex_info[i].use_count = 0; | 793 | acpi_gbl_mutex_info[i].use_count = 0; |
794 | } | 794 | } |
795 | 795 | ||
796 | for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { | ||
797 | acpi_gbl_owner_id_mask[i] = 0; | ||
798 | } | ||
799 | acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ | ||
800 | |||
796 | /* GPE support */ | 801 | /* GPE support */ |
797 | 802 | ||
798 | acpi_gbl_gpe_xrupt_list_head = NULL; | 803 | acpi_gbl_gpe_xrupt_list_head = NULL; |
@@ -830,8 +835,8 @@ void acpi_ut_init_globals(void) | |||
830 | acpi_gbl_ns_lookup_count = 0; | 835 | acpi_gbl_ns_lookup_count = 0; |
831 | acpi_gbl_ps_find_count = 0; | 836 | acpi_gbl_ps_find_count = 0; |
832 | acpi_gbl_acpi_hardware_present = TRUE; | 837 | acpi_gbl_acpi_hardware_present = TRUE; |
833 | acpi_gbl_owner_id_mask = 0; | 838 | acpi_gbl_last_owner_id_index = 0; |
834 | acpi_gbl_last_owner_id = 0; | 839 | acpi_gbl_next_owner_id_offset = 0; |
835 | acpi_gbl_trace_method_name = 0; | 840 | acpi_gbl_trace_method_name = 0; |
836 | acpi_gbl_trace_dbg_level = 0; | 841 | acpi_gbl_trace_dbg_level = 0; |
837 | acpi_gbl_trace_dbg_layer = 0; | 842 | acpi_gbl_trace_dbg_layer = 0; |
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 89efba7bf449..64dd64b1aa18 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
@@ -64,6 +64,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
64 | { | 64 | { |
65 | acpi_native_uint i; | 65 | acpi_native_uint i; |
66 | acpi_native_uint j; | 66 | acpi_native_uint j; |
67 | acpi_native_uint k; | ||
67 | acpi_status status; | 68 | acpi_status status; |
68 | 69 | ||
69 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); | 70 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); |
@@ -85,32 +86,50 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
85 | 86 | ||
86 | /* | 87 | /* |
87 | * Find a free owner ID, cycle through all possible IDs on repeated | 88 | * Find a free owner ID, cycle through all possible IDs on repeated |
88 | * allocations. Note: Index for next possible ID is equal to the value | 89 | * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have |
89 | * of the last allocated ID. | 90 | * to be scanned twice. |
90 | */ | 91 | */ |
91 | for (i = 0, j = acpi_gbl_last_owner_id; i < 32; i++, j++) { | 92 | for (i = 0, j = acpi_gbl_last_owner_id_index; |
92 | if (j >= 32) { | 93 | i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { |
93 | j = 0; /* Wraparound to ID start */ | 94 | if (j >= ACPI_NUM_OWNERID_MASKS) { |
95 | j = 0; /* Wraparound to start of mask array */ | ||
94 | } | 96 | } |
95 | 97 | ||
96 | if (!(acpi_gbl_owner_id_mask & (1 << j))) { | 98 | for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { |
97 | /* | 99 | if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { |
98 | * Found a free ID. The actual ID is the bit index plus one, | 100 | /* There are no free IDs in this mask */ |
99 | * making zero an invalid Owner ID. Save this as the last ID | ||
100 | * allocated and update the global ID mask. | ||
101 | */ | ||
102 | acpi_gbl_last_owner_id = (acpi_owner_id) (j + 1); | ||
103 | *owner_id = acpi_gbl_last_owner_id; | ||
104 | 101 | ||
105 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, | 102 | break; |
106 | "Current owner_id mask: %8.8X New ID: %2.2X\n", | 103 | } |
107 | acpi_gbl_owner_id_mask, | ||
108 | (unsigned int) | ||
109 | acpi_gbl_last_owner_id)); | ||
110 | 104 | ||
111 | acpi_gbl_owner_id_mask |= (1 << j); | 105 | if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { |
112 | goto exit; | 106 | /* |
107 | * Found a free ID. The actual ID is the bit index plus one, | ||
108 | * making zero an invalid Owner ID. Save this as the last ID | ||
109 | * allocated and update the global ID mask. | ||
110 | */ | ||
111 | acpi_gbl_owner_id_mask[j] |= (1 << k); | ||
112 | |||
113 | acpi_gbl_last_owner_id_index = (u8) j; | ||
114 | acpi_gbl_next_owner_id_offset = (u8) (k + 1); | ||
115 | |||
116 | /* | ||
117 | * Construct encoded ID from the index and bit position | ||
118 | * | ||
119 | * Note: Last [j].k (bit 255) is never used and is marked | ||
120 | * permanently allocated (prevents +1 overflow) | ||
121 | */ | ||
122 | *owner_id = | ||
123 | (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); | ||
124 | |||
125 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, | ||
126 | "Allocated owner_id: %2.2X\n", | ||
127 | (unsigned int)*owner_id)); | ||
128 | goto exit; | ||
129 | } | ||
113 | } | 130 | } |
131 | |||
132 | acpi_gbl_next_owner_id_offset = 0; | ||
114 | } | 133 | } |
115 | 134 | ||
116 | /* | 135 | /* |
@@ -124,7 +143,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
124 | * methods, or there may be a bug where the IDs are not released. | 143 | * methods, or there may be a bug where the IDs are not released. |
125 | */ | 144 | */ |
126 | status = AE_OWNER_ID_LIMIT; | 145 | status = AE_OWNER_ID_LIMIT; |
127 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); | 146 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT\n")); |
128 | 147 | ||
129 | exit: | 148 | exit: |
130 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); | 149 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); |
@@ -141,7 +160,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) | |||
141 | * control method or unloading a table. Either way, we would | 160 | * control method or unloading a table. Either way, we would |
142 | * ignore any error anyway. | 161 | * ignore any error anyway. |
143 | * | 162 | * |
144 | * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32 | 163 | * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 |
145 | * | 164 | * |
146 | ******************************************************************************/ | 165 | ******************************************************************************/ |
147 | 166 | ||
@@ -149,6 +168,8 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
149 | { | 168 | { |
150 | acpi_owner_id owner_id = *owner_id_ptr; | 169 | acpi_owner_id owner_id = *owner_id_ptr; |
151 | acpi_status status; | 170 | acpi_status status; |
171 | acpi_native_uint index; | ||
172 | u32 bit; | ||
152 | 173 | ||
153 | ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); | 174 | ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); |
154 | 175 | ||
@@ -158,7 +179,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
158 | 179 | ||
159 | /* Zero is not a valid owner_iD */ | 180 | /* Zero is not a valid owner_iD */ |
160 | 181 | ||
161 | if ((owner_id == 0) || (owner_id > 32)) { | 182 | if ((owner_id == 0) || (owner_id > 255)) { |
162 | ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); | 183 | ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); |
163 | return_VOID; | 184 | return_VOID; |
164 | } | 185 | } |
@@ -174,10 +195,18 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) | |||
174 | 195 | ||
175 | owner_id--; | 196 | owner_id--; |
176 | 197 | ||
198 | /* Decode ID to index/offset pair */ | ||
199 | |||
200 | index = ACPI_DIV_32(owner_id); | ||
201 | bit = 1 << ACPI_MOD_32(owner_id); | ||
202 | |||
177 | /* Free the owner ID only if it is valid */ | 203 | /* Free the owner ID only if it is valid */ |
178 | 204 | ||
179 | if (acpi_gbl_owner_id_mask & (1 << owner_id)) { | 205 | if (acpi_gbl_owner_id_mask[index] & bit) { |
180 | acpi_gbl_owner_id_mask ^= (1 << owner_id); | 206 | acpi_gbl_owner_id_mask[index] ^= bit; |
207 | } else { | ||
208 | ACPI_REPORT_ERROR(("Release of non-allocated owner_id: %2.2X\n", | ||
209 | owner_id + 1)); | ||
181 | } | 210 | } |
182 | 211 | ||
183 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); | 212 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); |