aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c65
-rw-r--r--drivers/acpi/dispatcher/dsobject.c81
-rw-r--r--drivers/acpi/dispatcher/dswexec.c33
-rw-r--r--drivers/acpi/dispatcher/dswload.c110
4 files changed, 203 insertions, 86 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 58ad00b31ee9..e7ce86b8d954 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -47,12 +47,70 @@
47#include <acpi/acdispat.h> 47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h> 48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h> 49#include <acpi/acnamesp.h>
50#include <acpi/acdisasm.h>
50 51
51#define _COMPONENT ACPI_DISPATCHER 52#define _COMPONENT ACPI_DISPATCHER
52ACPI_MODULE_NAME("dsmethod") 53ACPI_MODULE_NAME("dsmethod")
53 54
54/******************************************************************************* 55/*******************************************************************************
55 * 56 *
57 * FUNCTION: acpi_ds_method_error
58 *
59 * PARAMETERS: Status - Execution status
60 * walk_state - Current state
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Called on method error. Invoke the global exception handler if
65 * present, dump the method data if the disassembler is configured
66 *
67 * Note: Allows the exception handler to change the status code
68 *
69 ******************************************************************************/
70acpi_status
71acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
72{
73 ACPI_FUNCTION_ENTRY();
74
75 /* Ignore AE_OK and control exception codes */
76
77 if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {
78 return (status);
79 }
80
81 /* Invoke the global exception handler */
82
83 if (acpi_gbl_exception_handler) {
84 /* Exit the interpreter, allow handler to execute methods */
85
86 acpi_ex_exit_interpreter();
87
88 /*
89 * Handler can map the exception code to anything it wants, including
90 * AE_OK, in which case the executing method will not be aborted.
91 */
92 status = acpi_gbl_exception_handler(status,
93 walk_state->method_node ?
94 walk_state->method_node->
95 name.integer : 0,
96 walk_state->opcode,
97 walk_state->aml_offset,
98 NULL);
99 (void)acpi_ex_enter_interpreter();
100 }
101#ifdef ACPI_DISASSEMBLER
102 if (ACPI_FAILURE(status)) {
103 /* Display method locals/args if disassembler is present */
104
105 acpi_dm_dump_method_info(status, walk_state, walk_state->op);
106 }
107#endif
108
109 return (status);
110}
111
112/*******************************************************************************
113 *
56 * FUNCTION: acpi_ds_begin_method_execution 114 * FUNCTION: acpi_ds_begin_method_execution
57 * 115 *
58 * PARAMETERS: method_node - Node of the method 116 * PARAMETERS: method_node - Node of the method
@@ -66,10 +124,11 @@ ACPI_MODULE_NAME("dsmethod")
66 * for clearance to execute. 124 * for clearance to execute.
67 * 125 *
68 ******************************************************************************/ 126 ******************************************************************************/
127
69acpi_status 128acpi_status
70acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, 129acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
71 union acpi_operand_object *obj_desc, 130 union acpi_operand_object * obj_desc,
72 struct acpi_namespace_node *calling_method_node) 131 struct acpi_namespace_node * calling_method_node)
73{ 132{
74 acpi_status status = AE_OK; 133 acpi_status status = AE_OK;
75 134
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 8ac0cd93adb5..905a84e4b145 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -51,6 +51,7 @@
51#define _COMPONENT ACPI_DISPATCHER 51#define _COMPONENT ACPI_DISPATCHER
52ACPI_MODULE_NAME("dsobject") 52ACPI_MODULE_NAME("dsobject")
53 53
54/* Local prototypes */
54static acpi_status 55static acpi_status
55acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, 56acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
56 union acpi_parse_object *op, 57 union acpi_parse_object *op,
@@ -85,7 +86,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
85 *obj_desc_ptr = NULL; 86 *obj_desc_ptr = NULL;
86 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { 87 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
87 /* 88 /*
88 * This is an named object reference. If this name was 89 * This is a named object reference. If this name was
89 * previously looked up in the namespace, it was stored in this op. 90 * previously looked up in the namespace, it was stored in this op.
90 * Otherwise, go ahead and look it up now 91 * Otherwise, go ahead and look it up now
91 */ 92 */
@@ -96,18 +97,48 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
96 ACPI_IMODE_EXECUTE, 97 ACPI_IMODE_EXECUTE,
97 ACPI_NS_SEARCH_PARENT | 98 ACPI_NS_SEARCH_PARENT |
98 ACPI_NS_DONT_OPEN_SCOPE, NULL, 99 ACPI_NS_DONT_OPEN_SCOPE, NULL,
99 (struct acpi_namespace_node **) 100 ACPI_CAST_INDIRECT_PTR(struct
100 &(op->common.node)); 101 acpi_namespace_node,
101 102 &(op->
103 common.
104 node)));
102 if (ACPI_FAILURE(status)) { 105 if (ACPI_FAILURE(status)) {
103 ACPI_REPORT_NSERROR(op->common.value.string, 106 /* Check if we are resolving a named reference within a package */
104 status); 107
108 if ((status == AE_NOT_FOUND)
109 && (acpi_gbl_enable_interpreter_slack)
110 &&
111 ((op->common.parent->common.aml_opcode ==
112 AML_PACKAGE_OP)
113 || (op->common.parent->common.aml_opcode ==
114 AML_VAR_PACKAGE_OP))) {
115 /*
116 * We didn't find the target and we are populating elements
117 * of a package - ignore if slack enabled. Some ASL code
118 * contains dangling invalid references in packages and
119 * expects that no exception will be issued. Leave the
120 * element as a null element. It cannot be used, but it
121 * can be overwritten by subsequent ASL code - this is
122 * typically the case.
123 */
124 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
125 "Ignoring unresolved reference in package [%4.4s]\n",
126 walk_state->
127 scope_info->scope.
128 node->name.ascii));
129
130 return_ACPI_STATUS(AE_OK);
131 } else {
132 ACPI_REPORT_NSERROR(op->common.value.
133 string, status);
134 }
135
105 return_ACPI_STATUS(status); 136 return_ACPI_STATUS(status);
106 } 137 }
107 } 138 }
108 } 139 }
109 140
110 /* Create and init the internal ACPI object */ 141 /* Create and init a new internal ACPI object */
111 142
112 obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info 143 obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
113 (op->common.aml_opcode))-> 144 (op->common.aml_opcode))->
@@ -157,13 +188,13 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
157 188
158 ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj"); 189 ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
159 190
191 /*
192 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
193 * The buffer object already exists (from the NS node), otherwise it must
194 * be created.
195 */
160 obj_desc = *obj_desc_ptr; 196 obj_desc = *obj_desc_ptr;
161 if (obj_desc) { 197 if (!obj_desc) {
162 /*
163 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
164 * The buffer object already exists (from the NS node)
165 */
166 } else {
167 /* Create a new buffer object */ 198 /* Create a new buffer object */
168 199
169 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); 200 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
@@ -259,7 +290,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
259 union acpi_operand_object *obj_desc = NULL; 290 union acpi_operand_object *obj_desc = NULL;
260 u32 package_list_length; 291 u32 package_list_length;
261 acpi_status status = AE_OK; 292 acpi_status status = AE_OK;
262 u32 i; 293 acpi_native_uint i;
263 294
264 ACPI_FUNCTION_TRACE("ds_build_internal_package_obj"); 295 ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
265 296
@@ -271,13 +302,12 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
271 parent = parent->common.parent; 302 parent = parent->common.parent;
272 } 303 }
273 304
305 /*
306 * If we are evaluating a Named package object "Name (xxxx, Package)",
307 * the package object already exists, otherwise it must be created.
308 */
274 obj_desc = *obj_desc_ptr; 309 obj_desc = *obj_desc_ptr;
275 if (obj_desc) { 310 if (!obj_desc) {
276 /*
277 * We are evaluating a Named package object "Name (xxxx, Package)".
278 * Get the existing package object from the NS node
279 */
280 } else {
281 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); 311 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
282 *obj_desc_ptr = obj_desc; 312 *obj_desc_ptr = obj_desc;
283 if (!obj_desc) { 313 if (!obj_desc) {
@@ -291,11 +321,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
291 321
292 /* Count the number of items in the package list */ 322 /* Count the number of items in the package list */
293 323
294 package_list_length = 0;
295 arg = op->common.value.arg; 324 arg = op->common.value.arg;
296 arg = arg->common.next; 325 arg = arg->common.next;
297 while (arg) { 326 for (package_list_length = 0; arg; package_list_length++) {
298 package_list_length++;
299 arg = arg->common.next; 327 arg = arg->common.next;
300 } 328 }
301 329
@@ -322,12 +350,11 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
322 } 350 }
323 351
324 /* 352 /*
325 * Now init the elements of the package 353 * Initialize all elements of the package
326 */ 354 */
327 i = 0;
328 arg = op->common.value.arg; 355 arg = op->common.value.arg;
329 arg = arg->common.next; 356 arg = arg->common.next;
330 while (arg) { 357 for (i = 0; arg; i++) {
331 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { 358 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
332 /* Object (package or buffer) is already built */ 359 /* Object (package or buffer) is already built */
333 360
@@ -340,8 +367,6 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
340 package. 367 package.
341 elements[i]); 368 elements[i]);
342 } 369 }
343
344 i++;
345 arg = arg->common.next; 370 arg = arg->common.next;
346 } 371 }
347 372
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index e522763bb692..74f6996db2d7 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -314,12 +314,13 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
314 314
315 case AML_CLASS_EXECUTE: 315 case AML_CLASS_EXECUTE:
316 case AML_CLASS_CREATE: 316 case AML_CLASS_CREATE:
317
318 /* 317 /*
319 * Most operators with arguments. 318 * Most operators with arguments.
320 * Start a new result/operand state 319 * Start a new result/operand state
321 */ 320 */
322 status = acpi_ds_result_stack_push(walk_state); 321 if (walk_state->opcode != AML_CREATE_FIELD_OP) {
322 status = acpi_ds_result_stack_push(walk_state);
323 }
323 break; 324 break;
324 325
325 default: 326 default:
@@ -723,20 +724,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
723 724
724 cleanup: 725 cleanup:
725 726
726 /* Invoke exception handler on error */
727
728 if (ACPI_FAILURE(status) &&
729 acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
730 acpi_ex_exit_interpreter();
731 status = acpi_gbl_exception_handler(status,
732 walk_state->method_node->
733 name.integer,
734 walk_state->opcode,
735 walk_state->aml_offset,
736 NULL);
737 (void)acpi_ex_enter_interpreter();
738 }
739
740 if (walk_state->result_obj) { 727 if (walk_state->result_obj) {
741 /* Break to debugger to display result */ 728 /* Break to debugger to display result */
742 729
@@ -758,18 +745,14 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
758 } 745 }
759#endif 746#endif
760 747
761 /* Always clear the object stack */ 748 /* Invoke exception handler on error */
762
763 walk_state->num_operands = 0;
764
765#ifdef ACPI_DISASSEMBLER
766
767 /* On error, display method locals/args */
768 749
769 if (ACPI_FAILURE(status)) { 750 if (ACPI_FAILURE(status)) {
770 acpi_dm_dump_method_info(status, walk_state, op); 751 status = acpi_ds_method_error(status, walk_state);
771 } 752 }
772#endif
773 753
754 /* Always clear the object stack */
755
756 walk_state->num_operands = 0;
774 return_ACPI_STATUS(status); 757 return_ACPI_STATUS(status);
775} 758}
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 44d4f4bb2f92..441931cab08a 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -428,43 +428,54 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
428 } 428 }
429 } 429 }
430 430
431 if (op->common.aml_opcode == AML_METHOD_OP) { 431 /*
432 /* 432 * If we are executing a method, do not create any namespace objects
433 * method_op pkg_length name_string method_flags term_list 433 * during the load phase, only during execution.
434 * 434 */
435 * Note: We must create the method node/object pair as soon as we 435 if (!walk_state->method_node) {
436 * see the method declaration. This allows later pass1 parsing 436 if (op->common.aml_opcode == AML_METHOD_OP) {
437 * of invocations of the method (need to know the number of 437 /*
438 * arguments.) 438 * method_op pkg_length name_string method_flags term_list
439 */ 439 *
440 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 440 * Note: We must create the method node/object pair as soon as we
441 "LOADING-Method: State=%p Op=%p named_obj=%p\n", 441 * see the method declaration. This allows later pass1 parsing
442 walk_state, op, op->named.node)); 442 * of invocations of the method (need to know the number of
443 * arguments.)
444 */
445 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
446 "LOADING-Method: State=%p Op=%p named_obj=%p\n",
447 walk_state, op, op->named.node));
443 448
444 if (!acpi_ns_get_attached_object(op->named.node)) { 449 if (!acpi_ns_get_attached_object(op->named.node)) {
445 walk_state->operands[0] = (void *)op->named.node; 450 walk_state->operands[0] =
446 walk_state->num_operands = 1; 451 ACPI_CAST_PTR(void, op->named.node);
452 walk_state->num_operands = 1;
447 453
448 status = 454 status =
449 acpi_ds_create_operands(walk_state, 455 acpi_ds_create_operands(walk_state,
450 op->common.value.arg); 456 op->common.value.
451 if (ACPI_SUCCESS(status)) { 457 arg);
452 status = acpi_ex_create_method(op->named.data, 458 if (ACPI_SUCCESS(status)) {
453 op->named.length, 459 status =
454 walk_state); 460 acpi_ex_create_method(op->named.
455 } 461 data,
456 walk_state->operands[0] = NULL; 462 op->named.
457 walk_state->num_operands = 0; 463 length,
464 walk_state);
465 }
466 walk_state->operands[0] = NULL;
467 walk_state->num_operands = 0;
458 468
459 if (ACPI_FAILURE(status)) { 469 if (ACPI_FAILURE(status)) {
460 return_ACPI_STATUS(status); 470 return_ACPI_STATUS(status);
471 }
461 } 472 }
462 } 473 }
463 } 474 }
464 475
465 /* Pop the scope stack */ 476 /* Pop the scope stack (only if loading a table) */
466 477
467 if (acpi_ns_opens_scope(object_type)) { 478 if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
468 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 479 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
469 "(%s): Popping scope for Op %p\n", 480 "(%s): Popping scope for Op %p\n",
470 acpi_ut_get_type_name(object_type), op)); 481 acpi_ut_get_type_name(object_type), op));
@@ -1015,11 +1026,50 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
1015 1026
1016 status = acpi_ds_create_node(walk_state, node, op); 1027 status = acpi_ds_create_node(walk_state, node, op);
1017 break; 1028 break;
1029
1030 case AML_METHOD_OP:
1031 /*
1032 * method_op pkg_length name_string method_flags term_list
1033 *
1034 * Note: We must create the method node/object pair as soon as we
1035 * see the method declaration. This allows later pass1 parsing
1036 * of invocations of the method (need to know the number of
1037 * arguments.)
1038 */
1039 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
1040 "LOADING-Method: State=%p Op=%p named_obj=%p\n",
1041 walk_state, op, op->named.node));
1042
1043 if (!acpi_ns_get_attached_object(op->named.node)) {
1044 walk_state->operands[0] =
1045 ACPI_CAST_PTR(void, op->named.node);
1046 walk_state->num_operands = 1;
1047
1048 status =
1049 acpi_ds_create_operands(walk_state,
1050 op->common.value.
1051 arg);
1052 if (ACPI_SUCCESS(status)) {
1053 status =
1054 acpi_ex_create_method(op->named.
1055 data,
1056 op->named.
1057 length,
1058 walk_state);
1059 }
1060 walk_state->operands[0] = NULL;
1061 walk_state->num_operands = 0;
1062
1063 if (ACPI_FAILURE(status)) {
1064 return_ACPI_STATUS(status);
1065 }
1066 }
1067 break;
1068
1018#endif /* ACPI_NO_METHOD_EXECUTION */ 1069#endif /* ACPI_NO_METHOD_EXECUTION */
1019 1070
1020 default: 1071 default:
1021 /* All NAMED_COMPLEX opcodes must be handled above */ 1072 /* All NAMED_COMPLEX opcodes must be handled above */
1022 /* Note: Method objects were already created in Pass 1 */
1023 break; 1073 break;
1024 } 1074 }
1025 break; 1075 break;