acpi_status acpi_ns_execute_control_method ( acpi_namespace_node *method_node, acpi_operand_object **params, acpi_operand_object **return_obj_desc) { acpi_status status; acpi_operand_object *obj_desc; FUNCTION_TRACE ("Ns_execute_control_method"); /* Verify that there is a method associated with this object */ obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_NULL_OBJECT); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Control method at Offset %p Length %x]\n", obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1)); DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing", ACPI_LV_NAMES, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "At offset %p\n", obj_desc->method.aml_start + 1)); /* * Unlock the namespace before execution. This allows namespace access * via the external Acpi* interfaces while a method is being executed. * However, any namespace deletion must acquire both the namespace and * interpreter locks to ensure that no thread is using the portion of the * namespace that is being deleted. */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ status = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_psx_execute (method_node, params, return_obj_desc); acpi_ex_exit_interpreter (); return_ACPI_STATUS (status); }
acpi_status acpi_psx_execute ( acpi_namespace_node *method_node, acpi_operand_object **params, acpi_operand_object **return_obj_desc) { acpi_status status; acpi_operand_object *obj_desc; u32 i; acpi_parse_object *op; acpi_walk_state *walk_state; FUNCTION_TRACE ("Psx_execute"); /* Validate the Node and get the attached object */ if (!method_node) { return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if (params) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; params[i]; i++) { acpi_ut_add_reference (params[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Method Parse **** Entry=%p obj=%p\n", method_node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_alloc_op (AML_SCOPE_OP); if (!op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { /* TBD: delete walk state */ return_ACPI_STATUS (status); } /* Parse the AML */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Method Execution **** Entry=%p obj=%p\n", method_node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_alloc_op (AML_SCOPE_OP); if (!op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the NS node */ acpi_ps_set_name (op, method_node->name); op->node = method_node; /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, params, return_obj_desc, 3); if (ACPI_FAILURE (status)) { /* TBD: delete walk state */ return_ACPI_STATUS (status); } /* * The walk of the parse tree is where we actually execute the method */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); if (params) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; params[i]; i++) { acpi_ut_update_object_reference (params[i], REF_DECREMENT); } } if (ACPI_FAILURE (status)) { DUMP_PATHNAME (method_node, "Ps_execute: method failed -", ACPI_LV_ERROR, _COMPONENT); } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (*return_obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method returned Obj_desc=%p\n", *return_obj_desc)); DUMP_STACK_ENTRY (*return_obj_desc); status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (status); }