File Index
Files and directories
Sign in
FILE

nsload.c

File preview with syntax highlighting.

linux-6.19.14/drivers/acpi/acpica/nsload.c C
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Module Name: nsload - namespace loading/expanding/contracting procedures
  5 *
  6 * Copyright (C) 2000 - 2025, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#include <acpi/acpi.h>
 11#include "accommon.h"
 12#include "acnamesp.h"
 13#include "acdispat.h"
 14#include "actables.h"
 15#include "acinterp.h"
 16
 17#define _COMPONENT          ACPI_NAMESPACE
 18ACPI_MODULE_NAME("nsload")
 19
 20/* Local prototypes */
 21#ifdef ACPI_FUTURE_IMPLEMENTATION
 22acpi_status acpi_ns_unload_namespace(acpi_handle handle);
 23
 24static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
 25#endif
 26
 27/*******************************************************************************
 28 *
 29 * FUNCTION:    acpi_ns_load_table
 30 *
 31 * PARAMETERS:  table_index     - Index for table to be loaded
 32 *              node            - Owning NS node
 33 *
 34 * RETURN:      Status
 35 *
 36 * DESCRIPTION: Load one ACPI table into the namespace
 37 *
 38 ******************************************************************************/
 39
 40acpi_status
 41acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
 42{
 43	acpi_status status;
 44
 45	ACPI_FUNCTION_TRACE(ns_load_table);
 46
 47	/* If table already loaded into namespace, just return */
 48
 49	if (acpi_tb_is_table_loaded(table_index)) {
 50		status = AE_ALREADY_EXISTS;
 51		goto unlock;
 52	}
 53
 54	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 55			  "**** Loading table into namespace ****\n"));
 56
 57	status = acpi_tb_allocate_owner_id(table_index);
 58	if (ACPI_FAILURE(status)) {
 59		goto unlock;
 60	}
 61
 62	/*
 63	 * Parse the table and load the namespace with all named
 64	 * objects found within. Control methods are NOT parsed
 65	 * at this time. In fact, the control methods cannot be
 66	 * parsed until the entire namespace is loaded, because
 67	 * if a control method makes a forward reference (call)
 68	 * to another control method, we can't continue parsing
 69	 * because we don't know how many arguments to parse next!
 70	 */
 71	status = acpi_ns_parse_table(table_index, node);
 72	if (ACPI_SUCCESS(status)) {
 73		acpi_tb_set_table_loaded_flag(table_index, TRUE);
 74	} else {
 75		/*
 76		 * On error, delete any namespace objects created by this table.
 77		 * We cannot initialize these objects, so delete them. There are
 78		 * a couple of especially bad cases:
 79		 * AE_ALREADY_EXISTS - namespace collision.
 80		 * AE_NOT_FOUND - the target of a Scope operator does not
 81		 * exist. This target of Scope must already exist in the
 82		 * namespace, as per the ACPI specification.
 83		 */
 84		acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
 85						  tables[table_index].owner_id);
 86
 87		acpi_tb_release_owner_id(table_index);
 88		return_ACPI_STATUS(status);
 89	}
 90
 91unlock:
 92	if (ACPI_FAILURE(status)) {
 93		return_ACPI_STATUS(status);
 94	}
 95
 96	/*
 97	 * Now we can parse the control methods. We always parse
 98	 * them here for a sanity check, and if configured for
 99	 * just-in-time parsing, we delete the control method
100	 * parse trees.
101	 */
102	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
103			  "**** Begin Table Object Initialization\n"));
104
105	acpi_ex_enter_interpreter();
106	status = acpi_ds_initialize_objects(table_index, node);
107	acpi_ex_exit_interpreter();
108
109	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
110			  "**** Completed Table Object Initialization\n"));
111
112	return_ACPI_STATUS(status);
113}
114
115#ifdef ACPI_OBSOLETE_FUNCTIONS
116/*******************************************************************************
117 *
118 * FUNCTION:    acpi_load_namespace
119 *
120 * PARAMETERS:  None
121 *
122 * RETURN:      Status
123 *
124 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
125 *              (DSDT points to either the BIOS or a buffer.)
126 *
127 ******************************************************************************/
128
129acpi_status acpi_ns_load_namespace(void)
130{
131	acpi_status status;
132
133	ACPI_FUNCTION_TRACE(acpi_load_name_space);
134
135	/* There must be at least a DSDT installed */
136
137	if (acpi_gbl_DSDT == NULL) {
138		ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
139		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
140	}
141
142	/*
143	 * Load the namespace. The DSDT is required,
144	 * but the SSDT and PSDT tables are optional.
145	 */
146	status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
147	if (ACPI_FAILURE(status)) {
148		return_ACPI_STATUS(status);
149	}
150
151	/* Ignore exceptions from these */
152
153	(void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
154	(void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
155
156	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
157			      "ACPI Namespace successfully loaded at root %p\n",
158			      acpi_gbl_root_node));
159
160	return_ACPI_STATUS(status);
161}
162#endif
163
164#ifdef ACPI_FUTURE_IMPLEMENTATION
165/*******************************************************************************
166 *
167 * FUNCTION:    acpi_ns_delete_subtree
168 *
169 * PARAMETERS:  start_handle        - Handle in namespace where search begins
170 *
171 * RETURNS      Status
172 *
173 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
174 *              all objects, entries, and scopes in the entire subtree.
175 *
176 *              Namespace/Interpreter should be locked or the subsystem should
177 *              be in shutdown before this routine is called.
178 *
179 ******************************************************************************/
180
181static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
182{
183	acpi_status status;
184	acpi_handle child_handle;
185	acpi_handle parent_handle;
186	acpi_handle next_child_handle;
187	acpi_handle dummy;
188	u32 level;
189
190	ACPI_FUNCTION_TRACE(ns_delete_subtree);
191
192	parent_handle = start_handle;
193	child_handle = NULL;
194	level = 1;
195
196	/*
197	 * Traverse the tree of objects until we bubble back up
198	 * to where we started.
199	 */
200	while (level > 0) {
201
202		/* Attempt to get the next object in this scope */
203
204		status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
205					      child_handle, &next_child_handle);
206
207		child_handle = next_child_handle;
208
209		/* Did we get a new object? */
210
211		if (ACPI_SUCCESS(status)) {
212
213			/* Check if this object has any children */
214
215			if (ACPI_SUCCESS
216			    (acpi_get_next_object
217			     (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
218				/*
219				 * There is at least one child of this object,
220				 * visit the object
221				 */
222				level++;
223				parent_handle = child_handle;
224				child_handle = NULL;
225			}
226		} else {
227			/*
228			 * No more children in this object, go back up to
229			 * the object's parent
230			 */
231			level--;
232
233			/* Delete all children now */
234
235			acpi_ns_delete_children(child_handle);
236
237			child_handle = parent_handle;
238			status = acpi_get_parent(parent_handle, &parent_handle);
239			if (ACPI_FAILURE(status)) {
240				return_ACPI_STATUS(status);
241			}
242		}
243	}
244
245	/* Now delete the starting object, and we are done */
246
247	acpi_ns_remove_node(child_handle);
248	return_ACPI_STATUS(AE_OK);
249}
250
251/*******************************************************************************
252 *
253 *  FUNCTION:       acpi_ns_unload_name_space
254 *
255 *  PARAMETERS:     handle          - Root of namespace subtree to be deleted
256 *
257 *  RETURN:         Status
258 *
259 *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
260 *                  event. Deletes an entire subtree starting from (and
261 *                  including) the given handle.
262 *
263 ******************************************************************************/
264
265acpi_status acpi_ns_unload_namespace(acpi_handle handle)
266{
267	acpi_status status;
268
269	ACPI_FUNCTION_TRACE(ns_unload_name_space);
270
271	/* Parameter validation */
272
273	if (!acpi_gbl_root_node) {
274		return_ACPI_STATUS(AE_NO_NAMESPACE);
275	}
276
277	if (!handle) {
278		return_ACPI_STATUS(AE_BAD_PARAMETER);
279	}
280
281	/* This function does the real work */
282
283	status = acpi_ns_delete_subtree(handle);
284	return_ACPI_STATUS(status);
285}
286#endif
~/ Read-only file preview.