xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/tbxfload.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: tbxfload - Table load/unload external interfaces
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *****************************************************************************/
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define EXPORT_ACPI_INTERFACES
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <acpi/acpi.h>
13*4882a593Smuzhiyun #include "accommon.h"
14*4882a593Smuzhiyun #include "acnamesp.h"
15*4882a593Smuzhiyun #include "actables.h"
16*4882a593Smuzhiyun #include "acevents.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define _COMPONENT          ACPI_TABLES
19*4882a593Smuzhiyun ACPI_MODULE_NAME("tbxfload")
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /*******************************************************************************
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * FUNCTION:    acpi_load_tables
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * PARAMETERS:  None
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  * RETURN:      Status
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  ******************************************************************************/
acpi_load_tables(void)32*4882a593Smuzhiyun acpi_status ACPI_INIT_FUNCTION acpi_load_tables(void)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	acpi_status status;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_load_tables);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	/*
39*4882a593Smuzhiyun 	 * Install the default operation region handlers. These are the
40*4882a593Smuzhiyun 	 * handlers that are defined by the ACPI specification to be
41*4882a593Smuzhiyun 	 * "always accessible" -- namely, system_memory, system_IO, and
42*4882a593Smuzhiyun 	 * PCI_Config. This also means that no _REG methods need to be
43*4882a593Smuzhiyun 	 * run for these address spaces. We need to have these handlers
44*4882a593Smuzhiyun 	 * installed before any AML code can be executed, especially any
45*4882a593Smuzhiyun 	 * module-level code (11/2015).
46*4882a593Smuzhiyun 	 * Note that we allow OSPMs to install their own region handlers
47*4882a593Smuzhiyun 	 * between acpi_initialize_subsystem() and acpi_load_tables() to use
48*4882a593Smuzhiyun 	 * their customized default region handlers.
49*4882a593Smuzhiyun 	 */
50*4882a593Smuzhiyun 	status = acpi_ev_install_region_handlers();
51*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
52*4882a593Smuzhiyun 		ACPI_EXCEPTION((AE_INFO, status,
53*4882a593Smuzhiyun 				"During Region initialization"));
54*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
55*4882a593Smuzhiyun 	}
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	/* Load the namespace from the tables */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	status = acpi_tb_load_namespace();
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	/* Don't let single failures abort the load */
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (status == AE_CTRL_TERMINATE) {
64*4882a593Smuzhiyun 		status = AE_OK;
65*4882a593Smuzhiyun 	}
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
68*4882a593Smuzhiyun 		ACPI_EXCEPTION((AE_INFO, status,
69*4882a593Smuzhiyun 				"While loading namespace from ACPI tables"));
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	/*
73*4882a593Smuzhiyun 	 * Initialize the objects in the namespace that remain uninitialized.
74*4882a593Smuzhiyun 	 * This runs the executable AML that may be part of the declaration of
75*4882a593Smuzhiyun 	 * these name objects:
76*4882a593Smuzhiyun 	 *     operation_regions, buffer_fields, Buffers, and Packages.
77*4882a593Smuzhiyun 	 *
78*4882a593Smuzhiyun 	 */
79*4882a593Smuzhiyun 	status = acpi_ns_initialize_objects();
80*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
81*4882a593Smuzhiyun 		acpi_gbl_namespace_initialized = TRUE;
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)87*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /*******************************************************************************
90*4882a593Smuzhiyun  *
91*4882a593Smuzhiyun  * FUNCTION:    acpi_tb_load_namespace
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * PARAMETERS:  None
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * RETURN:      Status
96*4882a593Smuzhiyun  *
97*4882a593Smuzhiyun  * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
98*4882a593Smuzhiyun  *              the RSDT/XSDT.
99*4882a593Smuzhiyun  *
100*4882a593Smuzhiyun  ******************************************************************************/
101*4882a593Smuzhiyun acpi_status acpi_tb_load_namespace(void)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	acpi_status status;
104*4882a593Smuzhiyun 	u32 i;
105*4882a593Smuzhiyun 	struct acpi_table_header *new_dsdt;
106*4882a593Smuzhiyun 	struct acpi_table_desc *table;
107*4882a593Smuzhiyun 	u32 tables_loaded = 0;
108*4882a593Smuzhiyun 	u32 tables_failed = 0;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(tb_load_namespace);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/*
115*4882a593Smuzhiyun 	 * Load the namespace. The DSDT is required, but any SSDT and
116*4882a593Smuzhiyun 	 * PSDT tables are optional. Verify the DSDT.
117*4882a593Smuzhiyun 	 */
118*4882a593Smuzhiyun 	table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index];
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (!acpi_gbl_root_table_list.current_table_count ||
121*4882a593Smuzhiyun 	    !ACPI_COMPARE_NAMESEG(table->signature.ascii, ACPI_SIG_DSDT) ||
122*4882a593Smuzhiyun 	    ACPI_FAILURE(acpi_tb_validate_table(table))) {
123*4882a593Smuzhiyun 		status = AE_NO_ACPI_TABLES;
124*4882a593Smuzhiyun 		goto unlock_and_exit;
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	/*
128*4882a593Smuzhiyun 	 * Save the DSDT pointer for simple access. This is the mapped memory
129*4882a593Smuzhiyun 	 * address. We must take care here because the address of the .Tables
130*4882a593Smuzhiyun 	 * array can change dynamically as tables are loaded at run-time. Note:
131*4882a593Smuzhiyun 	 * .Pointer field is not validated until after call to acpi_tb_validate_table.
132*4882a593Smuzhiyun 	 */
133*4882a593Smuzhiyun 	acpi_gbl_DSDT = table->pointer;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	/*
136*4882a593Smuzhiyun 	 * Optionally copy the entire DSDT to local memory (instead of simply
137*4882a593Smuzhiyun 	 * mapping it.) There are some BIOSs that corrupt or replace the original
138*4882a593Smuzhiyun 	 * DSDT, creating the need for this option. Default is FALSE, do not copy
139*4882a593Smuzhiyun 	 * the DSDT.
140*4882a593Smuzhiyun 	 */
141*4882a593Smuzhiyun 	if (acpi_gbl_copy_dsdt_locally) {
142*4882a593Smuzhiyun 		new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index);
143*4882a593Smuzhiyun 		if (new_dsdt) {
144*4882a593Smuzhiyun 			acpi_gbl_DSDT = new_dsdt;
145*4882a593Smuzhiyun 		}
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	/*
149*4882a593Smuzhiyun 	 * Save the original DSDT header for detection of table corruption
150*4882a593Smuzhiyun 	 * and/or replacement of the DSDT from outside the OS.
151*4882a593Smuzhiyun 	 */
152*4882a593Smuzhiyun 	memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
153*4882a593Smuzhiyun 	       sizeof(struct acpi_table_header));
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/* Load and parse tables */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
158*4882a593Smuzhiyun 	status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node);
159*4882a593Smuzhiyun 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
160*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
161*4882a593Smuzhiyun 		ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
162*4882a593Smuzhiyun 		tables_failed++;
163*4882a593Smuzhiyun 	} else {
164*4882a593Smuzhiyun 		tables_loaded++;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
170*4882a593Smuzhiyun 		table = &acpi_gbl_root_table_list.tables[i];
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 		if (!table->address ||
173*4882a593Smuzhiyun 		    (!ACPI_COMPARE_NAMESEG
174*4882a593Smuzhiyun 		     (table->signature.ascii, ACPI_SIG_SSDT)
175*4882a593Smuzhiyun 		     && !ACPI_COMPARE_NAMESEG(table->signature.ascii,
176*4882a593Smuzhiyun 					      ACPI_SIG_PSDT)
177*4882a593Smuzhiyun 		     && !ACPI_COMPARE_NAMESEG(table->signature.ascii,
178*4882a593Smuzhiyun 					      ACPI_SIG_OSDT))
179*4882a593Smuzhiyun 		    || ACPI_FAILURE(acpi_tb_validate_table(table))) {
180*4882a593Smuzhiyun 			continue;
181*4882a593Smuzhiyun 		}
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 		/* Ignore errors while loading tables, get as many as possible */
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
186*4882a593Smuzhiyun 		status = acpi_ns_load_table(i, acpi_gbl_root_node);
187*4882a593Smuzhiyun 		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
188*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
189*4882a593Smuzhiyun 			ACPI_EXCEPTION((AE_INFO, status,
190*4882a593Smuzhiyun 					"(%4.4s:%8.8s) while loading table",
191*4882a593Smuzhiyun 					table->signature.ascii,
192*4882a593Smuzhiyun 					table->pointer->oem_table_id));
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 			tables_failed++;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
197*4882a593Smuzhiyun 					      "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n",
198*4882a593Smuzhiyun 					      table->signature.ascii,
199*4882a593Smuzhiyun 					      table->pointer->oem_table_id));
200*4882a593Smuzhiyun 		} else {
201*4882a593Smuzhiyun 			tables_loaded++;
202*4882a593Smuzhiyun 		}
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if (!tables_failed) {
206*4882a593Smuzhiyun 		ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded", tables_loaded));
207*4882a593Smuzhiyun 	} else {
208*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
209*4882a593Smuzhiyun 			    "%u table load failures, %u successful",
210*4882a593Smuzhiyun 			    tables_failed, tables_loaded));
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		/* Indicate at least one failure */
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 		status = AE_CTRL_TERMINATE;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun #ifdef ACPI_APPLICATION
218*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "\n"));
219*4882a593Smuzhiyun #endif
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun unlock_and_exit:
222*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
223*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun /*******************************************************************************
227*4882a593Smuzhiyun  *
228*4882a593Smuzhiyun  * FUNCTION:    acpi_install_table
229*4882a593Smuzhiyun  *
230*4882a593Smuzhiyun  * PARAMETERS:  address             - Address of the ACPI table to be installed.
231*4882a593Smuzhiyun  *              physical            - Whether the address is a physical table
232*4882a593Smuzhiyun  *                                    address or not
233*4882a593Smuzhiyun  *
234*4882a593Smuzhiyun  * RETURN:      Status
235*4882a593Smuzhiyun  *
236*4882a593Smuzhiyun  * DESCRIPTION: Dynamically install an ACPI table.
237*4882a593Smuzhiyun  *              Note: This function should only be invoked after
238*4882a593Smuzhiyun  *                    acpi_initialize_tables() and before acpi_load_tables().
239*4882a593Smuzhiyun  *
240*4882a593Smuzhiyun  ******************************************************************************/
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun acpi_status ACPI_INIT_FUNCTION
acpi_install_table(acpi_physical_address address,u8 physical)243*4882a593Smuzhiyun acpi_install_table(acpi_physical_address address, u8 physical)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	acpi_status status;
246*4882a593Smuzhiyun 	u8 flags;
247*4882a593Smuzhiyun 	u32 table_index;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_install_table);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (physical) {
252*4882a593Smuzhiyun 		flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
253*4882a593Smuzhiyun 	} else {
254*4882a593Smuzhiyun 		flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	status = acpi_tb_install_standard_table(address, flags,
258*4882a593Smuzhiyun 						FALSE, FALSE, &table_index);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)263*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun /*******************************************************************************
266*4882a593Smuzhiyun  *
267*4882a593Smuzhiyun  * FUNCTION:    acpi_load_table
268*4882a593Smuzhiyun  *
269*4882a593Smuzhiyun  * PARAMETERS:  table               - Pointer to a buffer containing the ACPI
270*4882a593Smuzhiyun  *                                    table to be loaded.
271*4882a593Smuzhiyun  *              table_idx           - Pointer to a u32 for storing the table
272*4882a593Smuzhiyun  *                                    index, might be NULL
273*4882a593Smuzhiyun  *
274*4882a593Smuzhiyun  * RETURN:      Status
275*4882a593Smuzhiyun  *
276*4882a593Smuzhiyun  * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
277*4882a593Smuzhiyun  *              be a valid ACPI table with a valid ACPI table header.
278*4882a593Smuzhiyun  *              Note1: Mainly intended to support hotplug addition of SSDTs.
279*4882a593Smuzhiyun  *              Note2: Does not copy the incoming table. User is responsible
280*4882a593Smuzhiyun  *              to ensure that the table is not deleted or unmapped.
281*4882a593Smuzhiyun  *
282*4882a593Smuzhiyun  ******************************************************************************/
283*4882a593Smuzhiyun acpi_status acpi_load_table(struct acpi_table_header *table, u32 *table_idx)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	acpi_status status;
286*4882a593Smuzhiyun 	u32 table_index;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_load_table);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	/* Parameter validation */
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	if (!table) {
293*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PARAMETER);
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	/* Install the table and load it into the namespace */
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
299*4882a593Smuzhiyun 	status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
300*4882a593Smuzhiyun 						ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
301*4882a593Smuzhiyun 						FALSE, &table_index);
302*4882a593Smuzhiyun 	if (table_idx) {
303*4882a593Smuzhiyun 		*table_idx = table_index;
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 		/* Complete the initialization/resolution of new objects */
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 		acpi_ns_initialize_objects();
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_load_table)316*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_load_table)
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /*******************************************************************************
319*4882a593Smuzhiyun  *
320*4882a593Smuzhiyun  * FUNCTION:    acpi_unload_parent_table
321*4882a593Smuzhiyun  *
322*4882a593Smuzhiyun  * PARAMETERS:  object              - Handle to any namespace object owned by
323*4882a593Smuzhiyun  *                                    the table to be unloaded
324*4882a593Smuzhiyun  *
325*4882a593Smuzhiyun  * RETURN:      Status
326*4882a593Smuzhiyun  *
327*4882a593Smuzhiyun  * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
328*4882a593Smuzhiyun  *              the table and deletes all namespace objects associated with
329*4882a593Smuzhiyun  *              that table. Unloading of the DSDT is not allowed.
330*4882a593Smuzhiyun  *              Note: Mainly intended to support hotplug removal of SSDTs.
331*4882a593Smuzhiyun  *
332*4882a593Smuzhiyun  ******************************************************************************/
333*4882a593Smuzhiyun acpi_status acpi_unload_parent_table(acpi_handle object)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	struct acpi_namespace_node *node =
336*4882a593Smuzhiyun 	    ACPI_CAST_PTR(struct acpi_namespace_node, object);
337*4882a593Smuzhiyun 	acpi_status status = AE_NOT_EXIST;
338*4882a593Smuzhiyun 	acpi_owner_id owner_id;
339*4882a593Smuzhiyun 	u32 i;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_unload_parent_table);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* Parameter validation */
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	if (!object) {
346*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PARAMETER);
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	/*
350*4882a593Smuzhiyun 	 * The node owner_id is currently the same as the parent table ID.
351*4882a593Smuzhiyun 	 * However, this could change in the future.
352*4882a593Smuzhiyun 	 */
353*4882a593Smuzhiyun 	owner_id = node->owner_id;
354*4882a593Smuzhiyun 	if (!owner_id) {
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		/* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_TYPE);
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* Must acquire the table lock during this operation */
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
364*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
365*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/* Find the table in the global table list */
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
371*4882a593Smuzhiyun 		if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) {
372*4882a593Smuzhiyun 			continue;
373*4882a593Smuzhiyun 		}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 		/*
376*4882a593Smuzhiyun 		 * Allow unload of SSDT and OEMx tables only. Do not allow unload
377*4882a593Smuzhiyun 		 * of the DSDT. No other types of tables should get here, since
378*4882a593Smuzhiyun 		 * only these types can contain AML and thus are the only types
379*4882a593Smuzhiyun 		 * that can create namespace objects.
380*4882a593Smuzhiyun 		 */
381*4882a593Smuzhiyun 		if (ACPI_COMPARE_NAMESEG
382*4882a593Smuzhiyun 		    (acpi_gbl_root_table_list.tables[i].signature.ascii,
383*4882a593Smuzhiyun 		     ACPI_SIG_DSDT)) {
384*4882a593Smuzhiyun 			status = AE_TYPE;
385*4882a593Smuzhiyun 			break;
386*4882a593Smuzhiyun 		}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
389*4882a593Smuzhiyun 		status = acpi_tb_unload_table(i);
390*4882a593Smuzhiyun 		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
391*4882a593Smuzhiyun 		break;
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
395*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)398*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)
399*4882a593Smuzhiyun /*******************************************************************************
400*4882a593Smuzhiyun  *
401*4882a593Smuzhiyun  * FUNCTION:    acpi_unload_table
402*4882a593Smuzhiyun  *
403*4882a593Smuzhiyun  * PARAMETERS:  table_index         - Index as returned by acpi_load_table
404*4882a593Smuzhiyun  *
405*4882a593Smuzhiyun  * RETURN:      Status
406*4882a593Smuzhiyun  *
407*4882a593Smuzhiyun  * DESCRIPTION: Via the table_index representing an SSDT or OEMx table, unloads
408*4882a593Smuzhiyun  *              the table and deletes all namespace objects associated with
409*4882a593Smuzhiyun  *              that table. Unloading of the DSDT is not allowed.
410*4882a593Smuzhiyun  *              Note: Mainly intended to support hotplug removal of SSDTs.
411*4882a593Smuzhiyun  *
412*4882a593Smuzhiyun  ******************************************************************************/
413*4882a593Smuzhiyun acpi_status acpi_unload_table(u32 table_index)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun 	acpi_status status;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_unload_table);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	if (table_index == 1) {
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 		/* table_index==1 means DSDT is the owner. DSDT cannot be unloaded */
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_TYPE);
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	status = acpi_tb_unload_table(table_index);
427*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_unload_table)
431