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