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 * 6da6f8320SBob Moore * Copyright (C) 2000 - 2018, 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 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, 582fae3e56SBob Moore "Completing Region/Field/Buffer/Package initialization:\n")); 5995b482a8SLen Brown 6095b482a8SLen Brown /* Set all init info to zero */ 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 6695b482a8SLen Brown status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 671f86e8c1SLv Zheng ACPI_UINT32_MAX, acpi_ns_init_one_object, 681f86e8c1SLv Zheng NULL, &info, NULL); 6995b482a8SLen Brown if (ACPI_FAILURE(status)) { 7095b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); 7195b482a8SLen Brown } 7295b482a8SLen Brown 7395b482a8SLen Brown ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 742fae3e56SBob Moore " Initialized %u/%u Regions %u/%u Fields %u/%u " 7596b7b7adSAlexey Starikovskiy "Buffers %u/%u Packages (%u nodes)\n", 7695b482a8SLen Brown info.op_region_init, info.op_region_count, 7795b482a8SLen Brown info.field_init, info.field_count, 7895b482a8SLen Brown info.buffer_init, info.buffer_count, 7995b482a8SLen Brown info.package_init, info.package_count, 8095b482a8SLen Brown 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 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 * 245*7b34c0fbSBob Moore * FUNCTION: acpi_ns_init_one_package 246*7b34c0fbSBob Moore * 247*7b34c0fbSBob Moore * PARAMETERS: obj_handle - Node 248*7b34c0fbSBob Moore * level - Current nesting level 249*7b34c0fbSBob Moore * context - Not used 250*7b34c0fbSBob Moore * return_value - Not used 251*7b34c0fbSBob Moore * 252*7b34c0fbSBob Moore * RETURN: Status 253*7b34c0fbSBob Moore * 254*7b34c0fbSBob Moore * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package 255*7b34c0fbSBob Moore * within the namespace. Used during dynamic load of an SSDT. 256*7b34c0fbSBob Moore * 257*7b34c0fbSBob Moore ******************************************************************************/ 258*7b34c0fbSBob Moore 259*7b34c0fbSBob Moore acpi_status 260*7b34c0fbSBob Moore acpi_ns_init_one_package(acpi_handle obj_handle, 261*7b34c0fbSBob Moore u32 level, void *context, void **return_value) 262*7b34c0fbSBob Moore { 263*7b34c0fbSBob Moore acpi_status status; 264*7b34c0fbSBob Moore union acpi_operand_object *obj_desc; 265*7b34c0fbSBob Moore struct acpi_namespace_node *node = 266*7b34c0fbSBob Moore (struct acpi_namespace_node *)obj_handle; 267*7b34c0fbSBob Moore 268*7b34c0fbSBob Moore obj_desc = acpi_ns_get_attached_object(node); 269*7b34c0fbSBob Moore if (!obj_desc) { 270*7b34c0fbSBob Moore return (AE_OK); 271*7b34c0fbSBob Moore } 272*7b34c0fbSBob Moore 273*7b34c0fbSBob Moore /* Exit if package is already initialized */ 274*7b34c0fbSBob Moore 275*7b34c0fbSBob Moore if (obj_desc->package.flags & AOPOBJ_DATA_VALID) { 276*7b34c0fbSBob Moore return (AE_OK); 277*7b34c0fbSBob Moore } 278*7b34c0fbSBob Moore 279*7b34c0fbSBob Moore status = acpi_ds_get_package_arguments(obj_desc); 280*7b34c0fbSBob Moore if (ACPI_FAILURE(status)) { 281*7b34c0fbSBob Moore return (AE_OK); 282*7b34c0fbSBob Moore } 283*7b34c0fbSBob Moore 284*7b34c0fbSBob Moore status = 285*7b34c0fbSBob Moore acpi_ut_walk_package_tree(obj_desc, NULL, 286*7b34c0fbSBob Moore acpi_ds_init_package_element, NULL); 287*7b34c0fbSBob Moore if (ACPI_FAILURE(status)) { 288*7b34c0fbSBob Moore return (AE_OK); 289*7b34c0fbSBob Moore } 290*7b34c0fbSBob Moore 291*7b34c0fbSBob Moore obj_desc->package.flags |= AOPOBJ_DATA_VALID; 292*7b34c0fbSBob Moore return (AE_OK); 293*7b34c0fbSBob Moore } 294*7b34c0fbSBob Moore 295*7b34c0fbSBob Moore /******************************************************************************* 296*7b34c0fbSBob 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 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 /* 38595b482a8SLen Brown * Each of these types can contain executable AML code within the 38695b482a8SLen Brown * declaration. 38795b482a8SLen Brown */ 38895b482a8SLen Brown switch (type) { 38995b482a8SLen Brown case ACPI_TYPE_REGION: 39095b482a8SLen Brown 39195b482a8SLen Brown info->op_region_init++; 39295b482a8SLen Brown status = acpi_ds_get_region_arguments(obj_desc); 39395b482a8SLen Brown break; 39495b482a8SLen Brown 39595b482a8SLen Brown case ACPI_TYPE_BUFFER_FIELD: 39695b482a8SLen Brown 39795b482a8SLen Brown info->field_init++; 39895b482a8SLen Brown status = acpi_ds_get_buffer_field_arguments(obj_desc); 39995b482a8SLen Brown break; 40095b482a8SLen Brown 40195b482a8SLen Brown case ACPI_TYPE_LOCAL_BANK_FIELD: 40295b482a8SLen Brown 40395b482a8SLen Brown info->field_init++; 40495b482a8SLen Brown status = acpi_ds_get_bank_field_arguments(obj_desc); 40595b482a8SLen Brown break; 40695b482a8SLen Brown 40795b482a8SLen Brown case ACPI_TYPE_BUFFER: 40895b482a8SLen Brown 40995b482a8SLen Brown info->buffer_init++; 41095b482a8SLen Brown status = acpi_ds_get_buffer_arguments(obj_desc); 41195b482a8SLen Brown break; 41295b482a8SLen Brown 41395b482a8SLen Brown case ACPI_TYPE_PACKAGE: 41495b482a8SLen Brown 415*7b34c0fbSBob Moore /* Complete the initialization/resolution of the package object */ 416*7b34c0fbSBob Moore 41795b482a8SLen Brown info->package_init++; 418*7b34c0fbSBob Moore status = 419*7b34c0fbSBob Moore acpi_ns_init_one_package(obj_handle, level, NULL, NULL); 42095b482a8SLen Brown break; 42195b482a8SLen Brown 42295b482a8SLen Brown default: 4231d1ea1b7SChao Guan 42495b482a8SLen Brown /* No other types can get here */ 4251d1ea1b7SChao Guan 42695b482a8SLen Brown break; 42795b482a8SLen Brown } 42895b482a8SLen Brown 42995b482a8SLen Brown if (ACPI_FAILURE(status)) { 43095b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 43195b482a8SLen Brown "Could not execute arguments for [%4.4s] (%s)", 43295b482a8SLen Brown acpi_ut_get_node_name(node), 43395b482a8SLen Brown acpi_ut_get_type_name(type))); 43495b482a8SLen Brown } 43595b482a8SLen Brown 43695b482a8SLen Brown /* 43795b482a8SLen Brown * We ignore errors from above, and always return OK, since we don't want 43895b482a8SLen Brown * to abort the walk on any single error. 43995b482a8SLen Brown */ 44095b482a8SLen Brown acpi_ex_exit_interpreter(); 44195b482a8SLen Brown return (AE_OK); 44295b482a8SLen Brown } 44395b482a8SLen Brown 44495b482a8SLen Brown /******************************************************************************* 44595b482a8SLen Brown * 44695b482a8SLen Brown * FUNCTION: acpi_ns_find_ini_methods 44795b482a8SLen Brown * 44895b482a8SLen Brown * PARAMETERS: acpi_walk_callback 44995b482a8SLen Brown * 45095b482a8SLen Brown * RETURN: acpi_status 45195b482a8SLen Brown * 45295b482a8SLen Brown * DESCRIPTION: Called during namespace walk. Finds objects named _INI under 45395b482a8SLen Brown * device/processor/thermal objects, and marks the entire subtree 45495b482a8SLen Brown * with a SUBTREE_HAS_INI flag. This flag is used during the 45595b482a8SLen Brown * subsequent device initialization walk to avoid entire subtrees 45695b482a8SLen Brown * that do not contain an _INI. 45795b482a8SLen Brown * 45895b482a8SLen Brown ******************************************************************************/ 45995b482a8SLen Brown 46095b482a8SLen Brown static acpi_status 46195b482a8SLen Brown acpi_ns_find_ini_methods(acpi_handle obj_handle, 46295b482a8SLen Brown u32 nesting_level, void *context, void **return_value) 46395b482a8SLen Brown { 46495b482a8SLen Brown struct acpi_device_walk_info *info = 46595b482a8SLen Brown ACPI_CAST_PTR(struct acpi_device_walk_info, context); 46695b482a8SLen Brown struct acpi_namespace_node *node; 46795b482a8SLen Brown struct acpi_namespace_node *parent_node; 46895b482a8SLen Brown 46995b482a8SLen Brown /* Keep count of device/processor/thermal objects */ 47095b482a8SLen Brown 47195b482a8SLen Brown node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); 47295b482a8SLen Brown if ((node->type == ACPI_TYPE_DEVICE) || 47395b482a8SLen Brown (node->type == ACPI_TYPE_PROCESSOR) || 47495b482a8SLen Brown (node->type == ACPI_TYPE_THERMAL)) { 47595b482a8SLen Brown info->device_count++; 47695b482a8SLen Brown return (AE_OK); 47795b482a8SLen Brown } 47895b482a8SLen Brown 47995b482a8SLen Brown /* We are only looking for methods named _INI */ 48095b482a8SLen Brown 48195b482a8SLen Brown if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) { 48295b482a8SLen Brown return (AE_OK); 48395b482a8SLen Brown } 48495b482a8SLen Brown 48595b482a8SLen Brown /* 48695b482a8SLen Brown * The only _INI methods that we care about are those that are 48795b482a8SLen Brown * present under Device, Processor, and Thermal objects. 48895b482a8SLen Brown */ 489c45b5c09SAlexey Starikovskiy parent_node = node->parent; 49095b482a8SLen Brown switch (parent_node->type) { 49195b482a8SLen Brown case ACPI_TYPE_DEVICE: 49295b482a8SLen Brown case ACPI_TYPE_PROCESSOR: 49395b482a8SLen Brown case ACPI_TYPE_THERMAL: 49495b482a8SLen Brown 49595b482a8SLen Brown /* Mark parent and bubble up the INI present flag to the root */ 49695b482a8SLen Brown 49795b482a8SLen Brown while (parent_node) { 49895b482a8SLen Brown parent_node->flags |= ANOBJ_SUBTREE_HAS_INI; 499c45b5c09SAlexey Starikovskiy parent_node = parent_node->parent; 50095b482a8SLen Brown } 50195b482a8SLen Brown break; 50295b482a8SLen Brown 50395b482a8SLen Brown default: 5041d1ea1b7SChao Guan 50595b482a8SLen Brown break; 50695b482a8SLen Brown } 50795b482a8SLen Brown 50895b482a8SLen Brown return (AE_OK); 50995b482a8SLen Brown } 51095b482a8SLen Brown 51195b482a8SLen Brown /******************************************************************************* 51295b482a8SLen Brown * 51395b482a8SLen Brown * FUNCTION: acpi_ns_init_one_device 51495b482a8SLen Brown * 51595b482a8SLen Brown * PARAMETERS: acpi_walk_callback 51695b482a8SLen Brown * 51795b482a8SLen Brown * RETURN: acpi_status 51895b482a8SLen Brown * 51995b482a8SLen Brown * DESCRIPTION: This is called once per device soon after ACPI is enabled 52095b482a8SLen Brown * to initialize each device. It determines if the device is 52195b482a8SLen Brown * present, and if so, calls _INI. 52295b482a8SLen Brown * 52395b482a8SLen Brown ******************************************************************************/ 52495b482a8SLen Brown 52595b482a8SLen Brown static acpi_status 52695b482a8SLen Brown acpi_ns_init_one_device(acpi_handle obj_handle, 52795b482a8SLen Brown u32 nesting_level, void *context, void **return_value) 52895b482a8SLen Brown { 52995b482a8SLen Brown struct acpi_device_walk_info *walk_info = 53095b482a8SLen Brown ACPI_CAST_PTR(struct acpi_device_walk_info, context); 53195b482a8SLen Brown struct acpi_evaluate_info *info = walk_info->evaluate_info; 53295b482a8SLen Brown u32 flags; 53395b482a8SLen Brown acpi_status status; 53495b482a8SLen Brown struct acpi_namespace_node *device_node; 53595b482a8SLen Brown 53695b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_init_one_device); 53795b482a8SLen Brown 53895b482a8SLen Brown /* We are interested in Devices, Processors and thermal_zones only */ 53995b482a8SLen Brown 54095b482a8SLen Brown device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); 54195b482a8SLen Brown if ((device_node->type != ACPI_TYPE_DEVICE) && 54295b482a8SLen Brown (device_node->type != ACPI_TYPE_PROCESSOR) && 54395b482a8SLen Brown (device_node->type != ACPI_TYPE_THERMAL)) { 54495b482a8SLen Brown return_ACPI_STATUS(AE_OK); 54595b482a8SLen Brown } 54695b482a8SLen Brown 54795b482a8SLen Brown /* 54895b482a8SLen Brown * Because of an earlier namespace analysis, all subtrees that contain an 54995b482a8SLen Brown * _INI method are tagged. 55095b482a8SLen Brown * 55195b482a8SLen Brown * If this device subtree does not contain any _INI methods, we 55295b482a8SLen Brown * can exit now and stop traversing this entire subtree. 55395b482a8SLen Brown */ 55495b482a8SLen Brown if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) { 55595b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_DEPTH); 55695b482a8SLen Brown } 55795b482a8SLen Brown 55895b482a8SLen Brown /* 55995b482a8SLen Brown * Run _STA to determine if this device is present and functioning. We 56095b482a8SLen Brown * must know this information for two important reasons (from ACPI spec): 56195b482a8SLen Brown * 56295b482a8SLen Brown * 1) We can only run _INI if the device is present. 56395b482a8SLen Brown * 2) We must abort the device tree walk on this subtree if the device is 56495b482a8SLen Brown * not present and is not functional (we will not examine the children) 56595b482a8SLen Brown * 56695b482a8SLen Brown * The _STA method is not required to be present under the device, we 56795b482a8SLen Brown * assume the device is present if _STA does not exist. 56895b482a8SLen Brown */ 56995b482a8SLen Brown ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 57095b482a8SLen Brown (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA)); 57195b482a8SLen Brown 57295b482a8SLen Brown status = acpi_ut_execute_STA(device_node, &flags); 57395b482a8SLen Brown if (ACPI_FAILURE(status)) { 57495b482a8SLen Brown 57595b482a8SLen Brown /* Ignore error and move on to next device */ 57695b482a8SLen Brown 57795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 57895b482a8SLen Brown } 57995b482a8SLen Brown 58095b482a8SLen Brown /* 58195b482a8SLen Brown * Flags == -1 means that _STA was not found. In this case, we assume that 58295b482a8SLen Brown * the device is both present and functional. 58395b482a8SLen Brown * 58495b482a8SLen Brown * From the ACPI spec, description of _STA: 58595b482a8SLen Brown * 58695b482a8SLen Brown * "If a device object (including the processor object) does not have an 58795b482a8SLen Brown * _STA object, then OSPM assumes that all of the above bits are set (in 58895b482a8SLen Brown * other words, the device is present, ..., and functioning)" 58995b482a8SLen Brown */ 59095b482a8SLen Brown if (flags != ACPI_UINT32_MAX) { 59195b482a8SLen Brown walk_info->num_STA++; 59295b482a8SLen Brown } 59395b482a8SLen Brown 59495b482a8SLen Brown /* 59595b482a8SLen Brown * Examine the PRESENT and FUNCTIONING status bits 59695b482a8SLen Brown * 59795b482a8SLen Brown * Note: ACPI spec does not seem to specify behavior for the present but 59895b482a8SLen Brown * not functioning case, so we assume functioning if present. 59995b482a8SLen Brown */ 60095b482a8SLen Brown if (!(flags & ACPI_STA_DEVICE_PRESENT)) { 60195b482a8SLen Brown 60295b482a8SLen Brown /* Device is not present, we must examine the Functioning bit */ 60395b482a8SLen Brown 60495b482a8SLen Brown if (flags & ACPI_STA_DEVICE_FUNCTIONING) { 60595b482a8SLen Brown /* 60695b482a8SLen Brown * Device is not present but is "functioning". In this case, 60795b482a8SLen Brown * we will not run _INI, but we continue to examine the children 60895b482a8SLen Brown * of this device. 60995b482a8SLen Brown * 610ba494beeSBob Moore * From the ACPI spec, description of _STA: (note - no mention 61195b482a8SLen Brown * of whether to run _INI or not on the device in question) 61295b482a8SLen Brown * 61395b482a8SLen Brown * "_STA may return bit 0 clear (not present) with bit 3 set 61495b482a8SLen Brown * (device is functional). This case is used to indicate a valid 61595b482a8SLen Brown * device for which no device driver should be loaded (for example, 61695b482a8SLen Brown * a bridge device.) Children of this device may be present and 61795b482a8SLen Brown * valid. OSPM should continue enumeration below a device whose 61895b482a8SLen Brown * _STA returns this bit combination" 61995b482a8SLen Brown */ 62095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 62195b482a8SLen Brown } else { 62295b482a8SLen Brown /* 62395b482a8SLen Brown * Device is not present and is not functioning. We must abort the 62495b482a8SLen Brown * walk of this subtree immediately -- don't look at the children 62595b482a8SLen Brown * of such a device. 62695b482a8SLen Brown * 62795b482a8SLen Brown * From the ACPI spec, description of _INI: 62895b482a8SLen Brown * 62995b482a8SLen Brown * "If the _STA method indicates that the device is not present, 63095b482a8SLen Brown * OSPM will not run the _INI and will not examine the children 63195b482a8SLen Brown * of the device for _INI methods" 63295b482a8SLen Brown */ 63395b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_DEPTH); 63495b482a8SLen Brown } 63595b482a8SLen Brown } 63695b482a8SLen Brown 63795b482a8SLen Brown /* 63895b482a8SLen Brown * The device is present or is assumed present if no _STA exists. 63995b482a8SLen Brown * Run the _INI if it exists (not required to exist) 64095b482a8SLen Brown * 64195b482a8SLen Brown * Note: We know there is an _INI within this subtree, but it may not be 64295b482a8SLen Brown * under this particular device, it may be lower in the branch. 64395b482a8SLen Brown */ 6442d3349deSLv Zheng if (!ACPI_COMPARE_NAME(device_node->name.ascii, "_SB_") || 6452d3349deSLv Zheng device_node->parent != acpi_gbl_root_node) { 64695b482a8SLen Brown ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 6472d3349deSLv Zheng (ACPI_TYPE_METHOD, device_node, 6482d3349deSLv Zheng METHOD_NAME__INI)); 64995b482a8SLen Brown 6504fa4616eSBob Moore memset(info, 0, sizeof(struct acpi_evaluate_info)); 65195b482a8SLen Brown info->prefix_node = device_node; 65229a241ccSBob Moore info->relative_pathname = METHOD_NAME__INI; 65395b482a8SLen Brown info->parameters = NULL; 65495b482a8SLen Brown info->flags = ACPI_IGNORE_RETURN_VALUE; 65595b482a8SLen Brown 65695b482a8SLen Brown status = acpi_ns_evaluate(info); 65795b482a8SLen Brown if (ACPI_SUCCESS(status)) { 65895b482a8SLen Brown walk_info->num_INI++; 65995b482a8SLen Brown } 66095b482a8SLen Brown #ifdef ACPI_DEBUG_OUTPUT 66195b482a8SLen Brown else if (status != AE_NOT_FOUND) { 66295b482a8SLen Brown 66395b482a8SLen Brown /* Ignore error and move on to next device */ 66495b482a8SLen Brown 6650e166e4fSLv Zheng char *scope_name = 6660e166e4fSLv Zheng acpi_ns_get_normalized_pathname(device_node, TRUE); 66795b482a8SLen Brown 6682d3349deSLv Zheng ACPI_EXCEPTION((AE_INFO, status, 6692d3349deSLv Zheng "during %s._INI execution", 67095b482a8SLen Brown scope_name)); 67195b482a8SLen Brown ACPI_FREE(scope_name); 67295b482a8SLen Brown } 67395b482a8SLen Brown #endif 6742d3349deSLv Zheng } 67595b482a8SLen Brown 67695b482a8SLen Brown /* Ignore errors from above */ 67795b482a8SLen Brown 67895b482a8SLen Brown status = AE_OK; 67995b482a8SLen Brown 68095b482a8SLen Brown /* 68195b482a8SLen Brown * The _INI method has been run if present; call the Global Initialization 68295b482a8SLen Brown * Handler for this device. 68395b482a8SLen Brown */ 68495b482a8SLen Brown if (acpi_gbl_init_handler) { 68595b482a8SLen Brown status = 68695b482a8SLen Brown acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); 68795b482a8SLen Brown } 68895b482a8SLen Brown 68995b482a8SLen Brown return_ACPI_STATUS(status); 69095b482a8SLen Brown } 691