diff options
Diffstat (limited to 'drivers/acpi/acpica/nsxfeval.c')
| -rw-r--r-- | drivers/acpi/acpica/nsxfeval.c | 314 | 
1 files changed, 229 insertions, 85 deletions
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index ebef8a7fd70..4bd558bf10d 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,8 @@   * POSSIBILITY OF SUCH DAMAGES.   */ +#define EXPORT_ACPI_INTERFACES +  #include <acpi/acpi.h>  #include "accommon.h"  #include "acnamesp.h" @@ -57,19 +59,19 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);   *   * FUNCTION:    acpi_evaluate_object_typed   * - * PARAMETERS:  Handle              - Object handle (optional) - *              Pathname            - Object pathname (optional) + * PARAMETERS:  handle              - Object handle (optional) + *              pathname            - Object pathname (optional)   *              external_params     - List of parameters to pass to method, - *                                    terminated by NULL.  May be NULL + *                                    terminated by NULL. May be NULL   *                                    if no parameters are being passed.   *              return_buffer       - Where to put method's return value (if - *                                    any).  If NULL, no value is returned. + *                                    any). If NULL, no value is returned.   *              return_type         - Expected type of return object   *   * RETURN:      Status   *   * DESCRIPTION: Find and evaluate the given object, passing the given - *              parameters if necessary.  One of "Handle" or "Pathname" must + *              parameters if necessary. One of "Handle" or "Pathname" must   *              be valid (non-null)   *   ******************************************************************************/ @@ -82,7 +84,7 @@ acpi_evaluate_object_typed(acpi_handle handle,  			   acpi_object_type return_type)  {  	acpi_status status; -	u8 must_free = FALSE; +	u8 free_buffer_on_error = FALSE;  	ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); @@ -93,14 +95,13 @@ acpi_evaluate_object_typed(acpi_handle handle,  	}  	if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { -		must_free = TRUE; +		free_buffer_on_error = TRUE;  	}  	/* Evaluate the object */ -	status = -	    acpi_evaluate_object(handle, pathname, external_params, -				 return_buffer); +	status = acpi_evaluate_object(handle, pathname, +				      external_params, return_buffer);  	if (ACPI_FAILURE(status)) {  		return_ACPI_STATUS(status);  	} @@ -133,11 +134,15 @@ acpi_evaluate_object_typed(acpi_handle handle,  					   pointer)->type),  		    acpi_ut_get_type_name(return_type))); -	if (must_free) { - -		/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - -		ACPI_FREE(return_buffer->pointer); +	if (free_buffer_on_error) { +		/* +		 * Free a buffer created via ACPI_ALLOCATE_BUFFER. +		 * Note: We use acpi_os_free here because acpi_os_allocate was used +		 * to allocate the buffer. This purposefully bypasses the +		 * (optionally enabled) allocation tracking mechanism since we +		 * only want to track internal allocations. +		 */ +		acpi_os_free(return_buffer->pointer);  		return_buffer->pointer = NULL;  	} @@ -151,18 +156,18 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)   *   * FUNCTION:    acpi_evaluate_object   * - * PARAMETERS:  Handle              - Object handle (optional) - *              Pathname            - Object pathname (optional) + * PARAMETERS:  handle              - Object handle (optional) + *              pathname            - Object pathname (optional)   *              external_params     - List of parameters to pass to method, - *                                    terminated by NULL.  May be NULL + *                                    terminated by NULL. May be NULL   *                                    if no parameters are being passed.   *              return_buffer       - Where to put method's return value (if - *                                    any).  If NULL, no value is returned. + *                                    any). If NULL, no value is returned.   *   * RETURN:      Status   *   * DESCRIPTION: Find and evaluate the given object, passing the given - *              parameters if necessary.  One of "Handle" or "Pathname" must + *              parameters if necessary. One of "Handle" or "Pathname" must   *              be valid (non-null)   *   ******************************************************************************/ @@ -186,8 +191,6 @@ acpi_evaluate_object(acpi_handle handle,  		return_ACPI_STATUS(AE_NO_MEMORY);  	} -	info->pathname = pathname; -  	/* Convert and validate the device handle */  	info->prefix_node = acpi_ns_validate_handle(handle); @@ -197,17 +200,64 @@ acpi_evaluate_object(acpi_handle handle,  	}  	/* -	 * If there are parameters to be passed to a control method, the external -	 * objects must all be converted to internal objects +	 * Get the actual namespace node for the target object. +	 * Handles these cases: +	 * +	 * 1) Null node, valid pathname from root (absolute path) +	 * 2) Node and valid pathname (path relative to Node) +	 * 3) Node, Null pathname +	 */ +	if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { + +		/* The path is fully qualified, just evaluate by name */ + +		info->prefix_node = NULL; +	} 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. +		 */ +		if (!pathname) { +			ACPI_DEBUG_PRINT((ACPI_DB_INFO, +					  "Both Handle and Pathname are NULL")); +		} else { +			ACPI_DEBUG_PRINT((ACPI_DB_INFO, +					  "Null Handle with relative pathname [%s]", +					  pathname)); +		} + +		status = AE_BAD_PARAMETER; +		goto cleanup; +	} + +	info->relative_pathname = pathname; + +	/* +	 * Convert all external objects passed as arguments to the +	 * internal version(s).  	 */  	if (external_params && external_params->count) { +		info->param_count = (u16)external_params->count; + +		/* Warn on impossible argument count */ + +		if (info->param_count > ACPI_METHOD_NUM_ARGS) { +			ACPI_WARN_PREDEFINED((AE_INFO, pathname, +					      ACPI_WARN_ALWAYS, +					      "Excess arguments (%u) - using only %u", +					      info->param_count, +					      ACPI_METHOD_NUM_ARGS)); + +			info->param_count = ACPI_METHOD_NUM_ARGS; +		} +  		/*  		 * 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 + +		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> +							 param_count +  							 1) * sizeof(void *));  		if (!info->parameters) {  			status = AE_NO_MEMORY; @@ -216,7 +266,7 @@ acpi_evaluate_object(acpi_handle handle,  		/* Convert each external object in the list to an internal object */ -		for (i = 0; i < external_params->count; i++) { +		for (i = 0; i < info->param_count; i++) {  			status =  			    acpi_ut_copy_eobject_to_iobject(&external_params->  							    pointer[i], @@ -226,43 +276,96 @@ acpi_evaluate_object(acpi_handle handle,  				goto cleanup;  			}  		} -		info->parameters[external_params->count] = NULL; + +		info->parameters[info->param_count] = NULL;  	} +#if 0 +  	/* -	 * Three major cases: -	 * 1) Fully qualified pathname -	 * 2) No handle, not fully qualified pathname (error) -	 * 3) Valid handle +	 * Begin incoming argument count analysis. Check for too few args +	 * and too many args.  	 */ -	if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { -		/* The path is fully qualified, just evaluate by name */ +	switch (acpi_ns_get_type(info->node)) { +	case ACPI_TYPE_METHOD: + +		/* Check incoming argument count against the method definition */ + +		if (info->obj_desc->method.param_count > info->param_count) { +			ACPI_ERROR((AE_INFO, +				    "Insufficient arguments (%u) - %u are required", +				    info->param_count, +				    info->obj_desc->method.param_count)); + +			status = AE_MISSING_ARGUMENTS; +			goto cleanup; +		} + +		else if (info->obj_desc->method.param_count < info->param_count) { +			ACPI_WARNING((AE_INFO, +				      "Excess arguments (%u) - only %u are required", +				      info->param_count, +				      info->obj_desc->method.param_count)); + +			/* Just pass the required number of arguments */ + +			info->param_count = info->obj_desc->method.param_count; +		} -		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 +		 * Any incoming external objects to be passed as arguments to the +		 * method must be converted to internal objects  		 */ -		if (!pathname) { -			ACPI_DEBUG_PRINT((ACPI_DB_INFO, -					  "Both Handle and Pathname are NULL")); -		} else { -			ACPI_DEBUG_PRINT((ACPI_DB_INFO, -					  "Null Handle with relative pathname [%s]", -					  pathname)); +		if (info->param_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) +								 info-> +								 param_count + +								 1) * +								sizeof(void *)); +			if (!info->parameters) { +				status = AE_NO_MEMORY; +				goto cleanup; +			} + +			/* Convert each external object in the list to an internal object */ + +			for (i = 0; i < info->param_count; i++) { +				status = +				    acpi_ut_copy_eobject_to_iobject +				    (&external_params->pointer[i], +				     &info->parameters[i]); +				if (ACPI_FAILURE(status)) { +					goto cleanup; +				} +			} + +			info->parameters[info->param_count] = NULL;  		} +		break; -		status = AE_BAD_PARAMETER; -	} else { -		/* We have a namespace a node and a possible relative path */ +	default: -		status = acpi_ns_evaluate(info); +		/* Warn if arguments passed to an object that is not a method */ + +		if (info->param_count) { +			ACPI_WARNING((AE_INFO, +				      "%u arguments were passed to a non-method ACPI object", +				      info->param_count)); +		} +		break;  	} +#endif + +	/* Now we can evaluate the object */ + +	status = acpi_ns_evaluate(info); +  	/*  	 * If we are expecting a return value, and all went well above,  	 * copy the return value to an external object. @@ -342,7 +445,7 @@ acpi_evaluate_object(acpi_handle handle,  		acpi_ex_exit_interpreter();  	} -      cleanup: +cleanup:  	/* Free the input parameter list (if we created one) */ @@ -363,7 +466,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object)   *   * FUNCTION:    acpi_ns_resolve_references   * - * PARAMETERS:  Info                    - Evaluation info block + * PARAMETERS:  info                    - Evaluation info block   *   * RETURN:      Info->return_object is replaced with the dereferenced object   * @@ -412,6 +515,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)  		break;  	default: +  		return;  	} @@ -430,14 +534,14 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)   *   * FUNCTION:    acpi_walk_namespace   * - * PARAMETERS:  Type                - acpi_object_type to search for + * PARAMETERS:  type                - acpi_object_type to search for   *              start_object        - Handle in namespace where search begins   *              max_depth           - Depth to which search is to reach - *              pre_order_visit     - Called during tree pre-order visit + *              descending_callback - Called during tree descent   *                                    when an object of "Type" is found - *              post_order_visit    - Called during tree post-order visit + *              ascending_callback  - Called during tree ascent   *                                    when an object of "Type" is found - *              Context             - Passed to user function(s) above + *              context             - Passed to user function(s) above   *              return_value        - Location where return value of   *                                    user_function is put if terminated early   * @@ -463,8 +567,8 @@ acpi_status  acpi_walk_namespace(acpi_object_type type,  		    acpi_handle start_object,  		    u32 max_depth, -		    acpi_walk_callback pre_order_visit, -		    acpi_walk_callback post_order_visit, +		    acpi_walk_callback descending_callback, +		    acpi_walk_callback ascending_callback,  		    void *context, void **return_value)  {  	acpi_status status; @@ -474,7 +578,7 @@ acpi_walk_namespace(acpi_object_type type,  	/* Parameter validation */  	if ((type > ACPI_TYPE_LOCAL_MAX) || -	    (!max_depth) || (!pre_order_visit && !post_order_visit)) { +	    (!max_depth) || (!descending_callback && !ascending_callback)) {  		return_ACPI_STATUS(AE_BAD_PARAMETER);  	} @@ -491,7 +595,7 @@ acpi_walk_namespace(acpi_object_type type,  	 */  	status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);  	if (ACPI_FAILURE(status)) { -		return status; +		return_ACPI_STATUS(status);  	}  	/* @@ -505,14 +609,22 @@ acpi_walk_namespace(acpi_object_type type,  		goto unlock_and_exit;  	} +	/* Now we can validate the starting node */ + +	if (!acpi_ns_validate_handle(start_object)) { +		status = AE_BAD_PARAMETER; +		goto unlock_and_exit2; +	} +  	status = acpi_ns_walk_namespace(type, start_object, max_depth, -					ACPI_NS_WALK_UNLOCK, pre_order_visit, -					post_order_visit, context, -					return_value); +					ACPI_NS_WALK_UNLOCK, +					descending_callback, ascending_callback, +					context, return_value); +unlock_and_exit2:  	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -      unlock_and_exit: +unlock_and_exit:  	(void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);  	return_ACPI_STATUS(status);  } @@ -541,8 +653,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,  	acpi_status status;  	struct acpi_namespace_node *node;  	u32 flags; -	struct acpica_device_id *hid; -	struct acpica_device_id_list *cid; +	struct acpi_pnp_device_id *hid; +	struct acpi_pnp_device_id_list *cid;  	u32 i;  	u8 found;  	int no_match; @@ -601,17 +713,22 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,  			/* Walk the CID list */ -			found = 0; +			found = FALSE;  			for (i = 0; i < cid->count; i++) {  				if (ACPI_STRCMP(cid->ids[i].string, info->hid)  				    == 0) { -					found = 1; + +					/* Found a matching CID */ + +					found = TRUE;  					break;  				}  			} +  			ACPI_FREE(cid); -			if (!found) +			if (!found) {  				return (AE_OK); +			}  		}  	} @@ -645,7 +762,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,   *   * PARAMETERS:  HID                 - HID to search for. Can be NULL.   *              user_function       - Called when a matching object is found - *              Context             - Passed to user function + *              context             - Passed to user function   *              return_value        - Location where return value of   *                                    user_function is put if terminated early   * @@ -655,7 +772,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,   * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,   *              starting (and ending) at the object specified by start_handle.   *              The user_function is called whenever an object of type - *              Device is found.  If the user function returns + *              Device is found. If the user function returns   *              a non-zero value, the search is terminated immediately and this   *              value is returned to the caller.   * @@ -715,8 +832,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_devices)   * FUNCTION:    acpi_attach_data   *   * PARAMETERS:  obj_handle          - Namespace node - *              Handler             - Handler for this attachment - *              Data                - Pointer to data to be attached + *              handler             - Handler for this attachment + *              data                - Pointer to data to be attached   *   * RETURN:      Status   * @@ -751,7 +868,7 @@ acpi_attach_data(acpi_handle obj_handle,  	status = acpi_ns_attach_data(node, handler, data); -      unlock_and_exit: +unlock_and_exit:  	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return (status);  } @@ -763,7 +880,7 @@ ACPI_EXPORT_SYMBOL(acpi_attach_data)   * FUNCTION:    acpi_detach_data   *   * PARAMETERS:  obj_handle          - Namespace node handle - *              Handler             - Handler used in call to acpi_attach_data + *              handler             - Handler used in call to acpi_attach_data   *   * RETURN:      Status   * @@ -797,7 +914,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)  	status = acpi_ns_detach_data(node, handler); -      unlock_and_exit: +unlock_and_exit:  	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return (status);  } @@ -806,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data)  /*******************************************************************************   * - * FUNCTION:    acpi_get_data + * FUNCTION:    acpi_get_data_full   *   * PARAMETERS:  obj_handle          - Namespace node - *              Handler             - Handler used in call to attach_data - *              Data                - Where the data is returned + *              handler             - Handler used in call to attach_data + *              data                - Where the data is returned + *              callback            - function to execute before returning   *   * RETURN:      Status   * - * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * DESCRIPTION: Retrieve data that was previously attached to a namespace node + *              and execute a callback before returning.   *   ******************************************************************************/  acpi_status -acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler, +		   void **data, void (*callback)(void *))  {  	struct acpi_namespace_node *node;  	acpi_status status; @@ -843,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)  	}  	status = acpi_ns_get_attached_data(node, handler, data); +	if (ACPI_SUCCESS(status) && callback) { +		callback(*data); +	} -      unlock_and_exit: +unlock_and_exit:  	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);  	return (status);  } +ACPI_EXPORT_SYMBOL(acpi_get_data_full) + +/******************************************************************************* + * + * FUNCTION:    acpi_get_data + * + * PARAMETERS:  obj_handle          - Namespace node + *              handler             - Handler used in call to attach_data + *              data                - Where the data is returned + * + * RETURN:      Status + * + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. + * + ******************************************************************************/ +acpi_status +acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) +{ +	return acpi_get_data_full(obj_handle, handler, data, NULL); +} +  ACPI_EXPORT_SYMBOL(acpi_get_data)  | 
