Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16 414 lines 12 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: nsload - namespace loading/expanding/contracting procedures 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2006, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44#include <acpi/acpi.h> 45#include <acpi/acnamesp.h> 46#include <acpi/acdispat.h> 47 48#define _COMPONENT ACPI_NAMESPACE 49ACPI_MODULE_NAME("nsload") 50 51/* Local prototypes */ 52static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type); 53 54#ifdef ACPI_FUTURE_IMPLEMENTATION 55acpi_status acpi_ns_unload_namespace(acpi_handle handle); 56 57static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); 58#endif 59 60#ifndef ACPI_NO_METHOD_EXECUTION 61/******************************************************************************* 62 * 63 * FUNCTION: acpi_ns_load_table 64 * 65 * PARAMETERS: table_desc - Descriptor for table to be loaded 66 * Node - Owning NS node 67 * 68 * RETURN: Status 69 * 70 * DESCRIPTION: Load one ACPI table into the namespace 71 * 72 ******************************************************************************/ 73 74acpi_status 75acpi_ns_load_table(struct acpi_table_desc *table_desc, 76 struct acpi_namespace_node *node) 77{ 78 acpi_status status; 79 80 ACPI_FUNCTION_TRACE("ns_load_table"); 81 82 /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ 83 84 if (! 85 (acpi_gbl_table_data[table_desc->type]. 86 flags & ACPI_TABLE_EXECUTABLE)) { 87 /* Just ignore this table */ 88 89 return_ACPI_STATUS(AE_OK); 90 } 91 92 /* Check validity of the AML start and length */ 93 94 if (!table_desc->aml_start) { 95 ACPI_ERROR((AE_INFO, "Null AML pointer")); 96 return_ACPI_STATUS(AE_BAD_PARAMETER); 97 } 98 99 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AML block at %p\n", 100 table_desc->aml_start)); 101 102 /* Ignore table if there is no AML contained within */ 103 104 if (!table_desc->aml_length) { 105 ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]", 106 table_desc->pointer->signature)); 107 return_ACPI_STATUS(AE_OK); 108 } 109 110 /* 111 * Parse the table and load the namespace with all named 112 * objects found within. Control methods are NOT parsed 113 * at this time. In fact, the control methods cannot be 114 * parsed until the entire namespace is loaded, because 115 * if a control method makes a forward reference (call) 116 * to another control method, we can't continue parsing 117 * because we don't know how many arguments to parse next! 118 */ 119 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 120 "**** Loading table into namespace ****\n")); 121 122 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 123 if (ACPI_FAILURE(status)) { 124 return_ACPI_STATUS(status); 125 } 126 127 status = acpi_ns_parse_table(table_desc, node->child); 128 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 129 130 if (ACPI_FAILURE(status)) { 131 return_ACPI_STATUS(status); 132 } 133 134 /* 135 * Now we can parse the control methods. We always parse 136 * them here for a sanity check, and if configured for 137 * just-in-time parsing, we delete the control method 138 * parse trees. 139 */ 140 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 141 "**** Begin Table Method Parsing and Object Initialization ****\n")); 142 143 status = acpi_ds_initialize_objects(table_desc, node); 144 145 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 146 "**** Completed Table Method Parsing and Object Initialization ****\n")); 147 148 return_ACPI_STATUS(status); 149} 150 151/******************************************************************************* 152 * 153 * FUNCTION: acpi_ns_load_table_by_type 154 * 155 * PARAMETERS: table_type - Id of the table type to load 156 * 157 * RETURN: Status 158 * 159 * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables 160 * of the given type are loaded. The mechanism allows this 161 * routine to be called repeatedly. 162 * 163 ******************************************************************************/ 164 165static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type) 166{ 167 u32 i; 168 acpi_status status; 169 struct acpi_table_desc *table_desc; 170 171 ACPI_FUNCTION_TRACE("ns_load_table_by_type"); 172 173 status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 174 if (ACPI_FAILURE(status)) { 175 return_ACPI_STATUS(status); 176 } 177 178 /* 179 * Table types supported are: 180 * DSDT (one), SSDT/PSDT (multiple) 181 */ 182 switch (table_type) { 183 case ACPI_TABLE_DSDT: 184 185 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n")); 186 187 table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; 188 189 /* If table already loaded into namespace, just return */ 190 191 if (table_desc->loaded_into_namespace) { 192 goto unlock_and_exit; 193 } 194 195 /* Now load the single DSDT */ 196 197 status = acpi_ns_load_table(table_desc, acpi_gbl_root_node); 198 if (ACPI_SUCCESS(status)) { 199 table_desc->loaded_into_namespace = TRUE; 200 } 201 break; 202 203 case ACPI_TABLE_SSDT: 204 case ACPI_TABLE_PSDT: 205 206 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 207 "Namespace load: %d SSDT or PSDTs\n", 208 acpi_gbl_table_lists[table_type].count)); 209 210 /* 211 * Traverse list of SSDT or PSDT tables 212 */ 213 table_desc = acpi_gbl_table_lists[table_type].next; 214 for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) { 215 /* 216 * Only attempt to load table into namespace if it is not 217 * already loaded! 218 */ 219 if (!table_desc->loaded_into_namespace) { 220 status = 221 acpi_ns_load_table(table_desc, 222 acpi_gbl_root_node); 223 if (ACPI_FAILURE(status)) { 224 break; 225 } 226 227 table_desc->loaded_into_namespace = TRUE; 228 } 229 230 table_desc = table_desc->next; 231 } 232 break; 233 234 default: 235 status = AE_SUPPORT; 236 break; 237 } 238 239 unlock_and_exit: 240 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 241 return_ACPI_STATUS(status); 242} 243 244/******************************************************************************* 245 * 246 * FUNCTION: acpi_load_namespace 247 * 248 * PARAMETERS: None 249 * 250 * RETURN: Status 251 * 252 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. 253 * (DSDT points to either the BIOS or a buffer.) 254 * 255 ******************************************************************************/ 256 257acpi_status acpi_ns_load_namespace(void) 258{ 259 acpi_status status; 260 261 ACPI_FUNCTION_TRACE("acpi_load_name_space"); 262 263 /* There must be at least a DSDT installed */ 264 265 if (acpi_gbl_DSDT == NULL) { 266 ACPI_ERROR((AE_INFO, "DSDT is not in memory")); 267 return_ACPI_STATUS(AE_NO_ACPI_TABLES); 268 } 269 270 /* 271 * Load the namespace. The DSDT is required, 272 * but the SSDT and PSDT tables are optional. 273 */ 274 status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT); 275 if (ACPI_FAILURE(status)) { 276 return_ACPI_STATUS(status); 277 } 278 279 /* Ignore exceptions from these */ 280 281 (void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT); 282 (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT); 283 284 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 285 "ACPI Namespace successfully loaded at root %p\n", 286 acpi_gbl_root_node)); 287 288 return_ACPI_STATUS(status); 289} 290 291#ifdef ACPI_FUTURE_IMPLEMENTATION 292/******************************************************************************* 293 * 294 * FUNCTION: acpi_ns_delete_subtree 295 * 296 * PARAMETERS: start_handle - Handle in namespace where search begins 297 * 298 * RETURNS Status 299 * 300 * DESCRIPTION: Walks the namespace starting at the given handle and deletes 301 * all objects, entries, and scopes in the entire subtree. 302 * 303 * Namespace/Interpreter should be locked or the subsystem should 304 * be in shutdown before this routine is called. 305 * 306 ******************************************************************************/ 307 308static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) 309{ 310 acpi_status status; 311 acpi_handle child_handle; 312 acpi_handle parent_handle; 313 acpi_handle next_child_handle; 314 acpi_handle dummy; 315 u32 level; 316 317 ACPI_FUNCTION_TRACE("ns_delete_subtree"); 318 319 parent_handle = start_handle; 320 child_handle = NULL; 321 level = 1; 322 323 /* 324 * Traverse the tree of objects until we bubble back up 325 * to where we started. 326 */ 327 while (level > 0) { 328 /* Attempt to get the next object in this scope */ 329 330 status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, 331 child_handle, &next_child_handle); 332 333 child_handle = next_child_handle; 334 335 /* Did we get a new object? */ 336 337 if (ACPI_SUCCESS(status)) { 338 /* Check if this object has any children */ 339 340 if (ACPI_SUCCESS 341 (acpi_get_next_object 342 (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { 343 /* 344 * There is at least one child of this object, 345 * visit the object 346 */ 347 level++; 348 parent_handle = child_handle; 349 child_handle = NULL; 350 } 351 } else { 352 /* 353 * No more children in this object, go back up to 354 * the object's parent 355 */ 356 level--; 357 358 /* Delete all children now */ 359 360 acpi_ns_delete_children(child_handle); 361 362 child_handle = parent_handle; 363 status = acpi_get_parent(parent_handle, &parent_handle); 364 if (ACPI_FAILURE(status)) { 365 return_ACPI_STATUS(status); 366 } 367 } 368 } 369 370 /* Now delete the starting object, and we are done */ 371 372 acpi_ns_delete_node(child_handle); 373 374 return_ACPI_STATUS(AE_OK); 375} 376 377/******************************************************************************* 378 * 379 * FUNCTION: acpi_ns_unload_name_space 380 * 381 * PARAMETERS: Handle - Root of namespace subtree to be deleted 382 * 383 * RETURN: Status 384 * 385 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking 386 * event. Deletes an entire subtree starting from (and 387 * including) the given handle. 388 * 389 ******************************************************************************/ 390 391acpi_status acpi_ns_unload_namespace(acpi_handle handle) 392{ 393 acpi_status status; 394 395 ACPI_FUNCTION_TRACE("ns_unload_name_space"); 396 397 /* Parameter validation */ 398 399 if (!acpi_gbl_root_node) { 400 return_ACPI_STATUS(AE_NO_NAMESPACE); 401 } 402 403 if (!handle) { 404 return_ACPI_STATUS(AE_BAD_PARAMETER); 405 } 406 407 /* This function does the real work */ 408 409 status = acpi_ns_delete_subtree(handle); 410 411 return_ACPI_STATUS(status); 412} 413#endif 414#endif