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