aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Moore <robert.moore@intel.com>2005-05-26 00:00:00 -0400
committerLen Brown <len.brown@intel.com>2005-07-13 16:46:34 -0400
commit88ac00f5a841dcfc5c682000f4a6add0add8caac (patch)
tree80dcff8323c6c79e8706f42eb4b7c3884bc03152
parent6f42ccf2fc50ecee8ea170040627f268430c1648 (diff)
ACPICA 20050526 from Bob Moore <robert.moore@intel.com>
Implemented support to execute Type 1 and Type 2 AML opcodes appearing at the module level (not within a control method.) These opcodes are executed exactly once at the time the table is loaded. This type of code was legal up until the release of ACPI 2.0B (2002) and is now supported within ACPI CA in order to provide backwards compatibility with earlier BIOS implementations. This eliminates the "Encountered executable code at module level" warning that was previously generated upon detection of such code. Fixed a problem in the interpreter where an AE_NOT_FOUND exception could inadvertently be generated during the lookup of namespace objects in the second pass parse of ACPI tables and control methods. It appears that this problem could occur during the resolution of forward references to namespace objects. Added the ACPI_MUTEX_DEBUG #ifdef to the acpi_ut_release_mutex function, corresponding to the same the deadlock detection debug code to be compiled out in the normal case, improving mutex performance (and overall subsystem performance) considerably. As suggested by Alexey Starikovskiy. Implemented a handful of miscellaneous fixes for possible memory leaks on error conditions and error handling control paths. These fixes were suggested by FreeBSD and the Coverity Prevent source code analysis tool. Added a check for a null RSDT pointer in acpi_get_firmware_table (tbxfroot.c) to prevent a fault in this error case. Signed-off-by Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c8
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c15
-rw-r--r--drivers/acpi/dispatcher/dswload.c56
-rw-r--r--drivers/acpi/dispatcher/dswstate.c1
-rw-r--r--drivers/acpi/executer/exconfig.c27
-rw-r--r--drivers/acpi/executer/exfield.c5
-rw-r--r--drivers/acpi/executer/exnames.c7
-rw-r--r--drivers/acpi/executer/exoparg1.c11
-rw-r--r--drivers/acpi/namespace/nsparse.c2
-rw-r--r--drivers/acpi/parser/psparse.c109
-rw-r--r--drivers/acpi/tables/tbxfroot.c6
-rw-r--r--drivers/acpi/utilities/utmisc.c38
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acstruct.h2
14 files changed, 198 insertions, 91 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 9fc3f4c033eb..c9d9a6c45ae3 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -139,7 +139,8 @@ acpi_ds_parse_method (
139 139
140 walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL); 140 walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
141 if (!walk_state) { 141 if (!walk_state) {
142 return_ACPI_STATUS (AE_NO_MEMORY); 142 status = AE_NO_MEMORY;
143 goto cleanup;
143 } 144 }
144 145
145 status = acpi_ds_init_aml_walk (walk_state, op, node, 146 status = acpi_ds_init_aml_walk (walk_state, op, node,
@@ -147,7 +148,7 @@ acpi_ds_parse_method (
147 obj_desc->method.aml_length, NULL, 1); 148 obj_desc->method.aml_length, NULL, 1);
148 if (ACPI_FAILURE (status)) { 149 if (ACPI_FAILURE (status)) {
149 acpi_ds_delete_walk_state (walk_state); 150 acpi_ds_delete_walk_state (walk_state);
150 return_ACPI_STATUS (status); 151 goto cleanup;
151 } 152 }
152 153
153 /* 154 /*
@@ -161,13 +162,14 @@ acpi_ds_parse_method (
161 */ 162 */
162 status = acpi_ps_parse_aml (walk_state); 163 status = acpi_ps_parse_aml (walk_state);
163 if (ACPI_FAILURE (status)) { 164 if (ACPI_FAILURE (status)) {
164 return_ACPI_STATUS (status); 165 goto cleanup;
165 } 166 }
166 167
167 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 168 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
168 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", 169 "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
169 acpi_ut_get_node_name (obj_handle), obj_handle, op)); 170 acpi_ut_get_node_name (obj_handle), obj_handle, op));
170 171
172cleanup:
171 acpi_ps_delete_parse_tree (op); 173 acpi_ps_delete_parse_tree (op);
172 return_ACPI_STATUS (status); 174 return_ACPI_STATUS (status);
173} 175}
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index ba13bca28bee..750bdb1ac344 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -119,14 +119,15 @@ acpi_ds_execute_arguments (
119 119
120 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); 120 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
121 if (!walk_state) { 121 if (!walk_state) {
122 return_ACPI_STATUS (AE_NO_MEMORY); 122 status = AE_NO_MEMORY;
123 goto cleanup;
123 } 124 }
124 125
125 status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, 126 status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
126 aml_length, NULL, 1); 127 aml_length, NULL, 1);
127 if (ACPI_FAILURE (status)) { 128 if (ACPI_FAILURE (status)) {
128 acpi_ds_delete_walk_state (walk_state); 129 acpi_ds_delete_walk_state (walk_state);
129 return_ACPI_STATUS (status); 130 goto cleanup;
130 } 131 }
131 132
132 /* Mark this parse as a deferred opcode */ 133 /* Mark this parse as a deferred opcode */
@@ -138,8 +139,7 @@ acpi_ds_execute_arguments (
138 139
139 status = acpi_ps_parse_aml (walk_state); 140 status = acpi_ps_parse_aml (walk_state);
140 if (ACPI_FAILURE (status)) { 141 if (ACPI_FAILURE (status)) {
141 acpi_ps_delete_parse_tree (op); 142 goto cleanup;
142 return_ACPI_STATUS (status);
143 } 143 }
144 144
145 /* Get and init the Op created above */ 145 /* Get and init the Op created above */
@@ -160,7 +160,8 @@ acpi_ds_execute_arguments (
160 160
161 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); 161 walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
162 if (!walk_state) { 162 if (!walk_state) {
163 return_ACPI_STATUS (AE_NO_MEMORY); 163 status = AE_NO_MEMORY;
164 goto cleanup;
164 } 165 }
165 166
166 /* Execute the opcode and arguments */ 167 /* Execute the opcode and arguments */
@@ -169,13 +170,15 @@ acpi_ds_execute_arguments (
169 aml_length, NULL, 3); 170 aml_length, NULL, 3);
170 if (ACPI_FAILURE (status)) { 171 if (ACPI_FAILURE (status)) {
171 acpi_ds_delete_walk_state (walk_state); 172 acpi_ds_delete_walk_state (walk_state);
172 return_ACPI_STATUS (status); 173 goto cleanup;
173 } 174 }
174 175
175 /* Mark this execution as a deferred opcode */ 176 /* Mark this execution as a deferred opcode */
176 177
177 walk_state->deferred_node = node; 178 walk_state->deferred_node = node;
178 status = acpi_ps_parse_aml (walk_state); 179 status = acpi_ps_parse_aml (walk_state);
180
181cleanup:
179 acpi_ps_delete_parse_tree (op); 182 acpi_ps_delete_parse_tree (op);
180 return_ACPI_STATUS (status); 183 return_ACPI_STATUS (status);
181} 184}
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 1ac197ccfc80..e2e0a855be2c 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -145,15 +145,6 @@ acpi_ds_load1_begin_op (
145 145
146 if (op) { 146 if (op) {
147 if (!(walk_state->op_info->flags & AML_NAMED)) { 147 if (!(walk_state->op_info->flags & AML_NAMED)) {
148#if 0
149 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
150 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
151 acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n",
152 walk_state->op_info->name);
153 *out_op = op;
154 return (AE_CTRL_SKIP);
155 }
156#endif
157 *out_op = op; 148 *out_op = op;
158 return (AE_OK); 149 return (AE_OK);
159 } 150 }
@@ -486,6 +477,15 @@ acpi_ds_load2_begin_op (
486 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); 477 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
487 478
488 if (op) { 479 if (op) {
480 if ((walk_state->control_state) &&
481 (walk_state->control_state->common.state ==
482 ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
483 /* We are executing a while loop outside of a method */
484
485 status = acpi_ds_exec_begin_op (walk_state, out_op);
486 return_ACPI_STATUS (status);
487 }
488
489 /* We only care about Namespace opcodes here */ 489 /* We only care about Namespace opcodes here */
490 490
491 if ((!(walk_state->op_info->flags & AML_NSOPCODE) && 491 if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
@@ -493,9 +493,14 @@ acpi_ds_load2_begin_op (
493 (!(walk_state->op_info->flags & AML_NAMED))) { 493 (!(walk_state->op_info->flags & AML_NAMED))) {
494 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || 494 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
495 (walk_state->op_info->class == AML_CLASS_CONTROL)) { 495 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
496 ACPI_REPORT_WARNING (( 496 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
497 "Encountered executable code at module level, [%s]\n", 497 "Begin/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name,
498 acpi_ps_get_opcode_name (walk_state->opcode))); 498 walk_state->op_info->flags));
499
500 /* Executing a type1 or type2 opcode outside of a method */
501
502 status = acpi_ds_exec_begin_op (walk_state, out_op);
503 return_ACPI_STATUS (status);
499 } 504 }
500 return_ACPI_STATUS (AE_OK); 505 return_ACPI_STATUS (AE_OK);
501 } 506 }
@@ -657,8 +662,10 @@ acpi_ds_load2_begin_op (
657 break; 662 break;
658 } 663 }
659 664
665 /* Add new entry into namespace */
666
660 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type, 667 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
661 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, 668 ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
662 walk_state, &(node)); 669 walk_state, &(node));
663 break; 670 break;
664 } 671 }
@@ -668,7 +675,6 @@ acpi_ds_load2_begin_op (
668 return_ACPI_STATUS (status); 675 return_ACPI_STATUS (status);
669 } 676 }
670 677
671
672 if (!op) { 678 if (!op) {
673 /* Create a new op */ 679 /* Create a new op */
674 680
@@ -682,9 +688,7 @@ acpi_ds_load2_begin_op (
682 if (node) { 688 if (node) {
683 op->named.name = node->name.integer; 689 op->named.name = node->name.integer;
684 } 690 }
685 if (out_op) { 691 *out_op = op;
686 *out_op = op;
687 }
688 } 692 }
689 693
690 /* 694 /*
@@ -731,9 +735,24 @@ acpi_ds_load2_end_op (
731 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", 735 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
732 walk_state->op_info->name, op, walk_state)); 736 walk_state->op_info->name, op, walk_state));
733 737
734 /* Only interested in opcodes that have namespace objects */ 738 /* Check if opcode had an associated namespace object */
735 739
736 if (!(walk_state->op_info->flags & AML_NSOBJECT)) { 740 if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
741#ifndef ACPI_NO_METHOD_EXECUTION
742 /* No namespace object. Executable opcode? */
743
744 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
745 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
746 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
747 "End/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name,
748 walk_state->op_info->flags));
749
750 /* Executing a type1 or type2 opcode outside of a method */
751
752 status = acpi_ds_exec_end_op (walk_state);
753 return_ACPI_STATUS (status);
754 }
755#endif
737 return_ACPI_STATUS (AE_OK); 756 return_ACPI_STATUS (AE_OK);
738 } 757 }
739 758
@@ -742,7 +761,6 @@ acpi_ds_load2_end_op (
742 "Ending scope Op=%p State=%p\n", op, walk_state)); 761 "Ending scope Op=%p State=%p\n", op, walk_state));
743 } 762 }
744 763
745
746 object_type = walk_state->op_info->object_type; 764 object_type = walk_state->op_info->object_type;
747 765
748 /* 766 /*
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 4ef0e85c677b..cc45d52225d6 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -762,6 +762,7 @@ acpi_ds_init_aml_walk (
762 /* The next_op of the next_walk will be the beginning of the method */ 762 /* The next_op of the next_walk will be the beginning of the method */
763 763
764 walk_state->next_op = NULL; 764 walk_state->next_op = NULL;
765 walk_state->pass_number = (u8) pass_number;
765 766
766 if (info) { 767 if (info) {
767 if (info->parameter_type == ACPI_PARAM_GPE) { 768 if (info->parameter_type == ACPI_PARAM_GPE) {
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index 734b2f24af48..8bfa6effaa0c 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -376,16 +376,22 @@ acpi_ex_load_op (
376 */ 376 */
377 status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc); 377 status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
378 if (ACPI_FAILURE (status)) { 378 if (ACPI_FAILURE (status)) {
379 goto cleanup; 379 return_ACPI_STATUS (status);
380 } 380 }
381 381
382 table_ptr = ACPI_CAST_PTR (struct acpi_table_header, 382 table_ptr = ACPI_CAST_PTR (struct acpi_table_header,
383 buffer_desc->buffer.pointer); 383 buffer_desc->buffer.pointer);
384 384
385 /* Sanity check the table length */ 385 /* All done with the buffer_desc, delete it */
386
387 buffer_desc->buffer.pointer = NULL;
388 acpi_ut_remove_reference (buffer_desc);
389
390 /* Sanity check the table length */
386 391
387 if (table_ptr->length < sizeof (struct acpi_table_header)) { 392 if (table_ptr->length < sizeof (struct acpi_table_header)) {
388 return_ACPI_STATUS (AE_BAD_HEADER); 393 status = AE_BAD_HEADER;
394 goto cleanup;
389 } 395 }
390 break; 396 break;
391 397
@@ -413,7 +419,9 @@ acpi_ex_load_op (
413 419
414 status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle); 420 status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
415 if (ACPI_FAILURE (status)) { 421 if (ACPI_FAILURE (status)) {
416 goto cleanup; 422 /* On error, table_ptr was deallocated above */
423
424 return_ACPI_STATUS (status);
417 } 425 }
418 426
419 /* Store the ddb_handle into the Target operand */ 427 /* Store the ddb_handle into the Target operand */
@@ -421,17 +429,14 @@ acpi_ex_load_op (
421 status = acpi_ex_store (ddb_handle, target, walk_state); 429 status = acpi_ex_store (ddb_handle, target, walk_state);
422 if (ACPI_FAILURE (status)) { 430 if (ACPI_FAILURE (status)) {
423 (void) acpi_ex_unload_table (ddb_handle); 431 (void) acpi_ex_unload_table (ddb_handle);
424 }
425 432
426 return_ACPI_STATUS (status); 433 /* table_ptr was deallocated above */
427 434
435 return_ACPI_STATUS (status);
436 }
428 437
429cleanup: 438cleanup:
430 439 if (ACPI_FAILURE (status)) {
431 if (buffer_desc) {
432 acpi_ut_remove_reference (buffer_desc);
433 }
434 else {
435 ACPI_MEM_FREE (table_ptr); 440 ACPI_MEM_FREE (table_ptr);
436 } 441 }
437 return_ACPI_STATUS (status); 442 return_ACPI_STATUS (status);
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index 22c8fa480f60..a690c9250990 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -87,6 +87,9 @@ acpi_ex_read_data_from_field (
87 if (!obj_desc) { 87 if (!obj_desc) {
88 return_ACPI_STATUS (AE_AML_NO_OPERAND); 88 return_ACPI_STATUS (AE_AML_NO_OPERAND);
89 } 89 }
90 if (!ret_buffer_desc) {
91 return_ACPI_STATUS (AE_BAD_PARAMETER);
92 }
90 93
91 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) { 94 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
92 /* 95 /*
@@ -182,7 +185,7 @@ exit:
182 if (ACPI_FAILURE (status)) { 185 if (ACPI_FAILURE (status)) {
183 acpi_ut_remove_reference (buffer_desc); 186 acpi_ut_remove_reference (buffer_desc);
184 } 187 }
185 else if (ret_buffer_desc) { 188 else {
186 *ret_buffer_desc = buffer_desc; 189 *ret_buffer_desc = buffer_desc;
187 } 190 }
188 191
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 639f0bd3f6d8..b6ba1a7a677a 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -438,6 +438,13 @@ acpi_ex_get_name_string (
438 status = AE_AML_BAD_NAME; 438 status = AE_AML_BAD_NAME;
439 } 439 }
440 440
441 if (ACPI_FAILURE (status)) {
442 if (name_string) {
443 ACPI_MEM_FREE (name_string);
444 }
445 return_ACPI_STATUS (status);
446 }
447
441 *out_name_string = name_string; 448 *out_name_string = name_string;
442 *out_name_length = (u32) (aml_address - in_aml_address); 449 *out_name_length = (u32) (aml_address - in_aml_address);
443 450
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index dbdf8262ba00..ffc61ddeb659 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -127,15 +127,16 @@ acpi_ex_opcode_0A_0T_1R (
127 127
128cleanup: 128cleanup:
129 129
130 if (!walk_state->result_obj) {
131 walk_state->result_obj = return_desc;
132 }
133
134 /* Delete return object on error */ 130 /* Delete return object on error */
135 131
136 if (ACPI_FAILURE (status)) { 132 if ((ACPI_FAILURE (status)) || walk_state->result_obj) {
137 acpi_ut_remove_reference (return_desc); 133 acpi_ut_remove_reference (return_desc);
138 } 134 }
135 else {
136 /* Save the return value */
137
138 walk_state->result_obj = return_desc;
139 }
139 140
140 return_ACPI_STATUS (status); 141 return_ACPI_STATUS (status);
141} 142}
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index a0e13e8d3764..f81b836e77f1 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -146,6 +146,7 @@ acpi_ns_parse_table (
146 * to service the entire parse. The second pass of the parse then 146 * to service the entire parse. The second pass of the parse then
147 * performs another complete parse of the AML.. 147 * performs another complete parse of the AML..
148 */ 148 */
149 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n"));
149 status = acpi_ns_one_complete_parse (1, table_desc); 150 status = acpi_ns_one_complete_parse (1, table_desc);
150 if (ACPI_FAILURE (status)) { 151 if (ACPI_FAILURE (status)) {
151 return_ACPI_STATUS (status); 152 return_ACPI_STATUS (status);
@@ -160,6 +161,7 @@ acpi_ns_parse_table (
160 * overhead of this is compensated for by the fact that the 161 * overhead of this is compensated for by the fact that the
161 * parse objects are all cached. 162 * parse objects are all cached.
162 */ 163 */
164 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n"));
163 status = acpi_ns_one_complete_parse (2, table_desc); 165 status = acpi_ns_one_complete_parse (2, table_desc);
164 if (ACPI_FAILURE (status)) { 166 if (ACPI_FAILURE (status)) {
165 return_ACPI_STATUS (status); 167 return_ACPI_STATUS (status);
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index bbfdc1a58c27..bdbe0d99486f 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -66,7 +66,7 @@ static u32 acpi_gbl_depth = 0;
66 66
67/* Local prototypes */ 67/* Local prototypes */
68 68
69static void 69static acpi_status
70acpi_ps_complete_this_op ( 70acpi_ps_complete_this_op (
71 struct acpi_walk_state *walk_state, 71 struct acpi_walk_state *walk_state,
72 union acpi_parse_object *op); 72 union acpi_parse_object *op);
@@ -152,13 +152,13 @@ acpi_ps_peek_opcode (
152 * PARAMETERS: walk_state - Current State 152 * PARAMETERS: walk_state - Current State
153 * Op - Op to complete 153 * Op - Op to complete
154 * 154 *
155 * RETURN: None. 155 * RETURN: Status
156 * 156 *
157 * DESCRIPTION: Perform any cleanup at the completion of an Op. 157 * DESCRIPTION: Perform any cleanup at the completion of an Op.
158 * 158 *
159 ******************************************************************************/ 159 ******************************************************************************/
160 160
161static void 161static acpi_status
162acpi_ps_complete_this_op ( 162acpi_ps_complete_this_op (
163 struct acpi_walk_state *walk_state, 163 struct acpi_walk_state *walk_state,
164 union acpi_parse_object *op) 164 union acpi_parse_object *op)
@@ -175,19 +175,26 @@ acpi_ps_complete_this_op (
175 /* Check for null Op, can happen if AML code is corrupt */ 175 /* Check for null Op, can happen if AML code is corrupt */
176 176
177 if (!op) { 177 if (!op) {
178 return_VOID; 178 return_ACPI_STATUS (AE_OK); /* OK for now */
179 } 179 }
180 180
181 /* Delete this op and the subtree below it if asked to */ 181 /* Delete this op and the subtree below it if asked to */
182 182
183 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || 183 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
184 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { 184 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
185 return_VOID; 185 return_ACPI_STATUS (AE_OK);
186 } 186 }
187 187
188 /* Make sure that we only delete this subtree */ 188 /* Make sure that we only delete this subtree */
189 189
190 if (op->common.parent) { 190 if (op->common.parent) {
191 prev = op->common.parent->common.value.arg;
192 if (!prev) {
193 /* Nothing more to do */
194
195 goto cleanup;
196 }
197
191 /* 198 /*
192 * Check if we need to replace the operator and its subtree 199 * Check if we need to replace the operator and its subtree
193 * with a return value op (placeholder op) 200 * with a return value op (placeholder op)
@@ -206,7 +213,7 @@ acpi_ps_complete_this_op (
206 */ 213 */
207 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 214 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
208 if (!replacement_op) { 215 if (!replacement_op) {
209 goto cleanup; 216 goto allocate_error;
210 } 217 }
211 break; 218 break;
212 219
@@ -223,18 +230,17 @@ acpi_ps_complete_this_op (
223 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 230 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
224 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 231 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
225 if (!replacement_op) { 232 if (!replacement_op) {
226 goto cleanup; 233 goto allocate_error;
227 } 234 }
228 } 235 }
229 236 else if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
230 if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && 237 (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
231 (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
232 if ((op->common.aml_opcode == AML_BUFFER_OP) || 238 if ((op->common.aml_opcode == AML_BUFFER_OP) ||
233 (op->common.aml_opcode == AML_PACKAGE_OP) || 239 (op->common.aml_opcode == AML_PACKAGE_OP) ||
234 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 240 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
235 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); 241 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
236 if (!replacement_op) { 242 if (!replacement_op) {
237 goto cleanup; 243 goto allocate_error;
238 } 244 }
239 245
240 replacement_op->named.data = op->named.data; 246 replacement_op->named.data = op->named.data;
@@ -244,15 +250,15 @@ acpi_ps_complete_this_op (
244 break; 250 break;
245 251
246 default: 252 default:
253
247 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 254 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
248 if (!replacement_op) { 255 if (!replacement_op) {
249 goto cleanup; 256 goto allocate_error;
250 } 257 }
251 } 258 }
252 259
253 /* We must unlink this op from the parent tree */ 260 /* We must unlink this op from the parent tree */
254 261
255 prev = op->common.parent->common.value.arg;
256 if (prev == op) { 262 if (prev == op) {
257 /* This op is the first in the list */ 263 /* This op is the first in the list */
258 264
@@ -298,7 +304,15 @@ cleanup:
298 /* Now we can actually delete the subtree rooted at Op */ 304 /* Now we can actually delete the subtree rooted at Op */
299 305
300 acpi_ps_delete_parse_tree (op); 306 acpi_ps_delete_parse_tree (op);
301 return_VOID; 307 return_ACPI_STATUS (AE_OK);
308
309
310allocate_error:
311
312 /* Always delete the subtree, even on error */
313
314 acpi_ps_delete_parse_tree (op);
315 return_ACPI_STATUS (AE_NO_MEMORY);
302} 316}
303 317
304 318
@@ -443,6 +457,7 @@ acpi_ps_parse_loop (
443 struct acpi_walk_state *walk_state) 457 struct acpi_walk_state *walk_state)
444{ 458{
445 acpi_status status = AE_OK; 459 acpi_status status = AE_OK;
460 acpi_status status2;
446 union acpi_parse_object *op = NULL; /* current op */ 461 union acpi_parse_object *op = NULL; /* current op */
447 union acpi_parse_object *arg = NULL; 462 union acpi_parse_object *arg = NULL;
448 union acpi_parse_object *pre_op = NULL; 463 union acpi_parse_object *pre_op = NULL;
@@ -744,7 +759,6 @@ acpi_ps_parse_loop (
744 break; 759 break;
745 760
746 default: 761 default:
747
748 /* 762 /*
749 * Op is not a constant or string, append each argument 763 * Op is not a constant or string, append each argument
750 * to the Op 764 * to the Op
@@ -770,6 +784,23 @@ acpi_ps_parse_loop (
770 784
771 /* Special processing for certain opcodes */ 785 /* Special processing for certain opcodes */
772 786
787 if (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) {
788 switch (op->common.aml_opcode) {
789 case AML_IF_OP:
790 case AML_ELSE_OP:
791 case AML_WHILE_OP:
792
793 /* Skip body of if/else/while in pass 1 */
794
795 parser_state->aml = parser_state->pkg_end;
796 walk_state->arg_count = 0;
797 break;
798
799 default:
800 break;
801 }
802 }
803
773 switch (op->common.aml_opcode) { 804 switch (op->common.aml_opcode) {
774 case AML_METHOD_OP: 805 case AML_METHOD_OP:
775 806
@@ -796,7 +827,7 @@ acpi_ps_parse_loop (
796 827
797 if ((op->common.parent) && 828 if ((op->common.parent) &&
798 (op->common.parent->common.aml_opcode == AML_NAME_OP) && 829 (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
799 (walk_state->descending_callback != acpi_ds_exec_begin_op)) { 830 (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
800 /* 831 /*
801 * Skip parsing of Buffers and Packages 832 * Skip parsing of Buffers and Packages
802 * because we don't have enough info in the first pass 833 * because we don't have enough info in the first pass
@@ -900,15 +931,21 @@ close_this_op:
900 */ 931 */
901 parser_state->scope->parse_scope.arg_count--; 932 parser_state->scope->parse_scope.arg_count--;
902 933
903 /* Close this Op (will result in parse subtree deletion) */ 934 /* Finished with pre_op */
904 935
905 acpi_ps_complete_this_op (walk_state, op);
906 op = NULL;
907 if (pre_op) { 936 if (pre_op) {
908 acpi_ps_free_op (pre_op); 937 acpi_ps_free_op (pre_op);
909 pre_op = NULL; 938 pre_op = NULL;
910 } 939 }
911 940
941 /* Close this Op (will result in parse subtree deletion) */
942
943 status2 = acpi_ps_complete_this_op (walk_state, op);
944 if (ACPI_FAILURE (status2)) {
945 return_ACPI_STATUS (status2);
946 }
947 op = NULL;
948
912 switch (status) { 949 switch (status) {
913 case AE_OK: 950 case AE_OK:
914 break; 951 break;
@@ -936,7 +973,10 @@ close_this_op:
936 status = walk_state->ascending_callback (walk_state); 973 status = walk_state->ascending_callback (walk_state);
937 status = acpi_ps_next_parse_state (walk_state, op, status); 974 status = acpi_ps_next_parse_state (walk_state, op, status);
938 975
939 acpi_ps_complete_this_op (walk_state, op); 976 status2 = acpi_ps_complete_this_op (walk_state, op);
977 if (ACPI_FAILURE (status2)) {
978 return_ACPI_STATUS (status2);
979 }
940 op = NULL; 980 op = NULL;
941 } 981 }
942 status = AE_OK; 982 status = AE_OK;
@@ -962,7 +1002,10 @@ close_this_op:
962 status = walk_state->ascending_callback (walk_state); 1002 status = walk_state->ascending_callback (walk_state);
963 status = acpi_ps_next_parse_state (walk_state, op, status); 1003 status = acpi_ps_next_parse_state (walk_state, op, status);
964 1004
965 acpi_ps_complete_this_op (walk_state, op); 1005 status2 = acpi_ps_complete_this_op (walk_state, op);
1006 if (ACPI_FAILURE (status2)) {
1007 return_ACPI_STATUS (status2);
1008 }
966 op = NULL; 1009 op = NULL;
967 1010
968 status = AE_OK; 1011 status = AE_OK;
@@ -976,7 +1019,10 @@ close_this_op:
976 /* Clean up */ 1019 /* Clean up */
977 do { 1020 do {
978 if (op) { 1021 if (op) {
979 acpi_ps_complete_this_op (walk_state, op); 1022 status2 = acpi_ps_complete_this_op (walk_state, op);
1023 if (ACPI_FAILURE (status2)) {
1024 return_ACPI_STATUS (status2);
1025 }
980 } 1026 }
981 acpi_ps_pop_scope (parser_state, &op, 1027 acpi_ps_pop_scope (parser_state, &op,
982 &walk_state->arg_types, &walk_state->arg_count); 1028 &walk_state->arg_types, &walk_state->arg_count);
@@ -990,7 +1036,10 @@ close_this_op:
990 1036
991 do { 1037 do {
992 if (op) { 1038 if (op) {
993 acpi_ps_complete_this_op (walk_state, op); 1039 status2 = acpi_ps_complete_this_op (walk_state, op);
1040 if (ACPI_FAILURE (status2)) {
1041 return_ACPI_STATUS (status2);
1042 }
994 } 1043 }
995 acpi_ps_pop_scope (parser_state, &op, 1044 acpi_ps_pop_scope (parser_state, &op,
996 &walk_state->arg_types, &walk_state->arg_count); 1045 &walk_state->arg_types, &walk_state->arg_count);
@@ -1053,7 +1102,10 @@ close_this_op:
1053 /* Clean up */ 1102 /* Clean up */
1054 do { 1103 do {
1055 if (op) { 1104 if (op) {
1056 acpi_ps_complete_this_op (walk_state, op); 1105 status2 = acpi_ps_complete_this_op (walk_state, op);
1106 if (ACPI_FAILURE (status2)) {
1107 return_ACPI_STATUS (status2);
1108 }
1057 } 1109 }
1058 1110
1059 acpi_ps_pop_scope (parser_state, &op, 1111 acpi_ps_pop_scope (parser_state, &op,
@@ -1065,12 +1117,17 @@ close_this_op:
1065 } 1117 }
1066 1118
1067 else if (ACPI_FAILURE (status)) { 1119 else if (ACPI_FAILURE (status)) {
1068 acpi_ps_complete_this_op (walk_state, op); 1120 /* First error is most important */
1121
1122 (void) acpi_ps_complete_this_op (walk_state, op);
1069 return_ACPI_STATUS (status); 1123 return_ACPI_STATUS (status);
1070 } 1124 }
1071 } 1125 }
1072 1126
1073 acpi_ps_complete_this_op (walk_state, op); 1127 status2 = acpi_ps_complete_this_op (walk_state, op);
1128 if (ACPI_FAILURE (status2)) {
1129 return_ACPI_STATUS (status2);
1130 }
1074 } 1131 }
1075 1132
1076 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, 1133 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index dc3c3f6a9f62..198997aa7fbe 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -331,8 +331,10 @@ acpi_get_firmware_table (
331 331
332 332
333cleanup: 333cleanup:
334 acpi_os_unmap_memory (rsdt_info->pointer, 334 if (rsdt_info->pointer) {
335 (acpi_size) rsdt_info->pointer->length); 335 acpi_os_unmap_memory (rsdt_info->pointer,
336 (acpi_size) rsdt_info->pointer->length);
337 }
336 ACPI_MEM_FREE (rsdt_info); 338 ACPI_MEM_FREE (rsdt_info);
337 339
338 if (header) { 340 if (header) {
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index f6de4ed3d527..bb658777fa88 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -787,7 +787,6 @@ acpi_ut_release_mutex (
787 acpi_mutex_handle mutex_id) 787 acpi_mutex_handle mutex_id)
788{ 788{
789 acpi_status status; 789 acpi_status status;
790 u32 i;
791 u32 this_thread_id; 790 u32 this_thread_id;
792 791
793 792
@@ -814,25 +813,32 @@ acpi_ut_release_mutex (
814 return (AE_NOT_ACQUIRED); 813 return (AE_NOT_ACQUIRED);
815 } 814 }
816 815
817 /* 816#ifdef ACPI_MUTEX_DEBUG
818 * Deadlock prevention. Check if this thread owns any mutexes of value 817 {
819 * greater than this one. If so, the thread has violated the mutex 818 u32 i;
820 * ordering rule. This indicates a coding error somewhere in 819 /*
821 * the ACPI subsystem code. 820 * Mutex debug code, for internal debugging only.
822 */ 821 *
823 for (i = mutex_id; i < MAX_MUTEX; i++) { 822 * Deadlock prevention. Check if this thread owns any mutexes of value
824 if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { 823 * greater than this one. If so, the thread has violated the mutex
825 if (i == mutex_id) { 824 * ordering rule. This indicates a coding error somewhere in
826 continue; 825 * the ACPI subsystem code.
827 } 826 */
827 for (i = mutex_id; i < MAX_MUTEX; i++) {
828 if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
829 if (i == mutex_id) {
830 continue;
831 }
828 832
829 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 833 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
830 "Invalid release order: owns [%s], releasing [%s]\n", 834 "Invalid release order: owns [%s], releasing [%s]\n",
831 acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); 835 acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));
832 836
833 return (AE_RELEASE_DEADLOCK); 837 return (AE_RELEASE_DEADLOCK);
838 }
834 } 839 }
835 } 840 }
841#endif
836 842
837 /* Mark unlocked FIRST */ 843 /* Mark unlocked FIRST */
838 844
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index a268c4ae1877..6babcb104930 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -64,7 +64,7 @@
64 64
65/* Version string */ 65/* Version string */
66 66
67#define ACPI_CA_VERSION 0x20050513 67#define ACPI_CA_VERSION 0x20050526
68 68
69/* 69/*
70 * OS name, used for the _OS object. The _OS object is essentially obsolete, 70 * OS name, used for the _OS object. The _OS object is essentially obsolete,
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index e6b9e36a2eda..4e926457bd2f 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -78,7 +78,7 @@ struct acpi_walk_state
78 u8 return_used; 78 u8 return_used;
79 u16 opcode; /* Current AML opcode */ 79 u16 opcode; /* Current AML opcode */
80 u8 scope_depth; 80 u8 scope_depth;
81 u8 reserved1; 81 u8 pass_number; /* Parse pass during table load */
82 u32 arg_count; /* push for fixed or var args */ 82 u32 arg_count; /* push for fixed or var args */
83 u32 aml_offset; 83 u32 aml_offset;
84 u32 arg_types; 84 u32 arg_types;