summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/parser/psparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/parser/psparse.c')
-rw-r--r--drivers/acpi/parser/psparse.c109
1 files changed, 83 insertions, 26 deletions
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;
/* Local prototypes */
-static void
+static acpi_status
acpi_ps_complete_this_op (
struct acpi_walk_state *walk_state,
union acpi_parse_object *op);
@@ -152,13 +152,13 @@ acpi_ps_peek_opcode (
* PARAMETERS: walk_state - Current State
* Op - Op to complete
*
- * RETURN: None.
+ * RETURN: Status
*
* DESCRIPTION: Perform any cleanup at the completion of an Op.
*
******************************************************************************/
-static void
+static acpi_status
acpi_ps_complete_this_op (
struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
@@ -175,19 +175,26 @@ acpi_ps_complete_this_op (
/* Check for null Op, can happen if AML code is corrupt */
if (!op) {
- return_VOID;
+ return_ACPI_STATUS (AE_OK); /* OK for now */
}
/* Delete this op and the subtree below it if asked to */
if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
(walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
- return_VOID;
+ return_ACPI_STATUS (AE_OK);
}
/* Make sure that we only delete this subtree */
if (op->common.parent) {
+ prev = op->common.parent->common.value.arg;
+ if (!prev) {
+ /* Nothing more to do */
+
+ goto cleanup;
+ }
+
/*
* Check if we need to replace the operator and its subtree
* with a return value op (placeholder op)
@@ -206,7 +213,7 @@ acpi_ps_complete_this_op (
*/
replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
break;
@@ -223,18 +230,17 @@ acpi_ps_complete_this_op (
(op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
}
-
- if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
+ else if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
+ (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
if ((op->common.aml_opcode == AML_BUFFER_OP) ||
(op->common.aml_opcode == AML_PACKAGE_OP) ||
(op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
replacement_op->named.data = op->named.data;
@@ -244,15 +250,15 @@ acpi_ps_complete_this_op (
break;
default:
+
replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
if (!replacement_op) {
- goto cleanup;
+ goto allocate_error;
}
}
/* We must unlink this op from the parent tree */
- prev = op->common.parent->common.value.arg;
if (prev == op) {
/* This op is the first in the list */
@@ -298,7 +304,15 @@ cleanup:
/* Now we can actually delete the subtree rooted at Op */
acpi_ps_delete_parse_tree (op);
- return_VOID;
+ return_ACPI_STATUS (AE_OK);
+
+
+allocate_error:
+
+ /* Always delete the subtree, even on error */
+
+ acpi_ps_delete_parse_tree (op);
+ return_ACPI_STATUS (AE_NO_MEMORY);
}
@@ -443,6 +457,7 @@ acpi_ps_parse_loop (
struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
+ acpi_status status2;
union acpi_parse_object *op = NULL; /* current op */
union acpi_parse_object *arg = NULL;
union acpi_parse_object *pre_op = NULL;
@@ -744,7 +759,6 @@ acpi_ps_parse_loop (
break;
default:
-
/*
* Op is not a constant or string, append each argument
* to the Op
@@ -770,6 +784,23 @@ acpi_ps_parse_loop (
/* Special processing for certain opcodes */
+ if (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) {
+ switch (op->common.aml_opcode) {
+ case AML_IF_OP:
+ case AML_ELSE_OP:
+ case AML_WHILE_OP:
+
+ /* Skip body of if/else/while in pass 1 */
+
+ parser_state->aml = parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+
switch (op->common.aml_opcode) {
case AML_METHOD_OP:
@@ -796,7 +827,7 @@ acpi_ps_parse_loop (
if ((op->common.parent) &&
(op->common.parent->common.aml_opcode == AML_NAME_OP) &&
- (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
+ (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
/*
* Skip parsing of Buffers and Packages
* because we don't have enough info in the first pass
@@ -900,15 +931,21 @@ close_this_op:
*/
parser_state->scope->parse_scope.arg_count--;
- /* Close this Op (will result in parse subtree deletion) */
+ /* Finished with pre_op */
- acpi_ps_complete_this_op (walk_state, op);
- op = NULL;
if (pre_op) {
acpi_ps_free_op (pre_op);
pre_op = NULL;
}
+ /* Close this Op (will result in parse subtree deletion) */
+
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
+ op = NULL;
+
switch (status) {
case AE_OK:
break;
@@ -936,7 +973,10 @@ close_this_op:
status = walk_state->ascending_callback (walk_state);
status = acpi_ps_next_parse_state (walk_state, op, status);
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
op = NULL;
}
status = AE_OK;
@@ -962,7 +1002,10 @@ close_this_op:
status = walk_state->ascending_callback (walk_state);
status = acpi_ps_next_parse_state (walk_state, op, status);
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
op = NULL;
status = AE_OK;
@@ -976,7 +1019,10 @@ close_this_op:
/* Clean up */
do {
if (op) {
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
}
acpi_ps_pop_scope (parser_state, &op,
&walk_state->arg_types, &walk_state->arg_count);
@@ -990,7 +1036,10 @@ close_this_op:
do {
if (op) {
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
}
acpi_ps_pop_scope (parser_state, &op,
&walk_state->arg_types, &walk_state->arg_count);
@@ -1053,7 +1102,10 @@ close_this_op:
/* Clean up */
do {
if (op) {
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
}
acpi_ps_pop_scope (parser_state, &op,
@@ -1065,12 +1117,17 @@ close_this_op:
}
else if (ACPI_FAILURE (status)) {
- acpi_ps_complete_this_op (walk_state, op);
+ /* First error is most important */
+
+ (void) acpi_ps_complete_this_op (walk_state, op);
return_ACPI_STATUS (status);
}
}
- acpi_ps_complete_this_op (walk_state, op);
+ status2 = acpi_ps_complete_this_op (walk_state, op);
+ if (ACPI_FAILURE (status2)) {
+ return_ACPI_STATUS (status2);
+ }
}
acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
OpenPOWER on IntegriCloud