linux/drivers/acpi/acpica/nsload.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: nsload - namespace loading/expanding/contracting procedures
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2015, Intel Corp.
   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 "accommon.h"
  46#include "acnamesp.h"
  47#include "acdispat.h"
  48#include "actables.h"
  49
  50#define _COMPONENT          ACPI_NAMESPACE
  51ACPI_MODULE_NAME("nsload")
  52
  53/* Local prototypes */
  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_index     - Index 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(u32 table_index, struct acpi_namespace_node *node)
  76{
  77        acpi_status status;
  78
  79        ACPI_FUNCTION_TRACE(ns_load_table);
  80
  81        /*
  82         * Parse the table and load the namespace with all named
  83         * objects found within. Control methods are NOT parsed
  84         * at this time. In fact, the control methods cannot be
  85         * parsed until the entire namespace is loaded, because
  86         * if a control method makes a forward reference (call)
  87         * to another control method, we can't continue parsing
  88         * because we don't know how many arguments to parse next!
  89         */
  90        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  91        if (ACPI_FAILURE(status)) {
  92                return_ACPI_STATUS(status);
  93        }
  94
  95        /* If table already loaded into namespace, just return */
  96
  97        if (acpi_tb_is_table_loaded(table_index)) {
  98                status = AE_ALREADY_EXISTS;
  99                goto unlock;
 100        }
 101
 102        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 103                          "**** Loading table into namespace ****\n"));
 104
 105        status = acpi_tb_allocate_owner_id(table_index);
 106        if (ACPI_FAILURE(status)) {
 107                goto unlock;
 108        }
 109
 110        status = acpi_ns_parse_table(table_index, node);
 111        if (ACPI_SUCCESS(status)) {
 112                acpi_tb_set_table_loaded_flag(table_index, TRUE);
 113        } else {
 114                (void)acpi_tb_release_owner_id(table_index);
 115        }
 116
 117unlock:
 118        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 119
 120        if (ACPI_FAILURE(status)) {
 121                return_ACPI_STATUS(status);
 122        }
 123
 124        /*
 125         * Now we can parse the control methods. We always parse
 126         * them here for a sanity check, and if configured for
 127         * just-in-time parsing, we delete the control method
 128         * parse trees.
 129         */
 130        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 131                          "**** Begin Table Object Initialization\n"));
 132
 133        status = acpi_ds_initialize_objects(table_index, node);
 134
 135        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 136                          "**** Completed Table Object Initialization\n"));
 137
 138        return_ACPI_STATUS(status);
 139}
 140
 141#ifdef ACPI_OBSOLETE_FUNCTIONS
 142/*******************************************************************************
 143 *
 144 * FUNCTION:    acpi_load_namespace
 145 *
 146 * PARAMETERS:  None
 147 *
 148 * RETURN:      Status
 149 *
 150 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
 151 *              (DSDT points to either the BIOS or a buffer.)
 152 *
 153 ******************************************************************************/
 154
 155acpi_status acpi_ns_load_namespace(void)
 156{
 157        acpi_status status;
 158
 159        ACPI_FUNCTION_TRACE(acpi_load_name_space);
 160
 161        /* There must be at least a DSDT installed */
 162
 163        if (acpi_gbl_DSDT == NULL) {
 164                ACPI_ERROR((AE_INFO, "DSDT is not in memory"));
 165                return_ACPI_STATUS(AE_NO_ACPI_TABLES);
 166        }
 167
 168        /*
 169         * Load the namespace. The DSDT is required,
 170         * but the SSDT and PSDT tables are optional.
 171         */
 172        status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
 173        if (ACPI_FAILURE(status)) {
 174                return_ACPI_STATUS(status);
 175        }
 176
 177        /* Ignore exceptions from these */
 178
 179        (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
 180        (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
 181
 182        ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
 183                              "ACPI Namespace successfully loaded at root %p\n",
 184                              acpi_gbl_root_node));
 185
 186        return_ACPI_STATUS(status);
 187}
 188#endif
 189
 190#ifdef ACPI_FUTURE_IMPLEMENTATION
 191/*******************************************************************************
 192 *
 193 * FUNCTION:    acpi_ns_delete_subtree
 194 *
 195 * PARAMETERS:  start_handle        - Handle in namespace where search begins
 196 *
 197 * RETURNS      Status
 198 *
 199 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
 200 *              all objects, entries, and scopes in the entire subtree.
 201 *
 202 *              Namespace/Interpreter should be locked or the subsystem should
 203 *              be in shutdown before this routine is called.
 204 *
 205 ******************************************************************************/
 206
 207static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
 208{
 209        acpi_status status;
 210        acpi_handle child_handle;
 211        acpi_handle parent_handle;
 212        acpi_handle next_child_handle;
 213        acpi_handle dummy;
 214        u32 level;
 215
 216        ACPI_FUNCTION_TRACE(ns_delete_subtree);
 217
 218        parent_handle = start_handle;
 219        child_handle = NULL;
 220        level = 1;
 221
 222        /*
 223         * Traverse the tree of objects until we bubble back up
 224         * to where we started.
 225         */
 226        while (level > 0) {
 227
 228                /* Attempt to get the next object in this scope */
 229
 230                status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
 231                                              child_handle, &next_child_handle);
 232
 233                child_handle = next_child_handle;
 234
 235                /* Did we get a new object? */
 236
 237                if (ACPI_SUCCESS(status)) {
 238
 239                        /* Check if this object has any children */
 240
 241                        if (ACPI_SUCCESS
 242                            (acpi_get_next_object
 243                             (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) {
 244                                /*
 245                                 * There is at least one child of this object,
 246                                 * visit the object
 247                                 */
 248                                level++;
 249                                parent_handle = child_handle;
 250                                child_handle = NULL;
 251                        }
 252                } else {
 253                        /*
 254                         * No more children in this object, go back up to
 255                         * the object's parent
 256                         */
 257                        level--;
 258
 259                        /* Delete all children now */
 260
 261                        acpi_ns_delete_children(child_handle);
 262
 263                        child_handle = parent_handle;
 264                        status = acpi_get_parent(parent_handle, &parent_handle);
 265                        if (ACPI_FAILURE(status)) {
 266                                return_ACPI_STATUS(status);
 267                        }
 268                }
 269        }
 270
 271        /* Now delete the starting object, and we are done */
 272
 273        acpi_ns_remove_node(child_handle);
 274        return_ACPI_STATUS(AE_OK);
 275}
 276
 277/*******************************************************************************
 278 *
 279 *  FUNCTION:       acpi_ns_unload_name_space
 280 *
 281 *  PARAMETERS:     handle          - Root of namespace subtree to be deleted
 282 *
 283 *  RETURN:         Status
 284 *
 285 *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
 286 *                  event. Deletes an entire subtree starting from (and
 287 *                  including) the given handle.
 288 *
 289 ******************************************************************************/
 290
 291acpi_status acpi_ns_unload_namespace(acpi_handle handle)
 292{
 293        acpi_status status;
 294
 295        ACPI_FUNCTION_TRACE(ns_unload_name_space);
 296
 297        /* Parameter validation */
 298
 299        if (!acpi_gbl_root_node) {
 300                return_ACPI_STATUS(AE_NO_NAMESPACE);
 301        }
 302
 303        if (!handle) {
 304                return_ACPI_STATUS(AE_BAD_PARAMETER);
 305        }
 306
 307        /* This function does the real work */
 308
 309        status = acpi_ns_delete_subtree(handle);
 310
 311        return_ACPI_STATUS(status);
 312}
 313#endif
 314#endif
 315