Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
  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 "acinterp.h"
  47. #include "acnamesp.h"
  48. #include "actables.h"
  49. #include "acdispat.h"
  50. #include "acevents.h"
  51. #include "amlcode.h"
  52.  
  53. #define _COMPONENT          ACPI_EXECUTER
  54. ACPI_MODULE_NAME("exconfig")
  55.  
  56. /* Local prototypes */
  57. static acpi_status
  58. acpi_ex_add_table(u32 table_index,
  59.                   struct acpi_namespace_node *parent_node,
  60.                   union acpi_operand_object **ddb_handle);
  61.  
  62. static acpi_status
  63. acpi_ex_region_read(union acpi_operand_object *obj_desc,
  64.                     u32 length, u8 *buffer);
  65.  
  66. /*******************************************************************************
  67.  *
  68.  * FUNCTION:    acpi_ex_add_table
  69.  *
  70.  * PARAMETERS:  table               - Pointer to raw table
  71.  *              parent_node         - Where to load the table (scope)
  72.  *              ddb_handle          - Where to return the table handle.
  73.  *
  74.  * RETURN:      Status
  75.  *
  76.  * DESCRIPTION: Common function to Install and Load an ACPI table with a
  77.  *              returned table handle.
  78.  *
  79.  ******************************************************************************/
  80.  
  81. static acpi_status
  82. acpi_ex_add_table(u32 table_index,
  83.                   struct acpi_namespace_node *parent_node,
  84.                   union acpi_operand_object **ddb_handle)
  85. {
  86.         union acpi_operand_object *obj_desc;
  87.         acpi_status status;
  88.         acpi_owner_id owner_id;
  89.  
  90.         ACPI_FUNCTION_TRACE(ex_add_table);
  91.  
  92.         /* Create an object to be the table handle */
  93.  
  94.         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
  95.         if (!obj_desc) {
  96.                 return_ACPI_STATUS(AE_NO_MEMORY);
  97.         }
  98.  
  99.         /* Init the table handle */
  100.  
  101.         obj_desc->common.flags |= AOPOBJ_DATA_VALID;
  102.         obj_desc->reference.class = ACPI_REFCLASS_TABLE;
  103.         *ddb_handle = obj_desc;
  104.  
  105.         /* Install the new table into the local data structures */
  106.  
  107.         obj_desc->reference.value = table_index;
  108.  
  109.         /* Add the table to the namespace */
  110.  
  111.         status = acpi_ns_load_table(table_index, parent_node);
  112.         if (ACPI_FAILURE(status)) {
  113.                 acpi_ut_remove_reference(obj_desc);
  114.                 *ddb_handle = NULL;
  115.                 return_ACPI_STATUS(status);
  116.         }
  117.  
  118.         /* Execute any module-level code that was found in the table */
  119.  
  120.         acpi_ex_exit_interpreter();
  121.         acpi_ns_exec_module_code_list();
  122.         acpi_ex_enter_interpreter();
  123.  
  124.         /*
  125.          * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
  126.          * responsible for discovering any new wake GPEs by running _PRW methods
  127.          * that may have been loaded by this table.
  128.          */
  129.         status = acpi_tb_get_owner_id(table_index, &owner_id);
  130.         if (ACPI_SUCCESS(status)) {
  131.                 acpi_ev_update_gpes(owner_id);
  132.         }
  133.  
  134.         return_ACPI_STATUS(AE_OK);
  135. }
  136.  
  137. /*******************************************************************************
  138.  *
  139.  * FUNCTION:    acpi_ex_load_table_op
  140.  *
  141.  * PARAMETERS:  walk_state          - Current state with operands
  142.  *              return_desc         - Where to store the return object
  143.  *
  144.  * RETURN:      Status
  145.  *
  146.  * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
  147.  *
  148.  ******************************************************************************/
  149.  
  150. acpi_status
  151. acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
  152.                       union acpi_operand_object **return_desc)
  153. {
  154.         acpi_status status;
  155.         union acpi_operand_object **operand = &walk_state->operands[0];
  156.         struct acpi_namespace_node *parent_node;
  157.         struct acpi_namespace_node *start_node;
  158.         struct acpi_namespace_node *parameter_node = NULL;
  159.         union acpi_operand_object *ddb_handle;
  160.         struct acpi_table_header *table;
  161.         u32 table_index;
  162.  
  163.         ACPI_FUNCTION_TRACE(ex_load_table_op);
  164.  
  165.         /* Find the ACPI table in the RSDT/XSDT */
  166.  
  167.         status = acpi_tb_find_table(operand[0]->string.pointer,
  168.                                     operand[1]->string.pointer,
  169.                                     operand[2]->string.pointer, &table_index);
  170.         if (ACPI_FAILURE(status)) {
  171.                 if (status != AE_NOT_FOUND) {
  172.                         return_ACPI_STATUS(status);
  173.                 }
  174.  
  175.                 /* Table not found, return an Integer=0 and AE_OK */
  176.  
  177.                 ddb_handle = acpi_ut_create_integer_object((u64) 0);
  178.                 if (!ddb_handle) {
  179.                         return_ACPI_STATUS(AE_NO_MEMORY);
  180.                 }
  181.  
  182.                 *return_desc = ddb_handle;
  183.                 return_ACPI_STATUS(AE_OK);
  184.         }
  185.  
  186.         /* Default nodes */
  187.  
  188.         start_node = walk_state->scope_info->scope.node;
  189.         parent_node = acpi_gbl_root_node;
  190.  
  191.         /* root_path (optional parameter) */
  192.  
  193.         if (operand[3]->string.length > 0) {
  194.                 /*
  195.                  * Find the node referenced by the root_path_string. This is the
  196.                  * location within the namespace where the table will be loaded.
  197.                  */
  198.                 status =
  199.                     acpi_ns_get_node(start_node, operand[3]->string.pointer,
  200.                                      ACPI_NS_SEARCH_PARENT, &parent_node);
  201.                 if (ACPI_FAILURE(status)) {
  202.                         return_ACPI_STATUS(status);
  203.                 }
  204.         }
  205.  
  206.         /* parameter_path (optional parameter) */
  207.  
  208.         if (operand[4]->string.length > 0) {
  209.                 if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) &&
  210.                     (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) {
  211.                         /*
  212.                          * Path is not absolute, so it will be relative to the node
  213.                          * referenced by the root_path_string (or the NS root if omitted)
  214.                          */
  215.                         start_node = parent_node;
  216.                 }
  217.  
  218.                 /* Find the node referenced by the parameter_path_string */
  219.  
  220.                 status =
  221.                     acpi_ns_get_node(start_node, operand[4]->string.pointer,
  222.                                      ACPI_NS_SEARCH_PARENT, &parameter_node);
  223.                 if (ACPI_FAILURE(status)) {
  224.                         return_ACPI_STATUS(status);
  225.                 }
  226.         }
  227.  
  228.         /* Load the table into the namespace */
  229.  
  230.         status = acpi_ex_add_table(table_index, parent_node, &ddb_handle);
  231.         if (ACPI_FAILURE(status)) {
  232.                 return_ACPI_STATUS(status);
  233.         }
  234.  
  235.         /* Parameter Data (optional) */
  236.  
  237.         if (parameter_node) {
  238.  
  239.                 /* Store the parameter data into the optional parameter object */
  240.  
  241.                 status = acpi_ex_store(operand[5],
  242.                                        ACPI_CAST_PTR(union acpi_operand_object,
  243.                                                      parameter_node),
  244.                                        walk_state);
  245.                 if (ACPI_FAILURE(status)) {
  246.                         (void)acpi_ex_unload_table(ddb_handle);
  247.  
  248.                         acpi_ut_remove_reference(ddb_handle);
  249.                         return_ACPI_STATUS(status);
  250.                 }
  251.         }
  252.  
  253.         status = acpi_get_table_by_index(table_index, &table);
  254.         if (ACPI_SUCCESS(status)) {
  255.                 ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
  256.                 acpi_tb_print_table_header(0, table);
  257.         }
  258.  
  259.         /* Invoke table handler if present */
  260.  
  261.         if (acpi_gbl_table_handler) {
  262.                 (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
  263.                                              acpi_gbl_table_handler_context);
  264.         }
  265.  
  266.         *return_desc = ddb_handle;
  267.         return_ACPI_STATUS(status);
  268. }
  269.  
  270. /*******************************************************************************
  271.  *
  272.  * FUNCTION:    acpi_ex_region_read
  273.  *
  274.  * PARAMETERS:  obj_desc        - Region descriptor
  275.  *              length          - Number of bytes to read
  276.  *              buffer          - Pointer to where to put the data
  277.  *
  278.  * RETURN:      Status
  279.  *
  280.  * DESCRIPTION: Read data from an operation region. The read starts from the
  281.  *              beginning of the region.
  282.  *
  283.  ******************************************************************************/
  284.  
  285. static acpi_status
  286. acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
  287. {
  288.         acpi_status status;
  289.         u64 value;
  290.         u32 region_offset = 0;
  291.         u32 i;
  292.  
  293.         /* Bytewise reads */
  294.  
  295.         for (i = 0; i < length; i++) {
  296.                 status =
  297.                     acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
  298.                                                    region_offset, 8, &value);
  299.                 if (ACPI_FAILURE(status)) {
  300.                         return (status);
  301.                 }
  302.  
  303.                 *buffer = (u8)value;
  304.                 buffer++;
  305.                 region_offset++;
  306.         }
  307.  
  308.         return (AE_OK);
  309. }
  310.  
  311. /*******************************************************************************
  312.  *
  313.  * FUNCTION:    acpi_ex_load_op
  314.  *
  315.  * PARAMETERS:  obj_desc        - Region or Buffer/Field where the table will be
  316.  *                                obtained
  317.  *              target          - Where a handle to the table will be stored
  318.  *              walk_state      - Current state
  319.  *
  320.  * RETURN:      Status
  321.  *
  322.  * DESCRIPTION: Load an ACPI table from a field or operation region
  323.  *
  324.  * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
  325.  *       objects before this code is reached.
  326.  *
  327.  *       If source is an operation region, it must refer to system_memory, as
  328.  *       per the ACPI specification.
  329.  *
  330.  ******************************************************************************/
  331.  
  332. acpi_status
  333. acpi_ex_load_op(union acpi_operand_object *obj_desc,
  334.                 union acpi_operand_object *target,
  335.                 struct acpi_walk_state *walk_state)
  336. {
  337.         union acpi_operand_object *ddb_handle;
  338.         struct acpi_table_header *table_header;
  339.         struct acpi_table_header *table;
  340.         u32 table_index;
  341.         acpi_status status;
  342.         u32 length;
  343.  
  344.         ACPI_FUNCTION_TRACE(ex_load_op);
  345.  
  346.         /* Source Object can be either an op_region or a Buffer/Field */
  347.  
  348.         switch (obj_desc->common.type) {
  349.         case ACPI_TYPE_REGION:
  350.  
  351.                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  352.                                   "Load table from Region %p\n", obj_desc));
  353.  
  354.                 /* Region must be system_memory (from ACPI spec) */
  355.  
  356.                 if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
  357.                         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  358.                 }
  359.  
  360.                 /*
  361.                  * If the Region Address and Length have not been previously evaluated,
  362.                  * evaluate them now and save the results.
  363.                  */
  364.                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
  365.                         status = acpi_ds_get_region_arguments(obj_desc);
  366.                         if (ACPI_FAILURE(status)) {
  367.                                 return_ACPI_STATUS(status);
  368.                         }
  369.                 }
  370.  
  371.                 /* Get the table header first so we can get the table length */
  372.  
  373.                 table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
  374.                 if (!table_header) {
  375.                         return_ACPI_STATUS(AE_NO_MEMORY);
  376.                 }
  377.  
  378.                 status =
  379.                     acpi_ex_region_read(obj_desc,
  380.                                         sizeof(struct acpi_table_header),
  381.                                         ACPI_CAST_PTR(u8, table_header));
  382.                 length = table_header->length;
  383.                 ACPI_FREE(table_header);
  384.  
  385.                 if (ACPI_FAILURE(status)) {
  386.                         return_ACPI_STATUS(status);
  387.                 }
  388.  
  389.                 /* Must have at least an ACPI table header */
  390.  
  391.                 if (length < sizeof(struct acpi_table_header)) {
  392.                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
  393.                 }
  394.  
  395.                 /*
  396.                  * The original implementation simply mapped the table, with no copy.
  397.                  * However, the memory region is not guaranteed to remain stable and
  398.                  * we must copy the table to a local buffer. For example, the memory
  399.                  * region is corrupted after suspend on some machines. Dynamically
  400.                  * loaded tables are usually small, so this overhead is minimal.
  401.                  *
  402.                  * The latest implementation (5/2009) does not use a mapping at all.
  403.                  * We use the low-level operation region interface to read the table
  404.                  * instead of the obvious optimization of using a direct mapping.
  405.                  * This maintains a consistent use of operation regions across the
  406.                  * entire subsystem. This is important if additional processing must
  407.                  * be performed in the (possibly user-installed) operation region
  408.                  * handler. For example, acpi_exec and ASLTS depend on this.
  409.                  */
  410.  
  411.                 /* Allocate a buffer for the table */
  412.  
  413.                 table = ACPI_ALLOCATE(length);
  414.                 if (!table) {
  415.                         return_ACPI_STATUS(AE_NO_MEMORY);
  416.                 }
  417.  
  418.                 /* Read the entire table */
  419.  
  420.                 status = acpi_ex_region_read(obj_desc, length,
  421.                                              ACPI_CAST_PTR(u8, table));
  422.                 if (ACPI_FAILURE(status)) {
  423.                         ACPI_FREE(table);
  424.                         return_ACPI_STATUS(status);
  425.                 }
  426.                 break;
  427.  
  428.         case ACPI_TYPE_BUFFER:  /* Buffer or resolved region_field */
  429.  
  430.                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  431.                                   "Load table from Buffer or Field %p\n",
  432.                                   obj_desc));
  433.  
  434.                 /* Must have at least an ACPI table header */
  435.  
  436.                 if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
  437.                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
  438.                 }
  439.  
  440.                 /* Get the actual table length from the table header */
  441.  
  442.                 table_header =
  443.                     ACPI_CAST_PTR(struct acpi_table_header,
  444.                                   obj_desc->buffer.pointer);
  445.                 length = table_header->length;
  446.  
  447.                 /* Table cannot extend beyond the buffer */
  448.  
  449.                 if (length > obj_desc->buffer.length) {
  450.                         return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
  451.                 }
  452.                 if (length < sizeof(struct acpi_table_header)) {
  453.                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
  454.                 }
  455.  
  456.                 /*
  457.                  * Copy the table from the buffer because the buffer could be modified
  458.                  * or even deleted in the future
  459.                  */
  460.                 table = ACPI_ALLOCATE(length);
  461.                 if (!table) {
  462.                         return_ACPI_STATUS(AE_NO_MEMORY);
  463.                 }
  464.  
  465.                 memcpy(table, table_header, length);
  466.                 break;
  467.  
  468.         default:
  469.  
  470.                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  471.         }
  472.  
  473.         /* Install the new table into the local data structures */
  474.  
  475.         ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
  476.         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
  477.  
  478.         status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
  479.                                                 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
  480.                                                 TRUE, TRUE, &table_index);
  481.  
  482.         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
  483.         if (ACPI_FAILURE(status)) {
  484.  
  485.                 /* Delete allocated table buffer */
  486.  
  487.                 ACPI_FREE(table);
  488.                 return_ACPI_STATUS(status);
  489.         }
  490.  
  491.         /*
  492.          * Note: Now table is "INSTALLED", it must be validated before
  493.          * loading.
  494.          */
  495.         status =
  496.             acpi_tb_validate_table(&acpi_gbl_root_table_list.
  497.                                    tables[table_index]);
  498.         if (ACPI_FAILURE(status)) {
  499.                 return_ACPI_STATUS(status);
  500.         }
  501.  
  502.         /*
  503.          * Add the table to the namespace.
  504.          *
  505.          * Note: Load the table objects relative to the root of the namespace.
  506.          * This appears to go against the ACPI specification, but we do it for
  507.          * compatibility with other ACPI implementations.
  508.          */
  509.         status =
  510.             acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
  511.         if (ACPI_FAILURE(status)) {
  512.  
  513.                 /* On error, table_ptr was deallocated above */
  514.  
  515.                 return_ACPI_STATUS(status);
  516.         }
  517.  
  518.         /* Store the ddb_handle into the Target operand */
  519.  
  520.         status = acpi_ex_store(ddb_handle, target, walk_state);
  521.         if (ACPI_FAILURE(status)) {
  522.                 (void)acpi_ex_unload_table(ddb_handle);
  523.  
  524.                 /* table_ptr was deallocated above */
  525.  
  526.                 acpi_ut_remove_reference(ddb_handle);
  527.                 return_ACPI_STATUS(status);
  528.         }
  529.  
  530.         /* Remove the reference by added by acpi_ex_store above */
  531.  
  532.         acpi_ut_remove_reference(ddb_handle);
  533.  
  534.         /* Invoke table handler if present */
  535.  
  536.         if (acpi_gbl_table_handler) {
  537.                 (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
  538.                                              acpi_gbl_table_handler_context);
  539.         }
  540.  
  541.         return_ACPI_STATUS(status);
  542. }
  543.  
  544. /*******************************************************************************
  545.  *
  546.  * FUNCTION:    acpi_ex_unload_table
  547.  *
  548.  * PARAMETERS:  ddb_handle          - Handle to a previously loaded table
  549.  *
  550.  * RETURN:      Status
  551.  *
  552.  * DESCRIPTION: Unload an ACPI table
  553.  *
  554.  ******************************************************************************/
  555.  
  556. acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
  557. {
  558.         acpi_status status = AE_OK;
  559.         union acpi_operand_object *table_desc = ddb_handle;
  560.         u32 table_index;
  561.         struct acpi_table_header *table;
  562.  
  563.         ACPI_FUNCTION_TRACE(ex_unload_table);
  564.  
  565.         /*
  566.          * Temporarily emit a warning so that the ASL for the machine can be
  567.          * hopefully obtained. This is to say that the Unload() operator is
  568.          * extremely rare if not completely unused.
  569.          */
  570.         ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
  571.  
  572.         /*
  573.          * Validate the handle
  574.          * Although the handle is partially validated in acpi_ex_reconfiguration()
  575.          * when it calls acpi_ex_resolve_operands(), the handle is more completely
  576.          * validated here.
  577.          *
  578.          * Handle must be a valid operand object of type reference. Also, the
  579.          * ddb_handle must still be marked valid (table has not been previously
  580.          * unloaded)
  581.          */
  582.         if ((!ddb_handle) ||
  583.             (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
  584.             (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
  585.             (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
  586.                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  587.         }
  588.  
  589.         /* Get the table index from the ddb_handle */
  590.  
  591.         table_index = table_desc->reference.value;
  592.  
  593.         /* Ensure the table is still loaded */
  594.  
  595.         if (!acpi_tb_is_table_loaded(table_index)) {
  596.                 return_ACPI_STATUS(AE_NOT_EXIST);
  597.         }
  598.  
  599.         /* Invoke table handler if present */
  600.  
  601.         if (acpi_gbl_table_handler) {
  602.                 status = acpi_get_table_by_index(table_index, &table);
  603.                 if (ACPI_SUCCESS(status)) {
  604.                         (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
  605.                                                      table,
  606.                                                      acpi_gbl_table_handler_context);
  607.                 }
  608.         }
  609.  
  610.         /* Delete the portion of the namespace owned by this table */
  611.  
  612.         status = acpi_tb_delete_namespace_by_owner(table_index);
  613.         if (ACPI_FAILURE(status)) {
  614.                 return_ACPI_STATUS(status);
  615.         }
  616.  
  617.         (void)acpi_tb_release_owner_id(table_index);
  618.         acpi_tb_set_table_loaded_flag(table_index, FALSE);
  619.  
  620.         /*
  621.          * Invalidate the handle. We do this because the handle may be stored
  622.          * in a named object and may not be actually deleted until much later.
  623.          */
  624.         ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
  625.         return_ACPI_STATUS(AE_OK);
  626. }
  627.