aboutsummaryrefslogtreecommitdiffstats
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;
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,