diff options
-rw-r--r-- | drivers/acpi/dispatcher/dsopcode.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 69fae5905bb8..5cd406676c2c 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c | |||
@@ -1140,10 +1140,29 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | |||
1140 | op->common.aml_opcode, walk_state)); | 1140 | op->common.aml_opcode, walk_state)); |
1141 | 1141 | ||
1142 | switch (op->common.aml_opcode) { | 1142 | switch (op->common.aml_opcode) { |
1143 | case AML_IF_OP: | ||
1144 | case AML_WHILE_OP: | 1143 | case AML_WHILE_OP: |
1145 | 1144 | ||
1146 | /* | 1145 | /* |
1146 | * If this is an additional iteration of a while loop, continue. | ||
1147 | * There is no need to allocate a new control state. | ||
1148 | */ | ||
1149 | if (walk_state->control_state) { | ||
1150 | if (walk_state->control_state->control.aml_predicate_start | ||
1151 | == (walk_state->parser_state.aml - 1)) { | ||
1152 | |||
1153 | /* Reset the state to start-of-loop */ | ||
1154 | |||
1155 | walk_state->control_state->common.state = | ||
1156 | ACPI_CONTROL_CONDITIONAL_EXECUTING; | ||
1157 | break; | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | /*lint -fallthrough */ | ||
1162 | |||
1163 | case AML_IF_OP: | ||
1164 | |||
1165 | /* | ||
1147 | * IF/WHILE: Create a new control state to manage these | 1166 | * IF/WHILE: Create a new control state to manage these |
1148 | * constructs. We need to manage these as a stack, in order | 1167 | * constructs. We need to manage these as a stack, in order |
1149 | * to handle nesting. | 1168 | * to handle nesting. |
@@ -1248,8 +1267,13 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | |||
1248 | /* Predicate was true, go back and evaluate it again! */ | 1267 | /* Predicate was true, go back and evaluate it again! */ |
1249 | 1268 | ||
1250 | status = AE_CTRL_PENDING; | 1269 | status = AE_CTRL_PENDING; |
1270 | walk_state->aml_last_while = | ||
1271 | walk_state->control_state->control.aml_predicate_start; | ||
1272 | break; | ||
1251 | } | 1273 | } |
1252 | 1274 | ||
1275 | /* Predicate was false, terminate this while loop */ | ||
1276 | |||
1253 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 1277 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
1254 | "[WHILE_OP] termination! Op=%p\n", op)); | 1278 | "[WHILE_OP] termination! Op=%p\n", op)); |
1255 | 1279 | ||
@@ -1257,9 +1281,6 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | |||
1257 | 1281 | ||
1258 | control_state = | 1282 | control_state = |
1259 | acpi_ut_pop_generic_state(&walk_state->control_state); | 1283 | acpi_ut_pop_generic_state(&walk_state->control_state); |
1260 | |||
1261 | walk_state->aml_last_while = | ||
1262 | control_state->control.aml_predicate_start; | ||
1263 | acpi_ut_delete_generic_state(control_state); | 1284 | acpi_ut_delete_generic_state(control_state); |
1264 | break; | 1285 | break; |
1265 | 1286 | ||