diff options
author | Bob Moore <robert.moore@intel.com> | 2006-05-27 00:36:00 +0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-06-14 10:44:35 +0400 |
commit | 4119532c95547821dbe72d6916dfa1b2148475b3 (patch) | |
tree | 564eb8f69924fb7dc72e93526faf1547acac7d30 /drivers/acpi/namespace | |
parent | b8d35192c55fb055792ff0641408eaaec7c88988 (diff) | |
download | linux-4119532c95547821dbe72d6916dfa1b2148475b3.tar.xz |
ACPI: ACPICA 20060526
Restructured, flattened, and simplified the internal
interfaces for namespace object evaluation - resulting
in smaller code, less CPU stack use, and fewer
interfaces. (With assistance from Mikhail Kouzmich)
Fixed a problem with the CopyObject operator where the
first parameter was not typed correctly for the parser,
interpreter, compiler, and disassembler. Caused various
errors and unexpected behavior.
Fixed a problem where a ShiftLeft or ShiftRight of
more than 64 bits produced incorrect results with some
C compilers. Since the behavior of C compilers when
the shift value is larger than the datatype width is
apparently not well defined, the interpreter now detects
this condition and simply returns zero as expected in all
such cases. (BZ 395)
Fixed problem reports (Valery Podrezov) integrated: -
Update String-to-Integer conversion to match ACPI 3.0A spec
http://bugzilla.kernel.org/show_bug.cgi?id=5329
Allow interpreter to handle nested method declarations
http://bugzilla.kernel.org/show_bug.cgi?id=5361
Fixed problem reports (Fiodor Suietov) integrated: -
acpi_terminate() doesn't free debug memory allocation
list objects (BZ 355) - After Core Subsystem
shutdown, acpi_subsystem_status() returns AE_OK (BZ 356) -
acpi_os_unmap_memory() for RSDP can be invoked inconsistently
(BZ 357) - Resource Manager should return AE_TYPE for
non-device objects (BZ 358) - Incomplete cleanup branch
in AcpiNsEvaluateRelative (BZ 359) - Use acpi_os_free()
instead of ACPI_FREE in acpi_rs_set_srs_method_data (BZ 360)
- Incomplete cleanup branch in acpi_ps_parse_aml (BZ 361) -
Incomplete cleanup branch in acpi_ds_delete_walk_state (BZ 362)
- acpi_get_table_header returns AE_NO_ACPI_TABLES until DSDT
is loaded (BZ 365) - Status of the Global Initialization
Handler call not used (BZ 366) - Incorrect object parameter
to Global Initialization Handler (BZ 367)
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/namespace')
-rw-r--r-- | drivers/acpi/namespace/nsaccess.c | 6 | ||||
-rw-r--r-- | drivers/acpi/namespace/nseval.c | 485 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsinit.c | 57 | ||||
-rw-r--r-- | drivers/acpi/namespace/nssearch.c | 82 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsutils.c | 63 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsxfeval.c | 119 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsxfname.c | 5 |
7 files changed, 293 insertions, 524 deletions
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index ba8ad569188f..48fadade52e2 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -259,10 +259,8 @@ acpi_status acpi_ns_root_initialize(void) /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS(status)) { - status = - acpi_ns_get_node_by_path("\\_GPE", NULL, - ACPI_NS_NO_UPSEARCH, - &acpi_gbl_fadt_gpe_device); + status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, + &acpi_gbl_fadt_gpe_device); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 4b054062b46a..4b0a4a8c9843 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -1,7 +1,6 @@ /******************************************************************************* * - * Module Name: nseval - Object evaluation interfaces -- includes control - * method lookup and execution. + * Module Name: nseval - Object evaluation, includes control method execution * ******************************************************************************/ @@ -50,196 +49,14 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nseval") -/* Local prototypes */ -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info); - -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info); - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_relative - * - * PARAMETERS: Pathname - Name of method to execute, If NULL, the - * handle is the object to execute - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or find and execute the requested method - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - struct acpi_namespace_node *node = NULL; - union acpi_generic_state *scope_info; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE(ns_evaluate_relative); - - /* - * Must have a valid object handle - */ - if (!info || !info->node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - scope_info = acpi_ut_create_generic_state(); - if (!scope_info) { - goto cleanup1; - } - - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* Lookup the name in the namespace */ - - scope_info->scope.node = info->node; - status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n", - pathname, acpi_format_exception(status))); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, node, acpi_ns_get_attached_object(node))); - - info->node = node; - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - acpi_ut_delete_generic_state(scope_info); - - cleanup1: - ACPI_FREE(internal_path); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_by_name - * - * PARAMETERS: Pathname - Fully qualified pathname to the object - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or rind and execute the requested method - * passing the given parameters - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE(ns_evaluate_by_name); - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Lookup the name in the namespace */ - - status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &info->node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Object at [%s] was not found, status=%.4X\n", - pathname, status)); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, info->node, - acpi_ns_get_attached_object(info->node))); - - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - - /* Cleanup */ - - if (internal_path) { - ACPI_FREE(internal_path); - } - - return_ACPI_STATUS(status); -} - /******************************************************************************* * - * FUNCTION: acpi_ns_evaluate_by_handle + * FUNCTION: acpi_ns_evaluate * - * PARAMETERS: Info - Method info block, contains: - * Node - Method/Object Node to execute + * PARAMETERS: Info - Evaluation info block, contains: + * prefix_node - Prefix or Method/Object Node to execute + * Pathname - Name of method to execute, If NULL, the + * Node is the object to execute * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. @@ -248,29 +65,21 @@ acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. + * Flags - ACPI_IGNORE_RETURN_VALUE to delete return * * RETURN: Status * - * DESCRIPTION: Evaluate object or execute the requested method passing the - * given parameters + * DESCRIPTION: Execute a control method or return the current value of an + * ACPI namespace object. * - * MUTEX: Locks Namespace + * MUTEX: Locks interpreter * ******************************************************************************/ - -acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE(ns_evaluate_by_handle); - - /* Check if namespace has been initialized */ - - if (!acpi_gbl_root_node) { - return_ACPI_STATUS(AE_NO_NAMESPACE); - } - - /* Parameter Validation */ + ACPI_FUNCTION_TRACE(ns_evaluate); if (!info) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -280,203 +89,120 @@ acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) info->return_object = NULL; - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + /* + * Get the actual namespace node for the target object. Handles these cases: + * + * 1) Null node, Pathname (absolute path) + * 2) Node, Pathname (path relative to Node) + * 3) Node, Null Pathname + */ + status = acpi_ns_get_node(info->prefix_node, info->pathname, + ACPI_NS_NO_UPSEARCH, &info->resolved_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - /* * For a method alias, we must grab the actual method node so that proper * scoping context will be established before execution. */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->node = + if (acpi_ns_get_type(info->resolved_node) == + ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node, - info->node->object); + info->resolved_node->object); } + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, + info->resolved_node, + acpi_ns_get_attached_object(info->resolved_node))); + /* * Two major cases here: - * 1) The object is an actual control method -- execute it. - * 2) The object is not a method -- just return it's current value * - * In both cases, the namespace is unlocked by the acpi_ns* procedure + * 1) The object is a control method -- execute it + * 2) The object is not a method -- just return it's current value */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) { + if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { /* - * Case 1) We have an actual control method to execute + * 1) Object is a control method - execute it */ - status = acpi_ns_execute_control_method(info); - } else { - /* - * Case 2) Object is NOT a method, just return its current value - */ - status = acpi_ns_get_object_value(info); - } - - /* - * Check if there is a return value on the stack that must be dealt with - */ - if (status == AE_CTRL_RETURN_VALUE) { - - /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ - - status = AE_OK; - } - - /* - * Namespace was unlocked by the handling acpi_ns* function, so we - * just return - */ - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_execute_control_method - * - * PARAMETERS: Info - Method info block, contains: - * Node - Method Node to execute - * obj_desc - Method object - * Parameters - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * parameter_type - Type of Parameter list - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Execute the requested method passing the given parameters - * - * MUTEX: Assumes namespace is locked - * - ******************************************************************************/ - -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_execute_control_method); - - /* Verify that there is a method associated with this object */ - - info->obj_desc = acpi_ns_get_attached_object(info->node); - if (!info->obj_desc) { - ACPI_ERROR((AE_INFO, "No attached method object")); - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - ACPI_DUMP_PATHNAME(info->node, "Execute Method:", - ACPI_LV_INFO, _COMPONENT); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", - info->obj_desc->method.aml_start + 1, - info->obj_desc->method.aml_length - 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. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Verify that there is a method object associated with this node */ - /* - * 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); - } + info->obj_desc = + acpi_ns_get_attached_object(info->resolved_node); + if (!info->obj_desc) { + ACPI_ERROR((AE_INFO, + "Control method has no attached sub-object")); + return_ACPI_STATUS(AE_NULL_OBJECT); + } - status = acpi_ps_execute_method(info); - acpi_ex_exit_interpreter(); + ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_LV_INFO, _COMPONENT); - return_ACPI_STATUS(status); -} + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Method at AML address %p Length %X\n", + info->obj_desc->method.aml_start + 1, + info->obj_desc->method.aml_length - 1)); -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_object_value - * - * PARAMETERS: Info - Method info block, contains: - * Node - Object's NS node - * return_object - Where to put object value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Return the current value of the object - * - * MUTEX: Assumes namespace is locked, leaves namespace unlocked - * - ******************************************************************************/ + /* + * 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. + * + * 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); + } -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) -{ - acpi_status status = AE_OK; - struct acpi_namespace_node *resolved_node = info->node; + status = acpi_ps_execute_method(info); + acpi_ex_exit_interpreter(); + } else { + /* + * 2) Object is not a method, return its current value + */ - ACPI_FUNCTION_TRACE(ns_get_object_value); + /* + * Objects require additional resolution steps (e.g., the Node may be + * a field that must be read, etc.) -- we can't just grab the object + * out of the node. + * + * Use resolve_node_to_value() to get the associated value. + * + * NOTE: we can get away with passing in NULL for a walk state because + * resolved_node is guaranteed to not be a reference to either a method + * local or a method argument (because this interface is never called + * from a running method.) + * + * Even though we do not directly invoke the interpreter for object + * resolution, we must lock it because we could access an opregion. + * The opregion access code assumes that the interpreter is locked. + */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* - * Objects require additional resolution steps (e.g., the Node may be a - * field that must be read, etc.) -- we can't just grab the object out of - * the node. - */ + /* Function has a strange interface */ - /* - * Use resolve_node_to_value() to get the associated value. This call always - * deletes obj_desc (allocated above). - * - * NOTE: we can get away with passing in NULL for a walk state because - * obj_desc is guaranteed to not be a reference to either a method local or - * a method argument (because this interface can only be called from the - * acpi_evaluate external interface, never called from a running method.) - * - * Even though we do not directly invoke the interpreter for this, we must - * enter it because we could access an opregion. The opregion access code - * assumes that the interpreter is locked. - * - * We must release the namespace lock before entering the intepreter. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + status = + acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_exit_interpreter(); - status = acpi_ex_enter_interpreter(); - if (ACPI_SUCCESS(status)) { - status = acpi_ex_resolve_node_to_value(&resolved_node, NULL); /* * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed * in resolved_node. */ - acpi_ex_exit_interpreter(); - if (ACPI_SUCCESS(status)) { status = AE_CTRL_RETURN_VALUE; - info->return_object = ACPI_CAST_PTR - (union acpi_operand_object, resolved_node); + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, + info->resolved_node); + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returning object %p [%s]\n", info->return_object, @@ -485,7 +211,30 @@ static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) } } - /* Namespace is unlocked */ + /* + * Check if there is a return value that must be dealt with + */ + if (status == AE_CTRL_RETURN_VALUE) { + + /* If caller does not want the return value, delete it */ + if (info->flags & ACPI_IGNORE_RETURN_VALUE) { + acpi_ut_remove_reference(info->return_object); + info->return_object = NULL; + } + + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + status = AE_OK; + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", + info->pathname)); + + /* + * Namespace was unlocked by the handling acpi_ns* function, so we + * just return + */ return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index bf1d8dbc0b86..1c9ca6e05314 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -154,7 +154,16 @@ acpi_status acpi_ns_initialize_devices(void) ACPI_UINT32_MAX, FALSE, acpi_ns_find_ini_methods, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + goto error_exit; + } + + /* Allocate the evaluation information block */ + + info.evaluate_info = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info.evaluate_info) { + status = AE_NO_MEMORY; + goto error_exit; } /* Walk namespace to execute all _INIs on present devices */ @@ -162,8 +171,10 @@ acpi_status acpi_ns_initialize_devices(void) status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); + + ACPI_FREE(info.evaluate_info); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); + goto error_exit; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -171,6 +182,10 @@ acpi_status acpi_ns_initialize_devices(void) info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); + + error_exit: + ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -398,9 +413,9 @@ static acpi_status acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { - struct acpi_device_walk_info *info = + struct acpi_device_walk_info *walk_info = ACPI_CAST_PTR(struct acpi_device_walk_info, context); - struct acpi_parameter_info pinfo; + struct acpi_evaluate_info *info = walk_info->evaluate_info; u32 flags; acpi_status status; struct acpi_namespace_node *device_node; @@ -460,7 +475,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, * other words, the device is present, ..., and functioning)" */ if (flags != ACPI_UINT32_MAX) { - info->num_STA++; + walk_info->num_STA++; } /* @@ -516,20 +531,16 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - pinfo.node = device_node; - pinfo.parameters = NULL; - pinfo.parameter_type = ACPI_PARAM_ARGS; + info->prefix_node = device_node; + info->pathname = METHOD_NAME__INI; + info->parameters = NULL; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; - status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo); + status = acpi_ns_evaluate(info); if (ACPI_SUCCESS(status)) { + walk_info->num_INI++; - /* Delete any return object (especially if implicit_return is enabled) */ - - if (pinfo.return_object) { - acpi_ut_remove_reference(pinfo.return_object); - } - - info->num_INI++; if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); @@ -540,20 +551,24 @@ acpi_ns_init_one_device(acpi_handle obj_handle, /* Ignore error and move on to next device */ - char *scope_name = acpi_ns_get_external_pathname(pinfo.node); + char *scope_name = + acpi_ns_get_external_pathname(info->resolved_node); ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", scope_name)); ACPI_FREE(scope_name); + status = AE_OK; } #endif - /* If an external initialization handler is present, call it */ - + /* + * The _INI method has been run if present; call the Global Initialization + * Handler for this device. + */ if (acpi_gbl_init_handler) { status = - acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); + acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); } - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index d2473476afa5..500e2bbcfaf7 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -56,16 +56,16 @@ acpi_ns_search_parent_tree(u32 target_name, /******************************************************************************* * - * FUNCTION: acpi_ns_search_node + * FUNCTION: acpi_ns_search_one_scope * * PARAMETERS: target_name - Ascii ACPI name to search for - * Node - Starting node where search will begin + * parent_node - Starting node where search will begin * Type - Object type to match * return_node - Where the matched Named obj is returned * * RETURN: Status * - * DESCRIPTION: Search a single level of the namespace. Performs a + * DESCRIPTION: Search a single level of the namespace. Performs a * simple search of the specified level, and does not add * entries or search parents. * @@ -75,32 +75,37 @@ acpi_ns_search_parent_tree(u32 target_name, * * All namespace searching is linear in this implementation, but * could be easily modified to support any improved search - * algorithm. However, the linear search was chosen for simplicity + * algorithm. However, the linear search was chosen for simplicity * and because the trees are small and the other interpreter * execution overhead is relatively high. * + * Note: CPU execution analysis has shown that the AML interpreter spends + * a very small percentage of its time searching the namespace. Therefore, + * the linear search seems to be sufficient, as there would seem to be + * little value in improving the search. + * ******************************************************************************/ acpi_status -acpi_ns_search_node(u32 target_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **return_node) +acpi_ns_search_one_scope(u32 target_name, + struct acpi_namespace_node *parent_node, + acpi_object_type type, + struct acpi_namespace_node **return_node) { - struct acpi_namespace_node *next_node; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE(ns_search_node); + ACPI_FUNCTION_TRACE(ns_search_one_scope); #ifdef ACPI_DEBUG_OUTPUT if (ACPI_LV_NAMES & acpi_dbg_level) { char *scope_name; - scope_name = acpi_ns_get_external_pathname(node); + scope_name = acpi_ns_get_external_pathname(parent_node); if (scope_name) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, node, ACPI_CAST_PTR(char, - &target_name), + scope_name, parent_node, + ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type))); ACPI_FREE(scope_name); @@ -112,20 +117,20 @@ acpi_ns_search_node(u32 target_name, * Search for name at this namespace level, which is to say that we * must search for the name among the children of this object */ - next_node = node->child; - while (next_node) { + node = parent_node->child; + while (node) { /* Check for match against the name */ - if (next_node->name.integer == target_name) { + if (node->name.integer == target_name) { /* Resolve a control method alias if any */ - if (acpi_ns_get_type(next_node) == + if (acpi_ns_get_type(node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - next_node = + node = ACPI_CAST_PTR(struct acpi_namespace_node, - next_node->object); + node->object); } /* Found matching entry */ @@ -133,12 +138,12 @@ acpi_ns_search_node(u32 target_name, ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(next_node-> - type), - next_node, - acpi_ut_get_node_name(node), node)); + acpi_ut_get_type_name(node->type), + node, + acpi_ut_get_node_name(parent_node), + parent_node)); - *return_node = next_node; + *return_node = node; return_ACPI_STATUS(AE_OK); } @@ -146,7 +151,7 @@ acpi_ns_search_node(u32 target_name, * The last entry in the list points back to the parent, * so a flag is used to indicate the end-of-list */ - if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + if (node->flags & ANOBJ_END_OF_PEER_LIST) { /* Searched entire list, we are done */ @@ -155,7 +160,7 @@ acpi_ns_search_node(u32 target_name, /* Didn't match name, move on to the next peer object */ - next_node = next_node->peer; + node = node->peer; } /* Searched entire namespace level, not found */ @@ -164,7 +169,8 @@ acpi_ns_search_node(u32 target_name, "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type), - acpi_ut_get_node_name(node), node, node->child)); + acpi_ut_get_node_name(parent_node), parent_node, + parent_node->child)); return_ACPI_STATUS(AE_NOT_FOUND); } @@ -181,14 +187,14 @@ acpi_ns_search_node(u32 target_name, * RETURN: Status * * DESCRIPTION: Called when a name has not been found in the current namespace - * level. Before adding it or giving up, ACPI scope rules require + * level. Before adding it or giving up, ACPI scope rules require * searching enclosing scopes in cases identified by acpi_ns_local(). * * "A name is located by finding the matching name in the current * name space, and then in the parent name space. If the parent * name space does not contain the name, the search continues * recursively until either the name is found or the name space - * does not have a parent (the root of the name space). This + * does not have a parent (the root of the name space). This * indicates that the name is not found" (From ACPI Specification, * section 5.3) * @@ -237,11 +243,12 @@ acpi_ns_search_parent_tree(u32 target_name, */ while (parent_node) { /* - * Search parent scope. Use TYPE_ANY because we don't care about the + * Search parent scope. Use TYPE_ANY because we don't care about the * object type at this point, we only care about the existence of - * the actual name we are searching for. Typechecking comes later. + * the actual name we are searching for. Typechecking comes later. */ - status = acpi_ns_search_node(target_name, parent_node, + status = + acpi_ns_search_one_scope(target_name, parent_node, ACPI_TYPE_ANY, return_node); if (ACPI_SUCCESS(status)) { return_ACPI_STATUS(status); @@ -273,7 +280,7 @@ acpi_ns_search_parent_tree(u32 target_name, * RETURN: Status * * DESCRIPTION: Search for a name segment in a single namespace level, - * optionally adding it if it is not found. If the passed + * optionally adding it if it is not found. If the passed * Type is not Any and the type previously stored in the * entry was Any (i.e. unknown), update the stored type. * @@ -332,7 +339,7 @@ acpi_ns_search_and_enter(u32 target_name, /* Try to find the name in the namespace level specified by the caller */ *return_node = ACPI_ENTRY_NOT_FOUND; - status = acpi_ns_search_node(target_name, node, type, return_node); + status = acpi_ns_search_one_scope(target_name, node, type, return_node); if (status != AE_NOT_FOUND) { /* * If we found it AND the request specifies that a find is an error, @@ -348,10 +355,10 @@ acpi_ns_search_and_enter(u32 target_name, } /* - * The name was not found. If we are NOT performing the first pass + * The name was not found. If we are NOT performing the first pass * (name entry) of loading the namespace, search the parent tree (all the * way to the root if necessary.) We don't want to perform the parent - * search when the namespace is actually being loaded. We want to perform + * search when the namespace is actually being loaded. We want to perform * the search when namespace references are being resolved (load pass 2) * and during the execution phase. */ @@ -386,6 +393,9 @@ acpi_ns_search_and_enter(u32 target_name, return_ACPI_STATUS(AE_NO_MEMORY); } #ifdef ACPI_ASL_COMPILER + /* + * Node is an object defined by an External() statement + */ if (flags & ACPI_NS_EXTERNAL) { new_node->flags |= ANOBJ_IS_EXTERNAL; } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index d1d55032b455..aa4e799d9a8c 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -142,8 +142,9 @@ acpi_ns_report_method_error(char *module_name, acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (path) { - status = acpi_ns_get_node_by_path(path, prefix_node, - ACPI_NS_NO_UPSEARCH, &node); + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); if (ACPI_FAILURE(status)) { acpi_os_printf("[Could not get node by pathname]"); } @@ -685,13 +686,9 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) ACPI_FUNCTION_ENTRY(); /* - * Simple implementation. + * Simple implementation */ - if (!handle) { - return (NULL); - } - - if (handle == ACPI_ROOT_OBJECT) { + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { return (acpi_gbl_root_node); } @@ -701,7 +698,7 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) return (NULL); } - return ((struct acpi_namespace_node *)handle); + return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); } /******************************************************************************* @@ -811,12 +808,12 @@ u32 acpi_ns_opens_scope(acpi_object_type type) /******************************************************************************* * - * FUNCTION: acpi_ns_get_node_by_path + * FUNCTION: acpi_ns_get_node * * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The * \ (backslash) and ^ (carat) prefixes, and the * . (period) to separate segments are supported. - * start_node - Root of subtree to be searched, or NS_ALL for the + * prefix_node - Root of subtree to be searched, or NS_ALL for the * root of the name space. If Name is fully * qualified (first s8 is '\'), the passed value * of Scope will not be accessed. @@ -832,24 +829,29 @@ u32 acpi_ns_opens_scope(acpi_object_type type) ******************************************************************************/ acpi_status -acpi_ns_get_node_by_path(char *pathname, - struct acpi_namespace_node *start_node, - u32 flags, struct acpi_namespace_node **return_node) +acpi_ns_get_node(struct acpi_namespace_node *prefix_node, + char *pathname, + u32 flags, struct acpi_namespace_node **return_node) { union acpi_generic_state scope_info; acpi_status status; - char *internal_path = NULL; + char *internal_path; - ACPI_FUNCTION_TRACE_PTR(ns_get_node_by_path, pathname); + ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); - if (pathname) { + if (!pathname) { + *return_node = prefix_node; + if (!prefix_node) { + *return_node = acpi_gbl_root_node; + } + return_ACPI_STATUS(AE_OK); + } - /* Convert path to internal representation */ + /* Convert path to internal representation */ - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + status = acpi_ns_internalize_name(pathname, &internal_path); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Must lock namespace during lookup */ @@ -861,26 +863,23 @@ acpi_ns_get_node_by_path(char *pathname, /* Setup lookup scope (search starting point) */ - scope_info.scope.node = start_node; + scope_info.scope.node = prefix_node; /* Lookup the name in the namespace */ - status = acpi_ns_lookup(&scope_info, internal_path, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - (flags | ACPI_NS_DONT_OPEN_SCOPE), - NULL, return_node); + status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, + return_node); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", - internal_path, - acpi_format_exception(status))); + pathname, acpi_format_exception(status))); } (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); cleanup: - if (internal_path) { - ACPI_FREE(internal_path); - } + ACPI_FREE(internal_path); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 998b29611b19..6d9bd45af30a 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -171,51 +171,61 @@ acpi_evaluate_object(acpi_handle handle, { acpi_status status; acpi_status status2; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; ACPI_FUNCTION_TRACE(acpi_evaluate_object); - info.node = handle; - info.parameters = NULL; - info.return_object = NULL; - info.parameter_type = ACPI_PARAM_ARGS; + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->pathname = pathname; + info->parameter_type = ACPI_PARAM_ARGS; + + /* Convert and validate the device handle */ + + info->prefix_node = acpi_ns_map_handle_to_node(handle); + if (!info->prefix_node) { + status = AE_BAD_PARAMETER; + goto cleanup; + } /* - * If there are parameters to be passed to the object - * (which must be a control method), the external objects - * must be converted to internal objects + * If there are parameters to be passed to a control method, the external + * objects must all be converted to internal objects */ if (external_params && external_params->count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info.parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) - external_params->count + - 1) * sizeof(void *)); - if (!info.parameters) { - return_ACPI_STATUS(AE_NO_MEMORY); + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + external_params-> + count + + 1) * sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; } - /* - * Convert each external object in the list to an - * internal object - */ + /* Convert each external object in the list to an internal object */ + for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], - &info. + &info-> parameters[i]); if (ACPI_FAILURE(status)) { - acpi_ut_delete_internal_object_list(info. - parameters); - return_ACPI_STATUS(status); + goto cleanup; } } - info.parameters[external_params->count] = NULL; + info->parameters[external_params->count] = NULL; } /* @@ -228,12 +238,13 @@ acpi_evaluate_object(acpi_handle handle, /* The path is fully qualified, just evaluate by name */ - status = acpi_ns_evaluate_by_name(pathname, &info); + info->prefix_node = NULL; + status = acpi_ns_evaluate(info); } else if (!handle) { /* - * A handle is optional iff a fully qualified pathname - * is specified. Since we've already handled fully - * qualified names above, this is an error + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error */ if (!pathname) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -246,22 +257,9 @@ acpi_evaluate_object(acpi_handle handle, status = AE_BAD_PARAMETER; } else { - /* - * We get here if we have a handle -- and if we have a - * pathname it is relative. The handle will be validated - * in the lower procedures - */ - if (!pathname) { - /* - * The null pathname case means the handle is for - * the actual object to be evaluated - */ - status = acpi_ns_evaluate_by_handle(&info); - } else { - /* Both a Handle and a relative Pathname */ + /* We have a namespace a node and a possible relative path */ - status = acpi_ns_evaluate_relative(pathname, &info); - } + status = acpi_ns_evaluate(info); } /* @@ -269,10 +267,10 @@ acpi_evaluate_object(acpi_handle handle, * copy the return value to an external object. */ if (return_buffer) { - if (!info.return_object) { + if (!info->return_object) { return_buffer->length = 0; } else { - if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) == + if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that @@ -283,17 +281,16 @@ acpi_evaluate_object(acpi_handle handle, * support for various types at a later date if necessary. */ status = AE_TYPE; - info.return_object = NULL; /* No need to delete a NS Node */ + info->return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { - /* - * Find out how large a buffer is needed - * to contain the returned object - */ + + /* Get the size of the returned object */ + status = - acpi_ut_get_object_size(info.return_object, + acpi_ut_get_object_size(info->return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { @@ -319,7 +316,7 @@ acpi_evaluate_object(acpi_handle handle, status = acpi_ut_copy_iobject_to_eobject - (info.return_object, + (info->return_object, return_buffer); } } @@ -327,31 +324,33 @@ acpi_evaluate_object(acpi_handle handle, } } - if (info.return_object) { + if (info->return_object) { /* - * Delete the internal return object. NOTE: Interpreter - * must be locked to avoid race condition. + * Delete the internal return object. NOTE: Interpreter must be + * locked to avoid race condition. */ status2 = acpi_ex_enter_interpreter(); if (ACPI_SUCCESS(status2)) { - /* - * Delete the internal return object. (Or at least - * decrement the reference count by one) - */ - acpi_ut_remove_reference(info.return_object); + + /* Remove one reference on the return object (should delete it) */ + + acpi_ut_remove_reference(info->return_object); acpi_ex_exit_interpreter(); } } + cleanup: + /* Free the input parameter list (if we created one) */ - if (info.parameters) { + if (info->parameters) { /* Free the allocated parameter block */ - acpi_ut_delete_internal_object_list(info.parameters); + acpi_ut_delete_internal_object_list(info->parameters); } + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 1303e2b062bb..978213a6c19f 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -112,9 +112,8 @@ acpi_get_handle(acpi_handle parent, /* * Find the Node and convert to a handle */ - status = - acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH, - &node); + status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS(status)) { |