/******************************************************************************* * * FUNCTION: acpi_unload_table_id * * PARAMETERS: id - Owner ID of the table to be removed. * * RETURN: Status * * DESCRIPTION: This routine is used to force the unload of a table (by id) * ******************************************************************************/ acpi_status acpi_unload_table_id(acpi_owner_id id) { int i; acpi_status status = AE_NOT_EXIST; ACPI_FUNCTION_TRACE(acpi_unload_table_id); /* Find table in the global table list */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { if (id != acpi_gbl_root_table_list.tables[i].owner_id) { continue; } /* * Delete all namespace objects owned by this table. Note that these * objects can appear anywhere in the namespace by virtue of the AML * "Scope" operator. Thus, we need to track ownership by an ID, not * simply a position within the hierarchy */ acpi_tb_delete_namespace_by_owner(i); status = acpi_tb_release_owner_id(i); acpi_tb_set_table_loaded_flag(i, FALSE); break; } return_ACPI_STATUS(status); }
acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) { acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; u32 table_index; struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); /* * Validate the handle * Although the handle is partially validated in acpi_ex_reconfiguration(), * when it calls acpi_ex_resolve_operands(), the handle is more completely * validated here. */ if ((!ddb_handle) || (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Get the table index from the ddb_handle (acpi_size for 64-bit case) */ table_index = (u32) (acpi_size) table_desc->reference.object; /* Invoke table handler if present */ if (acpi_gbl_table_handler) { status = acpi_get_table_by_index(table_index, &table); if (ACPI_SUCCESS(status)) { (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, table, acpi_gbl_table_handler_context); } } /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ acpi_tb_delete_namespace_by_owner(table_index); (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); /* Table unloaded, remove a reference to the ddb_handle object */ acpi_ut_remove_reference(ddb_handle); return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) { acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; acpi_native_uint table_index; ACPI_FUNCTION_TRACE(ex_unload_table); /* * Validate the handle * Although the handle is partially validated in acpi_ex_reconfiguration(), * when it calls acpi_ex_resolve_operands(), the handle is more completely * validated here. */ if ((!ddb_handle) || (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Get the table index from the ddb_handle */ table_index = (acpi_native_uint) table_desc->reference.object; /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ acpi_tb_delete_namespace_by_owner(table_index); acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); /* Delete the table descriptor (ddb_handle) */ acpi_ut_remove_reference(table_desc); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_unload_parent_table * * PARAMETERS: object - Handle to any namespace object owned by * the table to be unloaded * * RETURN: Status * * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads * the table and deletes all namespace objects associated with * that table. Unloading of the DSDT is not allowed. * Note: Mainly intended to support hotplug removal of SSDTs. * ******************************************************************************/ acpi_status acpi_unload_parent_table(acpi_handle object) { struct acpi_namespace_node *node = ACPI_CAST_PTR(struct acpi_namespace_node, object); acpi_status status = AE_NOT_EXIST; acpi_owner_id owner_id; u32 i; ACPI_FUNCTION_TRACE(acpi_unload_parent_table); /* Parameter validation */ if (!object) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * The node owner_id is currently the same as the parent table ID. * However, this could change in the future. */ owner_id = node->owner_id; if (!owner_id) { /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */ return_ACPI_STATUS(AE_TYPE); } /* Must acquire the interpreter lock during this operation */ status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Find the table in the global table list */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) { continue; } /* * Allow unload of SSDT and OEMx tables only. Do not allow unload * of the DSDT. No other types of tables should get here, since * only these types can contain AML and thus are the only types * that can create namespace objects. */ if (ACPI_COMPARE_NAME (acpi_gbl_root_table_list.tables[i].signature.ascii, ACPI_SIG_DSDT)) { status = AE_TYPE; break; } /* Ensure the table is actually loaded */ if (!acpi_tb_is_table_loaded(i)) { status = AE_NOT_EXIST; break; } /* Invoke table handler if present */ if (acpi_gbl_table_handler) { (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, acpi_gbl_root_table_list. tables[i].pointer, acpi_gbl_table_handler_context); } /* * Delete all namespace objects owned by this table. Note that * these objects can appear anywhere in the namespace by virtue * of the AML "Scope" operator. Thus, we need to track ownership * by an ID, not simply a position within the hierarchy. */ status = acpi_tb_delete_namespace_by_owner(i); if (ACPI_FAILURE(status)) { break; } status = acpi_tb_release_owner_id(i); acpi_tb_set_table_loaded_flag(i, FALSE); break; } (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); return_ACPI_STATUS(status); }