162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: tbxfload - Table load/unload external interfaces 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define EXPORT_ACPI_INTERFACES 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <acpi/acpi.h> 1362306a36Sopenharmony_ci#include "accommon.h" 1462306a36Sopenharmony_ci#include "acnamesp.h" 1562306a36Sopenharmony_ci#include "actables.h" 1662306a36Sopenharmony_ci#include "acevents.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define _COMPONENT ACPI_TABLES 1962306a36Sopenharmony_ciACPI_MODULE_NAME("tbxfload") 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/******************************************************************************* 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * FUNCTION: acpi_load_tables 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * PARAMETERS: None 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * RETURN: Status 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci ******************************************************************************/ 3262306a36Sopenharmony_ciacpi_status ACPI_INIT_FUNCTION acpi_load_tables(void) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci acpi_status status; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_load_tables); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* 3962306a36Sopenharmony_ci * Install the default operation region handlers. These are the 4062306a36Sopenharmony_ci * handlers that are defined by the ACPI specification to be 4162306a36Sopenharmony_ci * "always accessible" -- namely, system_memory, system_IO, and 4262306a36Sopenharmony_ci * PCI_Config. This also means that no _REG methods need to be 4362306a36Sopenharmony_ci * run for these address spaces. We need to have these handlers 4462306a36Sopenharmony_ci * installed before any AML code can be executed, especially any 4562306a36Sopenharmony_ci * module-level code (11/2015). 4662306a36Sopenharmony_ci * Note that we allow OSPMs to install their own region handlers 4762306a36Sopenharmony_ci * between acpi_initialize_subsystem() and acpi_load_tables() to use 4862306a36Sopenharmony_ci * their customized default region handlers. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci status = acpi_ev_install_region_handlers(); 5162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 5262306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 5362306a36Sopenharmony_ci "During Region initialization")); 5462306a36Sopenharmony_ci return_ACPI_STATUS(status); 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Load the namespace from the tables */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci status = acpi_tb_load_namespace(); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* Don't let single failures abort the load */ 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (status == AE_CTRL_TERMINATE) { 6462306a36Sopenharmony_ci status = AE_OK; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 6862306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 6962306a36Sopenharmony_ci "While loading namespace from ACPI tables")); 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* 7362306a36Sopenharmony_ci * Initialize the objects in the namespace that remain uninitialized. 7462306a36Sopenharmony_ci * This runs the executable AML that may be part of the declaration of 7562306a36Sopenharmony_ci * these name objects: 7662306a36Sopenharmony_ci * operation_regions, buffer_fields, Buffers, and Packages. 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci status = acpi_ns_initialize_objects(); 8062306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 8162306a36Sopenharmony_ci acpi_gbl_namespace_initialized = TRUE; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return_ACPI_STATUS(status); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciACPI_EXPORT_SYMBOL_INIT(acpi_load_tables) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/******************************************************************************* 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * FUNCTION: acpi_tb_load_namespace 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * PARAMETERS: None 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * RETURN: Status 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 9862306a36Sopenharmony_ci * the RSDT/XSDT. 9962306a36Sopenharmony_ci * 10062306a36Sopenharmony_ci ******************************************************************************/ 10162306a36Sopenharmony_ciacpi_status acpi_tb_load_namespace(void) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci acpi_status status; 10462306a36Sopenharmony_ci u32 i; 10562306a36Sopenharmony_ci struct acpi_table_header *new_dsdt; 10662306a36Sopenharmony_ci struct acpi_table_desc *table; 10762306a36Sopenharmony_ci u32 tables_loaded = 0; 10862306a36Sopenharmony_ci u32 tables_failed = 0; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(tb_load_namespace); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* 11562306a36Sopenharmony_ci * Load the namespace. The DSDT is required, but any SSDT and 11662306a36Sopenharmony_ci * PSDT tables are optional. Verify the DSDT. 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_ci table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index]; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (!acpi_gbl_root_table_list.current_table_count || 12162306a36Sopenharmony_ci !ACPI_COMPARE_NAMESEG(table->signature.ascii, ACPI_SIG_DSDT) || 12262306a36Sopenharmony_ci ACPI_FAILURE(acpi_tb_validate_table(table))) { 12362306a36Sopenharmony_ci status = AE_NO_ACPI_TABLES; 12462306a36Sopenharmony_ci goto unlock_and_exit; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* 12862306a36Sopenharmony_ci * Save the DSDT pointer for simple access. This is the mapped memory 12962306a36Sopenharmony_ci * address. We must take care here because the address of the .Tables 13062306a36Sopenharmony_ci * array can change dynamically as tables are loaded at run-time. Note: 13162306a36Sopenharmony_ci * .Pointer field is not validated until after call to acpi_tb_validate_table. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci acpi_gbl_DSDT = table->pointer; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* 13662306a36Sopenharmony_ci * Optionally copy the entire DSDT to local memory (instead of simply 13762306a36Sopenharmony_ci * mapping it.) There are some BIOSs that corrupt or replace the original 13862306a36Sopenharmony_ci * DSDT, creating the need for this option. Default is FALSE, do not copy 13962306a36Sopenharmony_ci * the DSDT. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ci if (acpi_gbl_copy_dsdt_locally) { 14262306a36Sopenharmony_ci new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index); 14362306a36Sopenharmony_ci if (new_dsdt) { 14462306a36Sopenharmony_ci acpi_gbl_DSDT = new_dsdt; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * Save the original DSDT header for detection of table corruption 15062306a36Sopenharmony_ci * and/or replacement of the DSDT from outside the OS. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, 15362306a36Sopenharmony_ci sizeof(struct acpi_table_header)); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Load and parse tables */ 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 15862306a36Sopenharmony_ci status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node); 15962306a36Sopenharmony_ci (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 16062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 16162306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed")); 16262306a36Sopenharmony_ci tables_failed++; 16362306a36Sopenharmony_ci } else { 16462306a36Sopenharmony_ci tables_loaded++; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { 17062306a36Sopenharmony_ci table = &acpi_gbl_root_table_list.tables[i]; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (!table->address || 17362306a36Sopenharmony_ci (!ACPI_COMPARE_NAMESEG 17462306a36Sopenharmony_ci (table->signature.ascii, ACPI_SIG_SSDT) 17562306a36Sopenharmony_ci && !ACPI_COMPARE_NAMESEG(table->signature.ascii, 17662306a36Sopenharmony_ci ACPI_SIG_PSDT) 17762306a36Sopenharmony_ci && !ACPI_COMPARE_NAMESEG(table->signature.ascii, 17862306a36Sopenharmony_ci ACPI_SIG_OSDT)) 17962306a36Sopenharmony_ci || ACPI_FAILURE(acpi_tb_validate_table(table))) { 18062306a36Sopenharmony_ci continue; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* Ignore errors while loading tables, get as many as possible */ 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 18662306a36Sopenharmony_ci status = acpi_ns_load_table(i, acpi_gbl_root_node); 18762306a36Sopenharmony_ci (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 18862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 18962306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 19062306a36Sopenharmony_ci "(%4.4s:%8.8s) while loading table", 19162306a36Sopenharmony_ci table->signature.ascii, 19262306a36Sopenharmony_ci table->pointer->oem_table_id)); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci tables_failed++; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 19762306a36Sopenharmony_ci "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", 19862306a36Sopenharmony_ci table->signature.ascii, 19962306a36Sopenharmony_ci table->pointer->oem_table_id)); 20062306a36Sopenharmony_ci } else { 20162306a36Sopenharmony_ci tables_loaded++; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (!tables_failed) { 20662306a36Sopenharmony_ci ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded", tables_loaded)); 20762306a36Sopenharmony_ci } else { 20862306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 20962306a36Sopenharmony_ci "%u table load failures, %u successful", 21062306a36Sopenharmony_ci tables_failed, tables_loaded)); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Indicate at least one failure */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci status = AE_CTRL_TERMINATE; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci#ifdef ACPI_APPLICATION 21862306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "\n")); 21962306a36Sopenharmony_ci#endif 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciunlock_and_exit: 22262306a36Sopenharmony_ci (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 22362306a36Sopenharmony_ci return_ACPI_STATUS(status); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/******************************************************************************* 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * FUNCTION: acpi_install_table 22962306a36Sopenharmony_ci * 23062306a36Sopenharmony_ci * PARAMETERS: table - Pointer to the ACPI table to be installed. 23162306a36Sopenharmony_ci * 23262306a36Sopenharmony_ci * RETURN: Status 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * DESCRIPTION: Dynamically install an ACPI table. 23562306a36Sopenharmony_ci * Note: This function should only be invoked after 23662306a36Sopenharmony_ci * acpi_initialize_tables() and before acpi_load_tables(). 23762306a36Sopenharmony_ci * 23862306a36Sopenharmony_ci ******************************************************************************/ 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ciacpi_status ACPI_INIT_FUNCTION 24162306a36Sopenharmony_ciacpi_install_table(struct acpi_table_header *table) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci acpi_status status; 24462306a36Sopenharmony_ci u32 table_index; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_install_table); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), 24962306a36Sopenharmony_ci ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, 25062306a36Sopenharmony_ci table, FALSE, FALSE, 25162306a36Sopenharmony_ci &table_index); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return_ACPI_STATUS(status); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciACPI_EXPORT_SYMBOL_INIT(acpi_install_table) 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/******************************************************************************* 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci * FUNCTION: acpi_install_physical_table 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * PARAMETERS: address - Address of the ACPI table to be installed. 26362306a36Sopenharmony_ci * 26462306a36Sopenharmony_ci * RETURN: Status 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * DESCRIPTION: Dynamically install an ACPI table. 26762306a36Sopenharmony_ci * Note: This function should only be invoked after 26862306a36Sopenharmony_ci * acpi_initialize_tables() and before acpi_load_tables(). 26962306a36Sopenharmony_ci * 27062306a36Sopenharmony_ci ******************************************************************************/ 27162306a36Sopenharmony_ciacpi_status ACPI_INIT_FUNCTION 27262306a36Sopenharmony_ciacpi_install_physical_table(acpi_physical_address address) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci acpi_status status; 27562306a36Sopenharmony_ci u32 table_index; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_install_physical_table); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci status = acpi_tb_install_standard_table(address, 28062306a36Sopenharmony_ci ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, 28162306a36Sopenharmony_ci NULL, FALSE, FALSE, 28262306a36Sopenharmony_ci &table_index); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return_ACPI_STATUS(status); 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciACPI_EXPORT_SYMBOL_INIT(acpi_install_physical_table) 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/******************************************************************************* 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * FUNCTION: acpi_load_table 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * PARAMETERS: table - Pointer to a buffer containing the ACPI 29462306a36Sopenharmony_ci * table to be loaded. 29562306a36Sopenharmony_ci * table_idx - Pointer to a u32 for storing the table 29662306a36Sopenharmony_ci * index, might be NULL 29762306a36Sopenharmony_ci * 29862306a36Sopenharmony_ci * RETURN: Status 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 30162306a36Sopenharmony_ci * be a valid ACPI table with a valid ACPI table header. 30262306a36Sopenharmony_ci * Note1: Mainly intended to support hotplug addition of SSDTs. 30362306a36Sopenharmony_ci * Note2: Does not copy the incoming table. User is responsible 30462306a36Sopenharmony_ci * to ensure that the table is not deleted or unmapped. 30562306a36Sopenharmony_ci * 30662306a36Sopenharmony_ci ******************************************************************************/ 30762306a36Sopenharmony_ciacpi_status acpi_load_table(struct acpi_table_header *table, u32 *table_idx) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci acpi_status status; 31062306a36Sopenharmony_ci u32 table_index; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_load_table); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* Parameter validation */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (!table) { 31762306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* Install the table and load it into the namespace */ 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ACPI_INFO(("Host-directed Dynamic ACPI Table Load:")); 32362306a36Sopenharmony_ci status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table), 32462306a36Sopenharmony_ci ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, 32562306a36Sopenharmony_ci table, FALSE, &table_index); 32662306a36Sopenharmony_ci if (table_idx) { 32762306a36Sopenharmony_ci *table_idx = table_index; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* Complete the initialization/resolution of new objects */ 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci acpi_ns_initialize_objects(); 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci return_ACPI_STATUS(status); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_load_table) 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci/******************************************************************************* 34362306a36Sopenharmony_ci * 34462306a36Sopenharmony_ci * FUNCTION: acpi_unload_parent_table 34562306a36Sopenharmony_ci * 34662306a36Sopenharmony_ci * PARAMETERS: object - Handle to any namespace object owned by 34762306a36Sopenharmony_ci * the table to be unloaded 34862306a36Sopenharmony_ci * 34962306a36Sopenharmony_ci * RETURN: Status 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 35262306a36Sopenharmony_ci * the table and deletes all namespace objects associated with 35362306a36Sopenharmony_ci * that table. Unloading of the DSDT is not allowed. 35462306a36Sopenharmony_ci * Note: Mainly intended to support hotplug removal of SSDTs. 35562306a36Sopenharmony_ci * 35662306a36Sopenharmony_ci ******************************************************************************/ 35762306a36Sopenharmony_ciacpi_status acpi_unload_parent_table(acpi_handle object) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct acpi_namespace_node *node = 36062306a36Sopenharmony_ci ACPI_CAST_PTR(struct acpi_namespace_node, object); 36162306a36Sopenharmony_ci acpi_status status = AE_NOT_EXIST; 36262306a36Sopenharmony_ci acpi_owner_id owner_id; 36362306a36Sopenharmony_ci u32 i; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_unload_parent_table); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* Parameter validation */ 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (!object) { 37062306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* 37462306a36Sopenharmony_ci * The node owner_id is currently the same as the parent table ID. 37562306a36Sopenharmony_ci * However, this could change in the future. 37662306a36Sopenharmony_ci */ 37762306a36Sopenharmony_ci owner_id = node->owner_id; 37862306a36Sopenharmony_ci if (!owner_id) { 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */ 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci return_ACPI_STATUS(AE_TYPE); 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* Must acquire the table lock during this operation */ 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 38862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 38962306a36Sopenharmony_ci return_ACPI_STATUS(status); 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Find the table in the global table list */ 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { 39562306a36Sopenharmony_ci if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) { 39662306a36Sopenharmony_ci continue; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * Allow unload of SSDT and OEMx tables only. Do not allow unload 40162306a36Sopenharmony_ci * of the DSDT. No other types of tables should get here, since 40262306a36Sopenharmony_ci * only these types can contain AML and thus are the only types 40362306a36Sopenharmony_ci * that can create namespace objects. 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci if (ACPI_COMPARE_NAMESEG 40662306a36Sopenharmony_ci (acpi_gbl_root_table_list.tables[i].signature.ascii, 40762306a36Sopenharmony_ci ACPI_SIG_DSDT)) { 40862306a36Sopenharmony_ci status = AE_TYPE; 40962306a36Sopenharmony_ci break; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 41362306a36Sopenharmony_ci status = acpi_tb_unload_table(i); 41462306a36Sopenharmony_ci (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 41562306a36Sopenharmony_ci break; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 41962306a36Sopenharmony_ci return_ACPI_STATUS(status); 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_unload_parent_table) 42362306a36Sopenharmony_ci/******************************************************************************* 42462306a36Sopenharmony_ci * 42562306a36Sopenharmony_ci * FUNCTION: acpi_unload_table 42662306a36Sopenharmony_ci * 42762306a36Sopenharmony_ci * PARAMETERS: table_index - Index as returned by acpi_load_table 42862306a36Sopenharmony_ci * 42962306a36Sopenharmony_ci * RETURN: Status 43062306a36Sopenharmony_ci * 43162306a36Sopenharmony_ci * DESCRIPTION: Via the table_index representing an SSDT or OEMx table, unloads 43262306a36Sopenharmony_ci * the table and deletes all namespace objects associated with 43362306a36Sopenharmony_ci * that table. Unloading of the DSDT is not allowed. 43462306a36Sopenharmony_ci * Note: Mainly intended to support hotplug removal of SSDTs. 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci ******************************************************************************/ 43762306a36Sopenharmony_ciacpi_status acpi_unload_table(u32 table_index) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci acpi_status status; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_unload_table); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (table_index == 1) { 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* table_index==1 means DSDT is the owner. DSDT cannot be unloaded */ 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci return_ACPI_STATUS(AE_TYPE); 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci status = acpi_tb_unload_table(table_index); 45162306a36Sopenharmony_ci return_ACPI_STATUS(status); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_unload_table) 455