xref: /openbmc/linux/drivers/acpi/acpica/nsinit.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: nsinit - namespace initialization
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acnamesp.h"
13e2f7a777SLen Brown #include "acdispat.h"
14e2f7a777SLen Brown #include "acinterp.h"
15ced04366SLv Zheng #include "acevents.h"
1695b482a8SLen Brown 
1795b482a8SLen Brown #define _COMPONENT          ACPI_NAMESPACE
1895b482a8SLen Brown ACPI_MODULE_NAME("nsinit")
1995b482a8SLen Brown 
2095b482a8SLen Brown /* Local prototypes */
2195b482a8SLen Brown static acpi_status
2295b482a8SLen Brown acpi_ns_init_one_object(acpi_handle obj_handle,
2395b482a8SLen Brown 			u32 level, void *context, void **return_value);
2495b482a8SLen Brown 
2595b482a8SLen Brown static acpi_status
2695b482a8SLen Brown acpi_ns_init_one_device(acpi_handle obj_handle,
2795b482a8SLen Brown 			u32 nesting_level, void *context, void **return_value);
2895b482a8SLen Brown 
2995b482a8SLen Brown static acpi_status
3095b482a8SLen Brown acpi_ns_find_ini_methods(acpi_handle obj_handle,
3195b482a8SLen Brown 			 u32 nesting_level, void *context, void **return_value);
3295b482a8SLen Brown 
3395b482a8SLen Brown /*******************************************************************************
3495b482a8SLen Brown  *
3595b482a8SLen Brown  * FUNCTION:    acpi_ns_initialize_objects
3695b482a8SLen Brown  *
3795b482a8SLen Brown  * PARAMETERS:  None
3895b482a8SLen Brown  *
3995b482a8SLen Brown  * RETURN:      Status
4095b482a8SLen Brown  *
4195b482a8SLen Brown  * DESCRIPTION: Walk the entire namespace and perform any necessary
4295b482a8SLen Brown  *              initialization on the objects found therein
4395b482a8SLen Brown  *
4495b482a8SLen Brown  ******************************************************************************/
4595b482a8SLen Brown 
acpi_ns_initialize_objects(void)4695b482a8SLen Brown acpi_status acpi_ns_initialize_objects(void)
4795b482a8SLen Brown {
4895b482a8SLen Brown 	acpi_status status;
4995b482a8SLen Brown 	struct acpi_init_walk_info info;
5095b482a8SLen Brown 
5195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ns_initialize_objects);
5295b482a8SLen Brown 
535508df89SLv Zheng 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
545508df89SLv Zheng 			  "[Init] Completing Initialization of ACPI Objects\n"));
5595b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
5695b482a8SLen Brown 			  "**** Starting initialization of namespace objects ****\n"));
5795b482a8SLen Brown 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
5886a33cf3SBob Moore 			      "Final data object initialization: "));
5995b482a8SLen Brown 
6086a33cf3SBob Moore 	/* Clear the info block */
6195b482a8SLen Brown 
624fa4616eSBob Moore 	memset(&info, 0, sizeof(struct acpi_init_walk_info));
6395b482a8SLen Brown 
6495b482a8SLen Brown 	/* Walk entire namespace from the supplied root */
6595b482a8SLen Brown 
6686a33cf3SBob Moore 	/*
6786a33cf3SBob Moore 	 * TBD: will become ACPI_TYPE_PACKAGE as this type object
6886a33cf3SBob Moore 	 * is now the only one that supports deferred initialization
6986a33cf3SBob Moore 	 * (forward references).
7086a33cf3SBob Moore 	 */
7195b482a8SLen Brown 	status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
721f86e8c1SLv Zheng 				     ACPI_UINT32_MAX, acpi_ns_init_one_object,
731f86e8c1SLv Zheng 				     NULL, &info, NULL);
7495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
7595b482a8SLen Brown 		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
7695b482a8SLen Brown 	}
7795b482a8SLen Brown 
7895b482a8SLen Brown 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
7986a33cf3SBob Moore 			      "Namespace contains %u (0x%X) objects\n",
8086a33cf3SBob Moore 			      info.object_count, info.object_count));
8195b482a8SLen Brown 
8295b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
8322b5afceSBob Moore 			  "%u Control Methods found\n%u Op Regions found\n",
8422b5afceSBob Moore 			  info.method_count, info.op_region_count));
8595b482a8SLen Brown 
8695b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
8795b482a8SLen Brown }
8895b482a8SLen Brown 
8995b482a8SLen Brown /*******************************************************************************
9095b482a8SLen Brown  *
9195b482a8SLen Brown  * FUNCTION:    acpi_ns_initialize_devices
9295b482a8SLen Brown  *
9395b482a8SLen Brown  * PARAMETERS:  None
9495b482a8SLen Brown  *
9595b482a8SLen Brown  * RETURN:      acpi_status
9695b482a8SLen Brown  *
9795b482a8SLen Brown  * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
9895b482a8SLen Brown  *              This means running _INI on all present devices.
9995b482a8SLen Brown  *
10095b482a8SLen Brown  *              Note: We install PCI config space handler on region access,
10195b482a8SLen Brown  *              not here.
10295b482a8SLen Brown  *
10395b482a8SLen Brown  ******************************************************************************/
10495b482a8SLen Brown 
acpi_ns_initialize_devices(u32 flags)105ced04366SLv Zheng acpi_status acpi_ns_initialize_devices(u32 flags)
10695b482a8SLen Brown {
107ebc3c9bbSLv Zheng 	acpi_status status = AE_OK;
10895b482a8SLen Brown 	struct acpi_device_walk_info info;
1092d3349deSLv Zheng 	acpi_handle handle;
11095b482a8SLen Brown 
11195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ns_initialize_devices);
11295b482a8SLen Brown 
113ced04366SLv Zheng 	if (!(flags & ACPI_NO_DEVICE_INIT)) {
114ced04366SLv Zheng 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
115ced04366SLv Zheng 				  "[Init] Initializing ACPI Devices\n"));
116ced04366SLv Zheng 
11795b482a8SLen Brown 		/* Init counters */
11895b482a8SLen Brown 
11995b482a8SLen Brown 		info.device_count = 0;
12095b482a8SLen Brown 		info.num_STA = 0;
12195b482a8SLen Brown 		info.num_INI = 0;
12295b482a8SLen Brown 
12395b482a8SLen Brown 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
124d4913dc6SBob Moore 				      "Initializing Device/Processor/Thermal objects "
1253e5621a7SBob Moore 				      "and executing _INI/_STA methods:\n"));
12695b482a8SLen Brown 
12795b482a8SLen Brown 		/* Tree analysis: find all subtrees that contain _INI methods */
12895b482a8SLen Brown 
12995b482a8SLen Brown 		status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
13095b482a8SLen Brown 						ACPI_UINT32_MAX, FALSE,
131ced04366SLv Zheng 						acpi_ns_find_ini_methods, NULL,
132ced04366SLv Zheng 						&info, NULL);
13395b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
13495b482a8SLen Brown 			goto error_exit;
13595b482a8SLen Brown 		}
13695b482a8SLen Brown 
13795b482a8SLen Brown 		/* Allocate the evaluation information block */
13895b482a8SLen Brown 
13995b482a8SLen Brown 		info.evaluate_info =
14095b482a8SLen Brown 		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
14195b482a8SLen Brown 		if (!info.evaluate_info) {
14295b482a8SLen Brown 			status = AE_NO_MEMORY;
14395b482a8SLen Brown 			goto error_exit;
14495b482a8SLen Brown 		}
14595b482a8SLen Brown 
1469e64155eSBob Moore 		/*
147ced04366SLv Zheng 		 * Execute the "global" _INI method that may appear at the root.
148ced04366SLv Zheng 		 * This support is provided for Windows compatibility (Vista+) and
149ced04366SLv Zheng 		 * is not part of the ACPI specification.
1509e64155eSBob Moore 		 */
1519e64155eSBob Moore 		info.evaluate_info->prefix_node = acpi_gbl_root_node;
15229a241ccSBob Moore 		info.evaluate_info->relative_pathname = METHOD_NAME__INI;
1539e64155eSBob Moore 		info.evaluate_info->parameters = NULL;
1549e64155eSBob Moore 		info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
1559e64155eSBob Moore 
1569e64155eSBob Moore 		status = acpi_ns_evaluate(info.evaluate_info);
1579e64155eSBob Moore 		if (ACPI_SUCCESS(status)) {
1589e64155eSBob Moore 			info.num_INI++;
1599e64155eSBob Moore 		}
1602d3349deSLv Zheng 
1612d3349deSLv Zheng 		/*
1622d3349deSLv Zheng 		 * Execute \_SB._INI.
1632d3349deSLv Zheng 		 * There appears to be a strict order requirement for \_SB._INI,
1642d3349deSLv Zheng 		 * which should be evaluated before any _REG evaluations.
1652d3349deSLv Zheng 		 */
1662d3349deSLv Zheng 		status = acpi_get_handle(NULL, "\\_SB", &handle);
1672d3349deSLv Zheng 		if (ACPI_SUCCESS(status)) {
1682d3349deSLv Zheng 			memset(info.evaluate_info, 0,
1692d3349deSLv Zheng 			       sizeof(struct acpi_evaluate_info));
1702d3349deSLv Zheng 			info.evaluate_info->prefix_node = handle;
1712d3349deSLv Zheng 			info.evaluate_info->relative_pathname =
1722d3349deSLv Zheng 			    METHOD_NAME__INI;
1732d3349deSLv Zheng 			info.evaluate_info->parameters = NULL;
1742d3349deSLv Zheng 			info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
1752d3349deSLv Zheng 
1762d3349deSLv Zheng 			status = acpi_ns_evaluate(info.evaluate_info);
1772d3349deSLv Zheng 			if (ACPI_SUCCESS(status)) {
1782d3349deSLv Zheng 				info.num_INI++;
1792d3349deSLv Zheng 			}
1802d3349deSLv Zheng 		}
181ced04366SLv Zheng 	}
182ced04366SLv Zheng 
183ced04366SLv Zheng 	/*
184ced04366SLv Zheng 	 * Run all _REG methods
185ced04366SLv Zheng 	 *
186ced04366SLv Zheng 	 * Note: Any objects accessed by the _REG methods will be automatically
187ced04366SLv Zheng 	 * initialized, even if they contain executable AML (see the call to
188ced04366SLv Zheng 	 * acpi_ns_initialize_objects below).
1892d3349deSLv Zheng 	 *
1902d3349deSLv Zheng 	 * Note: According to the ACPI specification, we actually needn't execute
1912d3349deSLv Zheng 	 * _REG for system_memory/system_io operation regions, but for PCI_Config
1922d3349deSLv Zheng 	 * operation regions, it is required to evaluate _REG for those on a PCI
1932d3349deSLv Zheng 	 * root bus that doesn't contain _BBN object. So this code is kept here
1942d3349deSLv Zheng 	 * in order not to break things.
195ced04366SLv Zheng 	 */
196ced04366SLv Zheng 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
197ced04366SLv Zheng 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
198ced04366SLv Zheng 				  "[Init] Executing _REG OpRegion methods\n"));
199ced04366SLv Zheng 
200ced04366SLv Zheng 		status = acpi_ev_initialize_op_regions();
201ced04366SLv Zheng 		if (ACPI_FAILURE(status)) {
202ced04366SLv Zheng 			goto error_exit;
203ced04366SLv Zheng 		}
204ced04366SLv Zheng 	}
205ced04366SLv Zheng 
206ced04366SLv Zheng 	if (!(flags & ACPI_NO_DEVICE_INIT)) {
2079e64155eSBob Moore 
20895b482a8SLen Brown 		/* Walk namespace to execute all _INIs on present devices */
20995b482a8SLen Brown 
21095b482a8SLen Brown 		status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
21195b482a8SLen Brown 						ACPI_UINT32_MAX, FALSE,
212ced04366SLv Zheng 						acpi_ns_init_one_device, NULL,
213ced04366SLv Zheng 						&info, NULL);
21495b482a8SLen Brown 
215b681f7d9SMatthew Garrett 		/*
216b681f7d9SMatthew Garrett 		 * Any _OSI requests should be completed by now. If the BIOS has
217b681f7d9SMatthew Garrett 		 * requested any Windows OSI strings, we will always truncate
218b681f7d9SMatthew Garrett 		 * I/O addresses to 16 bits -- for Windows compatibility.
219b681f7d9SMatthew Garrett 		 */
220b681f7d9SMatthew Garrett 		if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
221b681f7d9SMatthew Garrett 			acpi_gbl_truncate_io_addresses = TRUE;
222b681f7d9SMatthew Garrett 		}
223b681f7d9SMatthew Garrett 
22495b482a8SLen Brown 		ACPI_FREE(info.evaluate_info);
22595b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
22695b482a8SLen Brown 			goto error_exit;
22795b482a8SLen Brown 		}
22895b482a8SLen Brown 
22995b482a8SLen Brown 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
2302fae3e56SBob Moore 				      "    Executed %u _INI methods requiring %u _STA executions "
2315821f754SBob Moore 				      "(examined %u objects)\n",
232ced04366SLv Zheng 				      info.num_INI, info.num_STA,
233ced04366SLv Zheng 				      info.device_count));
234ced04366SLv Zheng 	}
23595b482a8SLen Brown 
23695b482a8SLen Brown 	return_ACPI_STATUS(status);
23795b482a8SLen Brown 
23895b482a8SLen Brown error_exit:
23995b482a8SLen Brown 	ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
24095b482a8SLen Brown 	return_ACPI_STATUS(status);
24195b482a8SLen Brown }
24295b482a8SLen Brown 
24395b482a8SLen Brown /*******************************************************************************
24495b482a8SLen Brown  *
2457b34c0fbSBob Moore  * FUNCTION:    acpi_ns_init_one_package
2467b34c0fbSBob Moore  *
2477b34c0fbSBob Moore  * PARAMETERS:  obj_handle      - Node
2487b34c0fbSBob Moore  *              level           - Current nesting level
2497b34c0fbSBob Moore  *              context         - Not used
2507b34c0fbSBob Moore  *              return_value    - Not used
2517b34c0fbSBob Moore  *
2527b34c0fbSBob Moore  * RETURN:      Status
2537b34c0fbSBob Moore  *
2547b34c0fbSBob Moore  * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package
2557b34c0fbSBob Moore  *              within the namespace. Used during dynamic load of an SSDT.
2567b34c0fbSBob Moore  *
2577b34c0fbSBob Moore  ******************************************************************************/
2587b34c0fbSBob Moore 
2597b34c0fbSBob Moore acpi_status
acpi_ns_init_one_package(acpi_handle obj_handle,u32 level,void * context,void ** return_value)2607b34c0fbSBob Moore acpi_ns_init_one_package(acpi_handle obj_handle,
2617b34c0fbSBob Moore 			 u32 level, void *context, void **return_value)
2627b34c0fbSBob Moore {
2637b34c0fbSBob Moore 	acpi_status status;
2647b34c0fbSBob Moore 	union acpi_operand_object *obj_desc;
2657b34c0fbSBob Moore 	struct acpi_namespace_node *node =
2667b34c0fbSBob Moore 	    (struct acpi_namespace_node *)obj_handle;
2677b34c0fbSBob Moore 
2687b34c0fbSBob Moore 	obj_desc = acpi_ns_get_attached_object(node);
2697b34c0fbSBob Moore 	if (!obj_desc) {
2707b34c0fbSBob Moore 		return (AE_OK);
2717b34c0fbSBob Moore 	}
2727b34c0fbSBob Moore 
2737b34c0fbSBob Moore 	/* Exit if package is already initialized */
2747b34c0fbSBob Moore 
2757b34c0fbSBob Moore 	if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {
2767b34c0fbSBob Moore 		return (AE_OK);
2777b34c0fbSBob Moore 	}
2787b34c0fbSBob Moore 
2797b34c0fbSBob Moore 	status = acpi_ds_get_package_arguments(obj_desc);
2807b34c0fbSBob Moore 	if (ACPI_FAILURE(status)) {
2817b34c0fbSBob Moore 		return (AE_OK);
2827b34c0fbSBob Moore 	}
2837b34c0fbSBob Moore 
2847b34c0fbSBob Moore 	status =
2857b34c0fbSBob Moore 	    acpi_ut_walk_package_tree(obj_desc, NULL,
2867b34c0fbSBob Moore 				      acpi_ds_init_package_element, NULL);
2877b34c0fbSBob Moore 	if (ACPI_FAILURE(status)) {
2887b34c0fbSBob Moore 		return (AE_OK);
2897b34c0fbSBob Moore 	}
2907b34c0fbSBob Moore 
2917b34c0fbSBob Moore 	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
2927b34c0fbSBob Moore 	return (AE_OK);
2937b34c0fbSBob Moore }
2947b34c0fbSBob Moore 
2957b34c0fbSBob Moore /*******************************************************************************
2967b34c0fbSBob Moore  *
29795b482a8SLen Brown  * FUNCTION:    acpi_ns_init_one_object
29895b482a8SLen Brown  *
29995b482a8SLen Brown  * PARAMETERS:  obj_handle      - Node
300ba494beeSBob Moore  *              level           - Current nesting level
301ba494beeSBob Moore  *              context         - Points to a init info struct
30295b482a8SLen Brown  *              return_value    - Not used
30395b482a8SLen Brown  *
30495b482a8SLen Brown  * RETURN:      Status
30595b482a8SLen Brown  *
30695b482a8SLen Brown  * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
30795b482a8SLen Brown  *              within the namespace.
30895b482a8SLen Brown  *
30995b482a8SLen Brown  *              Currently, the only objects that require initialization are:
31095b482a8SLen Brown  *              1) Methods
31195b482a8SLen Brown  *              2) Op Regions
31295b482a8SLen Brown  *
31395b482a8SLen Brown  ******************************************************************************/
31495b482a8SLen Brown 
31595b482a8SLen Brown static acpi_status
acpi_ns_init_one_object(acpi_handle obj_handle,u32 level,void * context,void ** return_value)31695b482a8SLen Brown acpi_ns_init_one_object(acpi_handle obj_handle,
31795b482a8SLen Brown 			u32 level, void *context, void **return_value)
31895b482a8SLen Brown {
31995b482a8SLen Brown 	acpi_object_type type;
32095b482a8SLen Brown 	acpi_status status = AE_OK;
32195b482a8SLen Brown 	struct acpi_init_walk_info *info =
32295b482a8SLen Brown 	    (struct acpi_init_walk_info *)context;
32395b482a8SLen Brown 	struct acpi_namespace_node *node =
32495b482a8SLen Brown 	    (struct acpi_namespace_node *)obj_handle;
32595b482a8SLen Brown 	union acpi_operand_object *obj_desc;
32695b482a8SLen Brown 
32795b482a8SLen Brown 	ACPI_FUNCTION_NAME(ns_init_one_object);
32895b482a8SLen Brown 
32995b482a8SLen Brown 	info->object_count++;
33095b482a8SLen Brown 
33195b482a8SLen Brown 	/* And even then, we are only interested in a few object types */
33295b482a8SLen Brown 
33395b482a8SLen Brown 	type = acpi_ns_get_type(obj_handle);
33495b482a8SLen Brown 	obj_desc = acpi_ns_get_attached_object(node);
33595b482a8SLen Brown 	if (!obj_desc) {
33695b482a8SLen Brown 		return (AE_OK);
33795b482a8SLen Brown 	}
33895b482a8SLen Brown 
33995b482a8SLen Brown 	/* Increment counters for object types we are looking for */
34095b482a8SLen Brown 
34195b482a8SLen Brown 	switch (type) {
34295b482a8SLen Brown 	case ACPI_TYPE_REGION:
3431d1ea1b7SChao Guan 
34495b482a8SLen Brown 		info->op_region_count++;
34595b482a8SLen Brown 		break;
34695b482a8SLen Brown 
34795b482a8SLen Brown 	case ACPI_TYPE_BUFFER_FIELD:
3481d1ea1b7SChao Guan 
34995b482a8SLen Brown 		info->field_count++;
35095b482a8SLen Brown 		break;
35195b482a8SLen Brown 
35295b482a8SLen Brown 	case ACPI_TYPE_LOCAL_BANK_FIELD:
3531d1ea1b7SChao Guan 
35495b482a8SLen Brown 		info->field_count++;
35595b482a8SLen Brown 		break;
35695b482a8SLen Brown 
35795b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
3581d1ea1b7SChao Guan 
35995b482a8SLen Brown 		info->buffer_count++;
36095b482a8SLen Brown 		break;
36195b482a8SLen Brown 
36295b482a8SLen Brown 	case ACPI_TYPE_PACKAGE:
3631d1ea1b7SChao Guan 
36495b482a8SLen Brown 		info->package_count++;
36595b482a8SLen Brown 		break;
36695b482a8SLen Brown 
36795b482a8SLen Brown 	default:
36895b482a8SLen Brown 
36995b482a8SLen Brown 		/* No init required, just exit now */
3701d1ea1b7SChao Guan 
37195b482a8SLen Brown 		return (AE_OK);
37295b482a8SLen Brown 	}
37395b482a8SLen Brown 
374d4913dc6SBob Moore 	/* If the object is already initialized, nothing else to do */
375d4913dc6SBob Moore 
37695b482a8SLen Brown 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
37795b482a8SLen Brown 		return (AE_OK);
37895b482a8SLen Brown 	}
37995b482a8SLen Brown 
380d4913dc6SBob Moore 	/* Must lock the interpreter before executing AML code */
381d4913dc6SBob Moore 
38295b482a8SLen Brown 	acpi_ex_enter_interpreter();
38395b482a8SLen Brown 
38495b482a8SLen Brown 	/*
38586a33cf3SBob Moore 	 * Only initialization of Package objects can be deferred, in order
38686a33cf3SBob Moore 	 * to support forward references.
38795b482a8SLen Brown 	 */
38895b482a8SLen Brown 	switch (type) {
38995b482a8SLen Brown 	case ACPI_TYPE_LOCAL_BANK_FIELD:
39095b482a8SLen Brown 
39186a33cf3SBob Moore 		/* TBD: bank_fields do not require deferred init, remove this code */
39286a33cf3SBob Moore 
39395b482a8SLen Brown 		info->field_init++;
39495b482a8SLen Brown 		status = acpi_ds_get_bank_field_arguments(obj_desc);
39595b482a8SLen Brown 		break;
39695b482a8SLen Brown 
39795b482a8SLen Brown 	case ACPI_TYPE_PACKAGE:
39895b482a8SLen Brown 
3997b34c0fbSBob Moore 		/* Complete the initialization/resolution of the package object */
4007b34c0fbSBob Moore 
40195b482a8SLen Brown 		info->package_init++;
4027b34c0fbSBob Moore 		status =
4037b34c0fbSBob Moore 		    acpi_ns_init_one_package(obj_handle, level, NULL, NULL);
40495b482a8SLen Brown 		break;
40595b482a8SLen Brown 
40695b482a8SLen Brown 	default:
4071d1ea1b7SChao Guan 
40886a33cf3SBob Moore 		/* No other types should get here */
4091d1ea1b7SChao Guan 
41086a33cf3SBob Moore 		status = AE_TYPE;
41186a33cf3SBob Moore 		ACPI_EXCEPTION((AE_INFO, status,
41286a33cf3SBob Moore 				"Opcode is not deferred [%4.4s] (%s)",
41386a33cf3SBob Moore 				acpi_ut_get_node_name(node),
41486a33cf3SBob Moore 				acpi_ut_get_type_name(type)));
41595b482a8SLen Brown 		break;
41695b482a8SLen Brown 	}
41795b482a8SLen Brown 
41895b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
41995b482a8SLen Brown 		ACPI_EXCEPTION((AE_INFO, status,
42095b482a8SLen Brown 				"Could not execute arguments for [%4.4s] (%s)",
42195b482a8SLen Brown 				acpi_ut_get_node_name(node),
42295b482a8SLen Brown 				acpi_ut_get_type_name(type)));
42395b482a8SLen Brown 	}
42495b482a8SLen Brown 
42595b482a8SLen Brown 	/*
42695b482a8SLen Brown 	 * We ignore errors from above, and always return OK, since we don't want
42795b482a8SLen Brown 	 * to abort the walk on any single error.
42895b482a8SLen Brown 	 */
42995b482a8SLen Brown 	acpi_ex_exit_interpreter();
43095b482a8SLen Brown 	return (AE_OK);
43195b482a8SLen Brown }
43295b482a8SLen Brown 
43395b482a8SLen Brown /*******************************************************************************
43495b482a8SLen Brown  *
43595b482a8SLen Brown  * FUNCTION:    acpi_ns_find_ini_methods
43695b482a8SLen Brown  *
43795b482a8SLen Brown  * PARAMETERS:  acpi_walk_callback
43895b482a8SLen Brown  *
43995b482a8SLen Brown  * RETURN:      acpi_status
44095b482a8SLen Brown  *
44195b482a8SLen Brown  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
44295b482a8SLen Brown  *              device/processor/thermal objects, and marks the entire subtree
44395b482a8SLen Brown  *              with a SUBTREE_HAS_INI flag. This flag is used during the
44495b482a8SLen Brown  *              subsequent device initialization walk to avoid entire subtrees
44595b482a8SLen Brown  *              that do not contain an _INI.
44695b482a8SLen Brown  *
44795b482a8SLen Brown  ******************************************************************************/
44895b482a8SLen Brown 
44995b482a8SLen Brown static acpi_status
acpi_ns_find_ini_methods(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)45095b482a8SLen Brown acpi_ns_find_ini_methods(acpi_handle obj_handle,
45195b482a8SLen Brown 			 u32 nesting_level, void *context, void **return_value)
45295b482a8SLen Brown {
45395b482a8SLen Brown 	struct acpi_device_walk_info *info =
45495b482a8SLen Brown 	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
45595b482a8SLen Brown 	struct acpi_namespace_node *node;
45695b482a8SLen Brown 	struct acpi_namespace_node *parent_node;
45795b482a8SLen Brown 
45895b482a8SLen Brown 	/* Keep count of device/processor/thermal objects */
45995b482a8SLen Brown 
46095b482a8SLen Brown 	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
46195b482a8SLen Brown 	if ((node->type == ACPI_TYPE_DEVICE) ||
46295b482a8SLen Brown 	    (node->type == ACPI_TYPE_PROCESSOR) ||
46395b482a8SLen Brown 	    (node->type == ACPI_TYPE_THERMAL)) {
46495b482a8SLen Brown 		info->device_count++;
46595b482a8SLen Brown 		return (AE_OK);
46695b482a8SLen Brown 	}
46795b482a8SLen Brown 
46895b482a8SLen Brown 	/* We are only looking for methods named _INI */
46995b482a8SLen Brown 
4705599fb69SBob Moore 	if (!ACPI_COMPARE_NAMESEG(node->name.ascii, METHOD_NAME__INI)) {
47195b482a8SLen Brown 		return (AE_OK);
47295b482a8SLen Brown 	}
47395b482a8SLen Brown 
47495b482a8SLen Brown 	/*
47595b482a8SLen Brown 	 * The only _INI methods that we care about are those that are
47695b482a8SLen Brown 	 * present under Device, Processor, and Thermal objects.
47795b482a8SLen Brown 	 */
478c45b5c09SAlexey Starikovskiy 	parent_node = node->parent;
47995b482a8SLen Brown 	switch (parent_node->type) {
48095b482a8SLen Brown 	case ACPI_TYPE_DEVICE:
48195b482a8SLen Brown 	case ACPI_TYPE_PROCESSOR:
48295b482a8SLen Brown 	case ACPI_TYPE_THERMAL:
48395b482a8SLen Brown 
48495b482a8SLen Brown 		/* Mark parent and bubble up the INI present flag to the root */
48595b482a8SLen Brown 
48695b482a8SLen Brown 		while (parent_node) {
48795b482a8SLen Brown 			parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
488c45b5c09SAlexey Starikovskiy 			parent_node = parent_node->parent;
48995b482a8SLen Brown 		}
49095b482a8SLen Brown 		break;
49195b482a8SLen Brown 
49295b482a8SLen Brown 	default:
4931d1ea1b7SChao Guan 
49495b482a8SLen Brown 		break;
49595b482a8SLen Brown 	}
49695b482a8SLen Brown 
49795b482a8SLen Brown 	return (AE_OK);
49895b482a8SLen Brown }
49995b482a8SLen Brown 
50095b482a8SLen Brown /*******************************************************************************
50195b482a8SLen Brown  *
50295b482a8SLen Brown  * FUNCTION:    acpi_ns_init_one_device
50395b482a8SLen Brown  *
50495b482a8SLen Brown  * PARAMETERS:  acpi_walk_callback
50595b482a8SLen Brown  *
50695b482a8SLen Brown  * RETURN:      acpi_status
50795b482a8SLen Brown  *
50895b482a8SLen Brown  * DESCRIPTION: This is called once per device soon after ACPI is enabled
50995b482a8SLen Brown  *              to initialize each device. It determines if the device is
51095b482a8SLen Brown  *              present, and if so, calls _INI.
51195b482a8SLen Brown  *
51295b482a8SLen Brown  ******************************************************************************/
51395b482a8SLen Brown 
51495b482a8SLen Brown static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)51595b482a8SLen Brown acpi_ns_init_one_device(acpi_handle obj_handle,
51695b482a8SLen Brown 			u32 nesting_level, void *context, void **return_value)
51795b482a8SLen Brown {
51895b482a8SLen Brown 	struct acpi_device_walk_info *walk_info =
51995b482a8SLen Brown 	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
52095b482a8SLen Brown 	struct acpi_evaluate_info *info = walk_info->evaluate_info;
52195b482a8SLen Brown 	u32 flags;
52295b482a8SLen Brown 	acpi_status status;
52395b482a8SLen Brown 	struct acpi_namespace_node *device_node;
52495b482a8SLen Brown 
52595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ns_init_one_device);
52695b482a8SLen Brown 
52795b482a8SLen Brown 	/* We are interested in Devices, Processors and thermal_zones only */
52895b482a8SLen Brown 
52995b482a8SLen Brown 	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
53095b482a8SLen Brown 	if ((device_node->type != ACPI_TYPE_DEVICE) &&
53195b482a8SLen Brown 	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
53295b482a8SLen Brown 	    (device_node->type != ACPI_TYPE_THERMAL)) {
53395b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
53495b482a8SLen Brown 	}
53595b482a8SLen Brown 
53695b482a8SLen Brown 	/*
53795b482a8SLen Brown 	 * Because of an earlier namespace analysis, all subtrees that contain an
53895b482a8SLen Brown 	 * _INI method are tagged.
53995b482a8SLen Brown 	 *
54095b482a8SLen Brown 	 * If this device subtree does not contain any _INI methods, we
54195b482a8SLen Brown 	 * can exit now and stop traversing this entire subtree.
54295b482a8SLen Brown 	 */
54395b482a8SLen Brown 	if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
54495b482a8SLen Brown 		return_ACPI_STATUS(AE_CTRL_DEPTH);
54595b482a8SLen Brown 	}
54695b482a8SLen Brown 
54795b482a8SLen Brown 	/*
54895b482a8SLen Brown 	 * Run _STA to determine if this device is present and functioning. We
54995b482a8SLen Brown 	 * must know this information for two important reasons (from ACPI spec):
55095b482a8SLen Brown 	 *
55195b482a8SLen Brown 	 * 1) We can only run _INI if the device is present.
55295b482a8SLen Brown 	 * 2) We must abort the device tree walk on this subtree if the device is
55395b482a8SLen Brown 	 *    not present and is not functional (we will not examine the children)
55495b482a8SLen Brown 	 *
55595b482a8SLen Brown 	 * The _STA method is not required to be present under the device, we
55695b482a8SLen Brown 	 * assume the device is present if _STA does not exist.
55795b482a8SLen Brown 	 */
55895b482a8SLen Brown 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
55995b482a8SLen Brown 			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
56095b482a8SLen Brown 
56195b482a8SLen Brown 	status = acpi_ut_execute_STA(device_node, &flags);
56295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
56395b482a8SLen Brown 
56495b482a8SLen Brown 		/* Ignore error and move on to next device */
56595b482a8SLen Brown 
56695b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
56795b482a8SLen Brown 	}
56895b482a8SLen Brown 
56995b482a8SLen Brown 	/*
57095b482a8SLen Brown 	 * Flags == -1 means that _STA was not found. In this case, we assume that
57195b482a8SLen Brown 	 * the device is both present and functional.
57295b482a8SLen Brown 	 *
57395b482a8SLen Brown 	 * From the ACPI spec, description of _STA:
57495b482a8SLen Brown 	 *
57595b482a8SLen Brown 	 * "If a device object (including the processor object) does not have an
57695b482a8SLen Brown 	 * _STA object, then OSPM assumes that all of the above bits are set (in
57795b482a8SLen Brown 	 * other words, the device is present, ..., and functioning)"
57895b482a8SLen Brown 	 */
57995b482a8SLen Brown 	if (flags != ACPI_UINT32_MAX) {
58095b482a8SLen Brown 		walk_info->num_STA++;
58195b482a8SLen Brown 	}
58295b482a8SLen Brown 
58395b482a8SLen Brown 	/*
58495b482a8SLen Brown 	 * Examine the PRESENT and FUNCTIONING status bits
58595b482a8SLen Brown 	 *
58695b482a8SLen Brown 	 * Note: ACPI spec does not seem to specify behavior for the present but
58795b482a8SLen Brown 	 * not functioning case, so we assume functioning if present.
58895b482a8SLen Brown 	 */
58995b482a8SLen Brown 	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
59095b482a8SLen Brown 
59195b482a8SLen Brown 		/* Device is not present, we must examine the Functioning bit */
59295b482a8SLen Brown 
59395b482a8SLen Brown 		if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
59495b482a8SLen Brown 			/*
59595b482a8SLen Brown 			 * Device is not present but is "functioning". In this case,
59695b482a8SLen Brown 			 * we will not run _INI, but we continue to examine the children
59795b482a8SLen Brown 			 * of this device.
59895b482a8SLen Brown 			 *
599ba494beeSBob Moore 			 * From the ACPI spec, description of _STA: (note - no mention
60095b482a8SLen Brown 			 * of whether to run _INI or not on the device in question)
60195b482a8SLen Brown 			 *
60295b482a8SLen Brown 			 * "_STA may return bit 0 clear (not present) with bit 3 set
60395b482a8SLen Brown 			 * (device is functional). This case is used to indicate a valid
60495b482a8SLen Brown 			 * device for which no device driver should be loaded (for example,
60595b482a8SLen Brown 			 * a bridge device.) Children of this device may be present and
60695b482a8SLen Brown 			 * valid. OSPM should continue enumeration below a device whose
60795b482a8SLen Brown 			 * _STA returns this bit combination"
60895b482a8SLen Brown 			 */
60995b482a8SLen Brown 			return_ACPI_STATUS(AE_OK);
61095b482a8SLen Brown 		} else {
61195b482a8SLen Brown 			/*
61295b482a8SLen Brown 			 * Device is not present and is not functioning. We must abort the
61395b482a8SLen Brown 			 * walk of this subtree immediately -- don't look at the children
61495b482a8SLen Brown 			 * of such a device.
61595b482a8SLen Brown 			 *
61695b482a8SLen Brown 			 * From the ACPI spec, description of _INI:
61795b482a8SLen Brown 			 *
61895b482a8SLen Brown 			 * "If the _STA method indicates that the device is not present,
61995b482a8SLen Brown 			 * OSPM will not run the _INI and will not examine the children
62095b482a8SLen Brown 			 * of the device for _INI methods"
62195b482a8SLen Brown 			 */
62295b482a8SLen Brown 			return_ACPI_STATUS(AE_CTRL_DEPTH);
62395b482a8SLen Brown 		}
62495b482a8SLen Brown 	}
62595b482a8SLen Brown 
62695b482a8SLen Brown 	/*
62795b482a8SLen Brown 	 * The device is present or is assumed present if no _STA exists.
62895b482a8SLen Brown 	 * Run the _INI if it exists (not required to exist)
62995b482a8SLen Brown 	 *
63095b482a8SLen Brown 	 * Note: We know there is an _INI within this subtree, but it may not be
63195b482a8SLen Brown 	 * under this particular device, it may be lower in the branch.
63295b482a8SLen Brown 	 */
6335599fb69SBob Moore 	if (!ACPI_COMPARE_NAMESEG(device_node->name.ascii, "_SB_") ||
6342d3349deSLv Zheng 	    device_node->parent != acpi_gbl_root_node) {
63595b482a8SLen Brown 		ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
6362d3349deSLv Zheng 				(ACPI_TYPE_METHOD, device_node,
6372d3349deSLv Zheng 				 METHOD_NAME__INI));
63895b482a8SLen Brown 
6394fa4616eSBob Moore 		memset(info, 0, sizeof(struct acpi_evaluate_info));
64095b482a8SLen Brown 		info->prefix_node = device_node;
64129a241ccSBob Moore 		info->relative_pathname = METHOD_NAME__INI;
64295b482a8SLen Brown 		info->parameters = NULL;
64395b482a8SLen Brown 		info->flags = ACPI_IGNORE_RETURN_VALUE;
64495b482a8SLen Brown 
64595b482a8SLen Brown 		status = acpi_ns_evaluate(info);
64695b482a8SLen Brown 		if (ACPI_SUCCESS(status)) {
64795b482a8SLen Brown 			walk_info->num_INI++;
64895b482a8SLen Brown 		}
64995b482a8SLen Brown #ifdef ACPI_DEBUG_OUTPUT
65095b482a8SLen Brown 		else if (status != AE_NOT_FOUND) {
65195b482a8SLen Brown 
65295b482a8SLen Brown 			/* Ignore error and move on to next device */
65395b482a8SLen Brown 
6540e166e4fSLv Zheng 			char *scope_name =
6550e166e4fSLv Zheng 			    acpi_ns_get_normalized_pathname(device_node, TRUE);
65695b482a8SLen Brown 
6572d3349deSLv Zheng 			ACPI_EXCEPTION((AE_INFO, status,
6582d3349deSLv Zheng 					"during %s._INI execution",
65995b482a8SLen Brown 					scope_name));
66095b482a8SLen Brown 			ACPI_FREE(scope_name);
66195b482a8SLen Brown 		}
66295b482a8SLen Brown #endif
6632d3349deSLv Zheng 	}
66495b482a8SLen Brown 
66595b482a8SLen Brown 	/* Ignore errors from above */
66695b482a8SLen Brown 
66795b482a8SLen Brown 	status = AE_OK;
66895b482a8SLen Brown 
66995b482a8SLen Brown 	/*
67095b482a8SLen Brown 	 * The _INI method has been run if present; call the Global Initialization
67195b482a8SLen Brown 	 * Handler for this device.
67295b482a8SLen Brown 	 */
67395b482a8SLen Brown 	if (acpi_gbl_init_handler) {
67495b482a8SLen Brown 		status =
67595b482a8SLen Brown 		    acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
67695b482a8SLen Brown 	}
67795b482a8SLen Brown 
67895b482a8SLen Brown 	return_ACPI_STATUS(status);
67995b482a8SLen Brown }
680