summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-07 00:45:27 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-07 00:45:27 +0200
commit23a75c52bef3ed0b688e45e352ce26069bdfd97f (patch)
treed9f0348ad9031f8552f6de067c76a6da1e24b03c /drivers/acpi
parentACPICA: Tables: Fix invalid pointer accesses in acpi_tb_parse_root_table(). (diff)
parentMerge back earlier ACPICA material. (diff)
downloadlinux-23a75c52bef3ed0b688e45e352ce26069bdfd97f.tar.xz
linux-23a75c52bef3ed0b688e45e352ce26069bdfd97f.zip
Merge back earlier ACPICA material.
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/Makefile1
-rw-r--r--drivers/acpi/acpica/acapps.h170
-rw-r--r--drivers/acpi/acpica/acglobal.h9
-rw-r--r--drivers/acpi/acpica/aclocal.h8
-rw-r--r--drivers/acpi/acpica/actables.h60
-rw-r--r--drivers/acpi/acpica/acutils.h10
-rw-r--r--drivers/acpi/acpica/evmisc.c3
-rw-r--r--drivers/acpi/acpica/evsci.c2
-rw-r--r--drivers/acpi/acpica/evxface.c61
-rw-r--r--drivers/acpi/acpica/exconfig.c82
-rw-r--r--drivers/acpi/acpica/exdump.c4
-rw-r--r--drivers/acpi/acpica/tbdata.c723
-rw-r--r--drivers/acpi/acpica/tbfadt.c10
-rw-r--r--drivers/acpi/acpica/tbfind.c4
-rw-r--r--drivers/acpi/acpica/tbinstal.c837
-rw-r--r--drivers/acpi/acpica/tbutils.c171
-rw-r--r--drivers/acpi/acpica/tbxface.c18
-rw-r--r--drivers/acpi/acpica/tbxfload.c87
-rw-r--r--drivers/acpi/acpica/utdecode.c74
-rw-r--r--drivers/acpi/acpica/utstring.c2
-rw-r--r--drivers/acpi/osl.c11
21 files changed, 1531 insertions, 816 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index b7ed86a20427..8bb43f06e11f 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -135,6 +135,7 @@ acpi-y += \
rsxface.o
acpi-y += \
+ tbdata.o \
tbfadt.o \
tbfind.o \
tbinstal.o \
diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h
new file mode 100644
index 000000000000..8698ffba6f39
--- /dev/null
+++ b/drivers/acpi/acpica/acapps.h
@@ -0,0 +1,170 @@
+/******************************************************************************
+ *
+ * Module Name: acapps - common include for ACPI applications/tools
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _ACAPPS
+#define _ACAPPS
+
+/* Common info for tool signons */
+
+#define ACPICA_NAME "Intel ACPI Component Architecture"
+#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2014 Intel Corporation"
+
+#if ACPI_MACHINE_WIDTH == 64
+#define ACPI_WIDTH "-64"
+
+#elif ACPI_MACHINE_WIDTH == 32
+#define ACPI_WIDTH "-32"
+
+#else
+#error unknown ACPI_MACHINE_WIDTH
+#define ACPI_WIDTH "-??"
+
+#endif
+
+/* Macros for signons and file headers */
+
+#define ACPI_COMMON_SIGNON(utility_name) \
+ "\n%s\n%s version %8.8X%s [%s]\n%s\n\n", \
+ ACPICA_NAME, \
+ utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \
+ ACPICA_COPYRIGHT
+
+#define ACPI_COMMON_HEADER(utility_name, prefix) \
+ "%s%s\n%s%s version %8.8X%s [%s]\n%s%s\n%s\n", \
+ prefix, ACPICA_NAME, \
+ prefix, utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \
+ prefix, ACPICA_COPYRIGHT, \
+ prefix
+
+/* Macros for usage messages */
+
+#define ACPI_USAGE_HEADER(usage) \
+ printf ("Usage: %s\nOptions:\n", usage);
+
+#define ACPI_OPTION(name, description) \
+ printf (" %-18s%s\n", name, description);
+
+#define FILE_SUFFIX_DISASSEMBLY "dsl"
+#define ACPI_TABLE_FILE_SUFFIX ".dat"
+
+/*
+ * getopt
+ */
+int acpi_getopt(int argc, char **argv, char *opts);
+
+int acpi_getopt_argument(int argc, char **argv);
+
+extern int acpi_gbl_optind;
+extern int acpi_gbl_opterr;
+extern int acpi_gbl_sub_opt_char;
+extern char *acpi_gbl_optarg;
+
+/*
+ * cmfsize - Common get file size function
+ */
+u32 cm_get_file_size(FILE * file);
+
+#ifndef ACPI_DUMP_APP
+/*
+ * adisasm
+ */
+acpi_status
+ad_aml_disassemble(u8 out_to_file,
+ char *filename, char *prefix, char **out_filename);
+
+void ad_print_statistics(void);
+
+acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length);
+
+void ad_dump_tables(void);
+
+acpi_status ad_get_local_tables(void);
+
+acpi_status
+ad_parse_table(struct acpi_table_header *table,
+ acpi_owner_id * owner_id, u8 load_table, u8 external);
+
+acpi_status ad_display_tables(char *filename, struct acpi_table_header *table);
+
+acpi_status ad_display_statistics(void);
+
+/*
+ * adwalk
+ */
+void
+acpi_dm_cross_reference_namespace(union acpi_parse_object *parse_tree_root,
+ struct acpi_namespace_node *namespace_root,
+ acpi_owner_id owner_id);
+
+void acpi_dm_dump_tree(union acpi_parse_object *origin);
+
+void acpi_dm_find_orphan_methods(union acpi_parse_object *origin);
+
+void
+acpi_dm_finish_namespace_load(union acpi_parse_object *parse_tree_root,
+ struct acpi_namespace_node *namespace_root,
+ acpi_owner_id owner_id);
+
+void
+acpi_dm_convert_resource_indexes(union acpi_parse_object *parse_tree_root,
+ struct acpi_namespace_node *namespace_root);
+
+/*
+ * adfile
+ */
+acpi_status ad_initialize(void);
+
+char *fl_generate_filename(char *input_filename, char *suffix);
+
+acpi_status
+fl_split_input_pathname(char *input_path,
+ char **out_directory_path, char **out_filename);
+
+char *ad_generate_filename(char *prefix, char *table_id);
+
+void
+ad_write_table(struct acpi_table_header *table,
+ u32 length, char *table_name, char *oem_table_id);
+#endif
+
+#endif /* _ACAPPS */
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 49bbc71fad54..1f602907dfab 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -103,8 +103,8 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE);
/*
* Create the predefined _OSI method in the namespace? Default is TRUE
- * because ACPI CA is fully compatible with other ACPI implementations.
- * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ * because ACPICA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPICA (and machine ASL) to pre-OSI behavior.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE);
@@ -160,10 +160,10 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_truncate_io_addresses, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE);
/*
- * Optionally do not load any SSDTs from the RSDT/XSDT during initialization.
+ * Optionally do not install any SSDTs from the RSDT/XSDT during initialization.
* This can be useful for debugging ACPI problems on some machines.
*/
-ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_load, FALSE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_install, FALSE);
/*
* We keep track of the latest version of Windows that has been requested by
@@ -509,5 +509,6 @@ ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
****************************************************************************/
extern const struct ah_predefined_name asl_predefined_info[];
+extern const struct ah_device_id asl_device_ids[];
#endif /* __ACGLOBAL_H__ */
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 52a21dafb540..f68cb602dc23 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -733,7 +733,8 @@ union acpi_parse_value {
#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */
#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */
#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */
-#define ACPI_DASM_IGNORE 0x09 /* Not used at this time */
+#define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */
+#define ACPI_DASM_IGNORE 0x0A /* Not used at this time */
/*
* Generic operation (for example: If, While, Store)
@@ -1147,4 +1148,9 @@ struct ah_predefined_name {
#endif
};
+struct ah_device_id {
+ char *name;
+ char *description;
+};
+
#endif /* __ACLOCAL_H__ */
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index 5fa4b2027697..bda9a7eb50c1 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -54,6 +54,26 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
/*
+ * tbdata - table data structure management
+ */
+acpi_status acpi_tb_get_next_root_index(u32 *table_index);
+
+void
+acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
+ acpi_physical_address address,
+ u8 flags, struct acpi_table_header *table);
+
+acpi_status
+acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
+ acpi_physical_address address, u8 flags);
+
+void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
+
+u8 acpi_tb_is_table_loaded(u32 table_index);
+
+void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
+
+/*
* tbfadt - FADT parse/convert/validate
*/
void acpi_tb_parse_fadt(u32 table_index);
@@ -72,22 +92,35 @@ acpi_tb_find_table(char *signature,
*/
acpi_status acpi_tb_resize_root_table_list(void);
-acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc);
+acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc);
-struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
- *table_header,
- struct acpi_table_desc
- *table_desc);
+void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc);
acpi_status
-acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index);
+acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature);
+
+void acpi_tb_override_table(struct acpi_table_desc *old_table_desc);
+
+acpi_status
+acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
+ struct acpi_table_header **table_ptr,
+ u32 *table_length, u8 *table_flags);
+
+void
+acpi_tb_release_table(struct acpi_table_header *table,
+ u32 table_length, u8 table_flags);
+
+acpi_status
+acpi_tb_install_standard_table(acpi_physical_address address,
+ u8 flags,
+ u8 reload, u8 override, u32 *table_index);
acpi_status
acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_header *table,
u32 length, u8 flags, u32 *table_index);
-void acpi_tb_delete_table(struct acpi_table_desc *table_desc);
+void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc);
void acpi_tb_terminate(void);
@@ -99,10 +132,6 @@ acpi_status acpi_tb_release_owner_id(u32 table_index);
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id);
-u8 acpi_tb_is_table_loaded(u32 table_index);
-
-void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
-
/*
* tbutils - table manager utilities
*/
@@ -124,8 +153,13 @@ void acpi_tb_check_dsdt_header(void);
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
void
-acpi_tb_install_table(acpi_physical_address address,
- char *signature, u32 table_index);
+acpi_tb_install_table_with_override(u32 table_index,
+ struct acpi_table_desc *new_table_desc,
+ u8 override);
+
+acpi_status
+acpi_tb_install_fixed_table(acpi_physical_address address,
+ char *signature, u32 table_index);
acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index ceeec0b7ccb1..1e256c5bda20 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -176,8 +176,7 @@ acpi_status acpi_ut_init_globals(void);
char *acpi_ut_get_mutex_name(u32 mutex_id);
-const char *acpi_ut_get_notify_name(u32 notify_value);
-
+const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type);
#endif
char *acpi_ut_get_type_name(acpi_object_type type);
@@ -737,4 +736,11 @@ acpi_ut_method_error(const char *module_name,
struct acpi_namespace_node *node,
const char *path, acpi_status lookup_status);
+/*
+ * Utility functions for ACPI names and IDs
+ */
+const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg);
+
+const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
+
#endif /* _ACUTILS_H */
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index 5d594eb2e5ec..24ea3424981b 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -167,7 +167,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
"Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type), notify_value,
- acpi_ut_get_notify_name(notify_value), node));
+ acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
+ node));
status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
info);
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index 4d8a709c1fc4..29630e303829 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -117,7 +117,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
/*
- * We are guaranteed by the ACPI CA initialization/shutdown code that
+ * We are guaranteed by the ACPICA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
*/
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index a734b27da061..11e5803b8b41 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -239,7 +239,7 @@ acpi_remove_notify_handler(acpi_handle device,
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
union acpi_operand_object *previous_handler_obj;
- acpi_status status;
+ acpi_status status = AE_OK;
u32 i;
ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
@@ -251,20 +251,17 @@ acpi_remove_notify_handler(acpi_handle device,
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Make sure all deferred notify tasks are completed */
-
- acpi_os_wait_events_complete();
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
/* Root Object. Global handlers are removed here */
if (device == ACPI_ROOT_OBJECT) {
for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
if (handler_type & (i + 1)) {
+ status =
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
if (!acpi_gbl_global_notify[i].handler ||
(acpi_gbl_global_notify[i].handler !=
handler)) {
@@ -277,31 +274,40 @@ acpi_remove_notify_handler(acpi_handle device,
acpi_gbl_global_notify[i].handler = NULL;
acpi_gbl_global_notify[i].context = NULL;
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+ /* Make sure all deferred notify tasks are completed */
+
+ acpi_os_wait_events_complete();
}
}
- goto unlock_and_exit;
+ return_ACPI_STATUS(AE_OK);
}
/* All other objects: Are Notifies allowed on this object? */
if (!acpi_ev_is_notify_object(node)) {
- status = AE_TYPE;
- goto unlock_and_exit;
+ return_ACPI_STATUS(AE_TYPE);
}
/* Must have an existing internal object */
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
- status = AE_NOT_EXIST;
- goto unlock_and_exit;
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Internal object exists. Find the handler and remove it */
for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
if (handler_type & (i + 1)) {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
handler_obj = obj_desc->common_notify.notify_list[i];
previous_handler_obj = NULL;
@@ -329,10 +335,17 @@ acpi_remove_notify_handler(acpi_handle device,
handler_obj->notify.next[i];
}
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+ /* Make sure all deferred notify tasks are completed */
+
+ acpi_os_wait_events_complete();
acpi_ut_remove_reference(handler_obj);
}
}
+ return_ACPI_STATUS(status);
+
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
@@ -457,6 +470,8 @@ exit:
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_install_sci_handler)
+
/*******************************************************************************
*
* FUNCTION: acpi_remove_sci_handler
@@ -468,7 +483,6 @@ exit:
* DESCRIPTION: Remove a handler for a System Control Interrupt.
*
******************************************************************************/
-
acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
{
struct acpi_sci_handler_info *prev_sci_handler;
@@ -522,6 +536,8 @@ unlock_and_exit:
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler)
+
/*******************************************************************************
*
* FUNCTION: acpi_install_global_event_handler
@@ -537,7 +553,6 @@ unlock_and_exit:
* Can be used to update event counters, etc.
*
******************************************************************************/
-
acpi_status
acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
{
@@ -840,10 +855,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Make sure all deferred GPE tasks are completed */
-
- acpi_os_wait_events_complete();
-
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -895,9 +906,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
(void)acpi_ev_add_gpe_reference(gpe_event_info);
}
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+ /* Make sure all deferred GPE tasks are completed */
+
+ acpi_os_wait_events_complete();
+
/* Now we can free the handler object */
ACPI_FREE(handler);
+ return_ACPI_STATUS(status);
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 8ba1464efd11..7d2949420db7 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -343,16 +343,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *ddb_handle;
+ struct acpi_table_header *table_header;
struct acpi_table_header *table;
- struct acpi_table_desc table_desc;
u32 table_index;
acpi_status status;
u32 length;
ACPI_FUNCTION_TRACE(ex_load_op);
- ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
-
/* Source Object can be either an op_region or a Buffer/Field */
switch (obj_desc->common.type) {
@@ -380,17 +378,17 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Get the table header first so we can get the table length */
- table = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
- if (!table) {
+ table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
+ if (!table_header) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
status =
acpi_ex_region_read(obj_desc,
sizeof(struct acpi_table_header),
- ACPI_CAST_PTR(u8, table));
- length = table->length;
- ACPI_FREE(table);
+ ACPI_CAST_PTR(u8, table_header));
+ length = table_header->length;
+ ACPI_FREE(table_header);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -420,22 +418,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Allocate a buffer for the table */
- table_desc.pointer = ACPI_ALLOCATE(length);
- if (!table_desc.pointer) {
+ table = ACPI_ALLOCATE(length);
+ if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Read the entire table */
status = acpi_ex_region_read(obj_desc, length,
- ACPI_CAST_PTR(u8,
- table_desc.pointer));
+ ACPI_CAST_PTR(u8, table));
if (ACPI_FAILURE(status)) {
- ACPI_FREE(table_desc.pointer);
+ ACPI_FREE(table);
return_ACPI_STATUS(status);
}
-
- table_desc.address = obj_desc->region.address;
break;
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
@@ -452,10 +447,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Get the actual table length from the table header */
- table =
+ table_header =
ACPI_CAST_PTR(struct acpi_table_header,
obj_desc->buffer.pointer);
- length = table->length;
+ length = table_header->length;
/* Table cannot extend beyond the buffer */
@@ -470,13 +465,12 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
* Copy the table from the buffer because the buffer could be modified
* or even deleted in the future
*/
- table_desc.pointer = ACPI_ALLOCATE(length);
- if (!table_desc.pointer) {
+ table = ACPI_ALLOCATE(length);
+ if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- ACPI_MEMCPY(table_desc.pointer, table, length);
- table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
+ ACPI_MEMCPY(table, table_header, length);
break;
default:
@@ -484,27 +478,32 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
- /* Validate table checksum (will not get validated in tb_add_table) */
-
- status = acpi_tb_verify_checksum(table_desc.pointer, length);
- if (ACPI_FAILURE(status)) {
- ACPI_FREE(table_desc.pointer);
- return_ACPI_STATUS(status);
- }
-
- /* Complete the table descriptor */
+ /* Install the new table into the local data structures */
- table_desc.length = length;
- table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+ ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- /* Install the new table into the local data structures */
+ status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
+ ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
+ TRUE, TRUE, &table_index);
- status = acpi_tb_add_table(&table_desc, &table_index);
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
/* Delete allocated table buffer */
- acpi_tb_delete_table(&table_desc);
+ ACPI_FREE(table);
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Note: Now table is "INSTALLED", it must be validated before
+ * loading.
+ */
+ status =
+ acpi_tb_validate_table(&acpi_gbl_root_table_list.
+ tables[table_index]);
+ if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -536,9 +535,6 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(status);
}
- ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
- acpi_tb_print_table_header(0, table_desc.pointer);
-
/* Remove the reference by added by acpi_ex_store above */
acpi_ut_remove_reference(ddb_handle);
@@ -546,8 +542,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Invoke table handler if present */
if (acpi_gbl_table_handler) {
- (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD,
- table_desc.pointer,
+ (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
acpi_gbl_table_handler_context);
}
@@ -576,6 +571,13 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
ACPI_FUNCTION_TRACE(ex_unload_table);
/*
+ * Temporarily emit a warning so that the ASL for the machine can be
+ * hopefully obtained. This is to say that the Unload() operator is
+ * extremely rare if not completely unused.
+ */
+ ACPI_WARNING((AE_INFO, "Received request to unload an ACPI 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
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 973fdae00f94..925202acc3e4 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -134,9 +134,11 @@ static struct acpi_exdump_info acpi_ex_dump_method[9] = {
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"}
};
-static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
+static struct acpi_exdump_info acpi_ex_dump_mutex[6] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.original_sync_level),
+ "Original Sync Level"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
"Acquire Depth"},
diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c
new file mode 100644
index 000000000000..cbe29944dc97
--- /dev/null
+++ b/drivers/acpi/acpica/tbdata.c
@@ -0,0 +1,723 @@
+/******************************************************************************
+ *
+ * Module Name: tbdata - Table manager data structure functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "actables.h"
+
+#define _COMPONENT ACPI_TABLES
+ACPI_MODULE_NAME("tbdata")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_init_table_descriptor
+ *
+ * PARAMETERS: table_desc - Table descriptor
+ * address - Physical address of the table
+ * flags - Allocation flags of the table
+ * table - Pointer to the table
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Initialize a new table descriptor
+ *
+ ******************************************************************************/
+void
+acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
+ acpi_physical_address address,
+ u8 flags, struct acpi_table_header *table)
+{
+
+ /*
+ * Initialize the table descriptor. Set the pointer to NULL, since the
+ * table is not fully mapped at this time.
+ */
+ ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc));
+ table_desc->address = address;
+ table_desc->length = table->length;
+ table_desc->flags = flags;
+ ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_acquire_table
+ *
+ * PARAMETERS: table_desc - Table descriptor
+ * table_ptr - Where table is returned
+ * table_length - Where table length is returned
+ * table_flags - Where table allocation flags are returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Acquire an ACPI table. It can be used for tables not
+ * maintained in the acpi_gbl_root_table_list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
+ struct acpi_table_header **table_ptr,
+ u32 *table_length, u8 *table_flags)
+{
+ struct acpi_table_header *table = NULL;
+
+ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+
+ table =
+ acpi_os_map_memory(table_desc->address, table_desc->length);
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+
+ table =
+ ACPI_CAST_PTR(struct acpi_table_header,
+ table_desc->address);
+ break;
+
+ default:
+
+ break;
+ }
+
+ /* Table is not valid yet */
+
+ if (!table) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Fill the return values */
+
+ *table_ptr = table;
+ *table_length = table_desc->length;
+ *table_flags = table_desc->flags;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_release_table
+ *
+ * PARAMETERS: table - Pointer for the table
+ * table_length - Length for the table
+ * table_flags - Allocation flags for the table
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().
+ *
+ ******************************************************************************/
+
+void
+acpi_tb_release_table(struct acpi_table_header *table,
+ u32 table_length, u8 table_flags)
+{
+
+ switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+
+ acpi_os_unmap_memory(table, table_length);
+ break;
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+ default:
+
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_acquire_temp_table
+ *
+ * PARAMETERS: table_desc - Table descriptor to be acquired
+ * address - Address of the table
+ * flags - Allocation flags of the table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function validates the table header to obtain the length
+ * of a table and fills the table descriptor to make its state as
+ * "INSTALLED". Such a table descriptor is only used for verified
+ * installation.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
+ acpi_physical_address address, u8 flags)
+{
+ struct acpi_table_header *table_header;
+
+ switch (flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
+
+ /* Get the length of the full table from the header */
+
+ table_header =
+ acpi_os_map_memory(address,
+ sizeof(struct acpi_table_header));
+ if (!table_header) {
+ return (AE_NO_MEMORY);
+ }
+
+ acpi_tb_init_table_descriptor(table_desc, address, flags,
+ table_header);
+ acpi_os_unmap_memory(table_header,
+ sizeof(struct acpi_table_header));
+ return (AE_OK);
+
+ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
+ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
+
+ table_header = ACPI_CAST_PTR(struct acpi_table_header, address);
+ if (!table_header) {
+ return (AE_NO_MEMORY);
+ }
+
+ acpi_tb_init_table_descriptor(table_desc, address, flags,
+ table_header);
+ return (AE_OK);
+
+ default:
+
+ break;
+ }
+
+ /* Table is not valid yet */
+
+ return (AE_NO_MEMORY);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_release_temp_table
+ *
+ * PARAMETERS: table_desc - Table descriptor to be released
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().
+ *
+ *****************************************************************************/
+
+void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)
+{
+
+ /*
+ * Note that the .Address is maintained by the callers of
+ * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table()
+ * where .Address will be freed.
+ */
+ acpi_tb_invalidate_table(table_desc);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_tb_validate_table
+ *
+ * PARAMETERS: table_desc - Table descriptor
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function is called to validate the table, the returned
+ * table descriptor is in "VALIDATED" state.
+ *
+ *****************************************************************************/
+
+acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(tb_validate_table);
+
+ /* Validate the table if necessary */
+
+ if (!table_desc->pointer) {
+ status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
+ &table_desc->length,
+ &table_desc->flags);
+ if (!table_desc->pointer) {
+ status = AE_NO_MEMORY;
+ }
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_invalidate_table
+ *
+ * PARAMETERS: table_desc - Table descriptor
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of
+ * acpi_tb_validate_table().
+ *
+ ******************************************************************************/
+
+void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
+{
+
+ ACPI_FUNCTION_TRACE(tb_invalidate_table);
+
+ /* Table must be validated */
+
+ if (!table_desc->pointer) {
+ return_VOID;
+ }
+
+ acpi_tb_release_table(table_desc->pointer, table_desc->length,
+ table_desc->flags);
+ table_desc->pointer = NULL;
+
+ return_VOID;
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_tb_verify_table
+ *
+ * PARAMETERS: table_desc - Table descriptor
+ * signature - Table signature to verify
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function is called to validate and verify the table, the
+ * returned table descriptor is in "VALIDATED" state.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(tb_verify_table);
+
+ /* Validate the table */
+
+ status = acpi_tb_validate_table(table_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* If a particular signature is expected (DSDT/FACS), it must match */
+
+ if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
+ ACPI_BIOS_ERROR((AE_INFO,
+ "Invalid signature 0x%X for ACPI table, expected [%s]",
+ table_desc->signature.integer, signature));
+ status = AE_BAD_SIGNATURE;
+ goto invalidate_and_exit;
+ }
+
+ /* Verify the checksum */
+
+ status =
+ acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
+ "%4.4s " ACPI_PRINTF_UINT
+ " Attempted table install failed",
+ acpi_ut_valid_acpi_name(table_desc->signature.
+ ascii) ? table_desc->
+ signature.ascii : "????",
+ ACPI_FORMAT_TO_UINT(table_desc->address)));
+ goto invalidate_and_exit;
+ }
+
+ return_ACPI_STATUS(AE_OK);
+
+invalidate_and_exit:
+ acpi_tb_invalidate_table(table_desc);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_resize_root_table_list
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Expand the size of global table array
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_resize_root_table_list(void)
+{
+ struct acpi_table_desc *tables;
+ u32 table_count;
+
+ ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
+
+ /* allow_resize flag is a parameter to acpi_initialize_tables */
+
+ if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
+ ACPI_ERROR((AE_INFO,
+ "Resize of Root Table Array is not allowed"));
+ return_ACPI_STATUS(AE_SUPPORT);
+ }
+
+ /* Increase the Table Array size */
+
+ if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
+ table_count = acpi_gbl_root_table_list.max_table_count;
+ } else {
+ table_count = acpi_gbl_root_table_list.current_table_count;
+ }
+
+ tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
+ ACPI_ROOT_TABLE_SIZE_INCREMENT) *
+ sizeof(struct acpi_table_desc));
+ if (!tables) {
+ ACPI_ERROR((AE_INFO,
+ "Could not allocate new root table array"));
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ /* Copy and free the previous table array */
+
+ if (acpi_gbl_root_table_list.tables) {
+ ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
+ (acpi_size) table_count *
+ sizeof(struct acpi_table_desc));
+
+ if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
+ ACPI_FREE(acpi_gbl_root_table_list.tables);
+ }
+ }
+
+ acpi_gbl_root_table_list.tables = tables;
+ acpi_gbl_root_table_list.max_table_count =
+ table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
+ acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_get_next_root_index
+ *
+ * PARAMETERS: table_index - Where table index is returned
+ *
+ * RETURN: Status and table index.
+ *
+ * DESCRIPTION: Allocate a new ACPI table entry to the global table list
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_get_next_root_index(u32 *table_index)
+{
+ acpi_status status;
+
+ /* Ensure that there is room for the table in the Root Table List */
+
+ if (acpi_gbl_root_table_list.current_table_count >=
+ acpi_gbl_root_table_list.max_table_count) {
+ status = acpi_tb_resize_root_table_list();
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+
+ *table_index = acpi_gbl_root_table_list.current_table_count;
+ acpi_gbl_root_table_list.current_table_count++;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_terminate
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete all internal ACPI tables
+ *
+ ******************************************************************************/
+
+void acpi_tb_terminate(void)
+{
+ u32 i;
+
+ ACPI_FUNCTION_TRACE(tb_terminate);
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+ /* Delete the individual tables */
+
+ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
+ acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
+ }
+
+ /*
+ * Delete the root table array if allocated locally. Array cannot be
+ * mapped, so we don't need to check for that flag.
+ */
+ if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
+ ACPI_FREE(acpi_gbl_root_table_list.tables);
+ }
+
+ acpi_gbl_root_table_list.tables = NULL;
+ acpi_gbl_root_table_list.flags = 0;
+ acpi_gbl_root_table_list.current_table_count = 0;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_delete_namespace_by_owner
+ *
+ * PARAMETERS: table_index - Table index
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete all namespace objects created when this table was loaded.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
+{
+ acpi_owner_id owner_id;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ if (table_index >= acpi_gbl_root_table_list.current_table_count) {
+
+ /* The table index does not exist */
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(AE_NOT_EXIST);
+ }
+
+ /* Get the owner ID for this table, used to delete namespace nodes */
+
+ owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+ /*
+ * Need to acquire the namespace writer lock to prevent interference
+ * with any concurrent namespace walks. The interpreter must be
+ * released during the deletion since the acquisition of the deletion
+ * lock may block, and also since the execution of a namespace walk
+ * must be allowed to use the interpreter.
+ */
+ (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
+ status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
+
+ acpi_ns_delete_namespace_by_owner(owner_id);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_allocate_owner_id
+ *
+ * PARAMETERS: table_index - Table index
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocates owner_id in table_desc
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_allocate_owner_id(u32 table_index)
+{
+ acpi_status status = AE_BAD_PARAMETER;
+
+ ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (table_index < acpi_gbl_root_table_list.current_table_count) {
+ status =
+ acpi_ut_allocate_owner_id(&
+ (acpi_gbl_root_table_list.
+ tables[table_index].owner_id));
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_release_owner_id
+ *
+ * PARAMETERS: table_index - Table index
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Releases owner_id in table_desc
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_release_owner_id(u32 table_index)
+{
+ acpi_status status = AE_BAD_PARAMETER;
+
+ ACPI_FUNCTION_TRACE(tb_release_owner_id);
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (table_index < acpi_gbl_root_table_list.current_table_count) {
+ acpi_ut_release_owner_id(&
+ (acpi_gbl_root_table_list.
+ tables[table_index].owner_id));
+ status = AE_OK;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_get_owner_id
+ *
+ * PARAMETERS: table_index - Table index
+ * owner_id - Where the table owner_id is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: returns owner_id for the ACPI table
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
+{
+ acpi_status status = AE_BAD_PARAMETER;
+
+ ACPI_FUNCTION_TRACE(tb_get_owner_id);
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (table_index < acpi_gbl_root_table_list.current_table_count) {
+ *owner_id =
+ acpi_gbl_root_table_list.tables[table_index].owner_id;
+ status = AE_OK;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_is_table_loaded
+ *
+ * PARAMETERS: table_index - Index into the root table
+ *
+ * RETURN: Table Loaded Flag
+ *
+ ******************************************************************************/
+
+u8 acpi_tb_is_table_loaded(u32 table_index)
+{
+ u8 is_loaded = FALSE;
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (table_index < acpi_gbl_root_table_list.current_table_count) {
+ is_loaded = (u8)
+ (acpi_gbl_root_table_list.tables[table_index].flags &
+ ACPI_TABLE_IS_LOADED);
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return (is_loaded);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_set_table_loaded_flag
+ *
+ * PARAMETERS: table_index - Table index
+ * is_loaded - TRUE if table is loaded, FALSE otherwise
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
+ *
+ ******************************************************************************/
+
+void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
+{
+
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (table_index < acpi_gbl_root_table_list.current_table_count) {
+ if (is_loaded) {
+ acpi_gbl_root_table_list.tables[table_index].flags |=
+ ACPI_TABLE_IS_LOADED;
+ } else {
+ acpi_gbl_root_table_list.tables[table_index].flags &=
+ ~ACPI_TABLE_IS_LOADED;
+ }
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+}
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index ec14588254d4..a37af164b8c8 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -332,15 +332,15 @@ void acpi_tb_parse_fadt(u32 table_index)
/* Obtain the DSDT and FACS tables via their addresses within the FADT */
- acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
- ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
+ acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
+ ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
/* If Hardware Reduced flag is set, there is no FACS */
if (!acpi_gbl_reduced_hardware) {
- acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.
- Xfacs, ACPI_SIG_FACS,
- ACPI_TABLE_INDEX_FACS);
+ acpi_tb_install_fixed_table((acpi_physical_address)
+ acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS,
+ ACPI_TABLE_INDEX_FACS);
}
}
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index c12003947bd5..cb947700206c 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature,
/* Table is not currently mapped, map it */
status =
- acpi_tb_verify_table(&acpi_gbl_root_table_list.
- tables[i]);
+ acpi_tb_validate_table(&acpi_gbl_root_table_list.
+ tables[i]);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index e3040947e9a0..d4d6029fef44 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -43,688 +43,483 @@
#include <acpi/acpi.h>
#include "accommon.h"
-#include "acnamesp.h"
#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal")
-/******************************************************************************
+/* Local prototypes */
+static u8
+acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
+
+/*******************************************************************************
*
- * FUNCTION: acpi_tb_verify_table
+ * FUNCTION: acpi_tb_compare_tables
*
- * PARAMETERS: table_desc - table
+ * PARAMETERS: table_desc - Table 1 descriptor to be compared
+ * table_index - Index of table 2 to be compared
*
- * RETURN: Status
+ * RETURN: TRUE if both tables are identical.
*
- * DESCRIPTION: this function is called to verify and map table
+ * DESCRIPTION: This function compares a table with another table that has
+ * already been installed in the root table list.
*
- *****************************************************************************/
-acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
+ ******************************************************************************/
+
+static u8
+acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
{
acpi_status status = AE_OK;
+ u8 is_identical;
+ struct acpi_table_header *table;
+ u32 table_length;
+ u8 table_flags;
- ACPI_FUNCTION_TRACE(tb_verify_table);
-
- /* Map the table if necessary */
-
- if (!table_desc->pointer) {
- if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
- ACPI_TABLE_ORIGIN_MAPPED) {
- table_desc->pointer =
- acpi_os_map_memory(table_desc->address,
- table_desc->length);
- }
- if (!table_desc->pointer) {
- return_ACPI_STATUS(AE_NO_MEMORY);
- }
+ status =
+ acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
+ &table, &table_length, &table_flags);
+ if (ACPI_FAILURE(status)) {
+ return (FALSE);
}
- /* Always calculate checksum, ignore bad checksum if requested */
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ is_identical = (u8)((table_desc->length != table_length ||
+ ACPI_MEMCMP(table_desc->pointer, table,
+ table_length)) ? FALSE : TRUE);
- status =
- acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
+ /* Release the acquired table */
- return_ACPI_STATUS(status);
+ acpi_tb_release_table(table, table_length, table_flags);
+ return (is_identical);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_add_table
+ * FUNCTION: acpi_tb_install_table_with_override
*
- * PARAMETERS: table_desc - Table descriptor
- * table_index - Where the table index is returned
+ * PARAMETERS: table_index - Index into root table array
+ * new_table_desc - New table descriptor to install
+ * override - Whether override should be performed
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: This function is called to add an ACPI table. It is used to
- * dynamically load tables via the Load and load_table AML
- * operators.
+ * DESCRIPTION: Install an ACPI table into the global data structure. The
+ * table override mechanism is called to allow the host
+ * OS to replace any table before it is installed in the root
+ * table array.
*
******************************************************************************/
-acpi_status
-acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
+void
+acpi_tb_install_table_with_override(u32 table_index,
+ struct acpi_table_desc *new_table_desc,
+ u8 override)
{
- u32 i;
- acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE(tb_add_table);
-
- if (!table_desc->pointer) {
- status = acpi_tb_verify_table(table_desc);
- if (ACPI_FAILURE(status) || !table_desc->pointer) {
- return_ACPI_STATUS(status);
- }
+ if (table_index >= acpi_gbl_root_table_list.current_table_count) {
+ return;
}
/*
- * Validate the incoming table signature.
+ * ACPI Table Override:
*
- * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
- * 2) We added support for OEMx tables, signature "OEM".
- * 3) Valid tables were encountered with a null signature, so we just
- * gave up on validating the signature, (05/2008).
- * 4) We encountered non-AML tables such as the MADT, which caused
- * interpreter errors and kernel faults. So now, we once again allow
- * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
+ * Before we install the table, let the host OS override it with a new
+ * one if desired. Any table within the RSDT/XSDT can be replaced,
+ * including the DSDT which is pointed to by the FADT.
*/
- if ((table_desc->pointer->signature[0] != 0x00) &&
- (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
- && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
- ACPI_BIOS_ERROR((AE_INFO,
- "Table has invalid signature [%4.4s] (0x%8.8X), "
- "must be SSDT or OEMx",
- acpi_ut_valid_acpi_name(table_desc->pointer->
- signature) ?
- table_desc->pointer->signature : "????",
- *(u32 *)table_desc->pointer->signature));
-
- return_ACPI_STATUS(AE_BAD_SIGNATURE);
+ if (override) {
+ acpi_tb_override_table(new_table_desc);
}
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
+ tables[table_index],
+ new_table_desc->address,
+ new_table_desc->flags,
+ new_table_desc->pointer);
- /* Check if table is already registered */
+ acpi_tb_print_table_header(new_table_desc->address,
+ new_table_desc->pointer);
- for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
- if (!acpi_gbl_root_table_list.tables[i].pointer) {
- status =
- acpi_tb_verify_table(&acpi_gbl_root_table_list.
- tables[i]);
- if (ACPI_FAILURE(status)
- || !acpi_gbl_root_table_list.tables[i].pointer) {
- continue;
- }
- }
+ /* Set the global integer width (based upon revision of the DSDT) */
- /*
- * Check for a table match on the entire table length,
- * not just the header.
- */
- if (table_desc->length !=
- acpi_gbl_root_table_list.tables[i].length) {
- continue;
- }
-
- if (ACPI_MEMCMP(table_desc->pointer,
- acpi_gbl_root_table_list.tables[i].pointer,
- acpi_gbl_root_table_list.tables[i].length)) {
- continue;
- }
-
- /*
- * Note: the current mechanism does not unregister a table if it is
- * dynamically unloaded. The related namespace entries are deleted,
- * but the table remains in the root table list.
- *
- * The assumption here is that the number of different tables that
- * will be loaded is actually small, and there is minimal overhead
- * in just keeping the table in case it is needed again.
- *
- * If this assumption changes in the future (perhaps on large
- * machines with many table load/unload operations), tables will
- * need to be unregistered when they are unloaded, and slots in the
- * root table list should be reused when empty.
- */
-
- /*
- * Table is already registered.
- * We can delete the table that was passed as a parameter.
- */
- acpi_tb_delete_table(table_desc);
- *table_index = i;
-
- if (acpi_gbl_root_table_list.tables[i].
- flags & ACPI_TABLE_IS_LOADED) {
-
- /* Table is still loaded, this is an error */
-
- status = AE_ALREADY_EXISTS;
- goto release;
- } else {
- /* Table was unloaded, allow it to be reloaded */
-
- table_desc->pointer =
- acpi_gbl_root_table_list.tables[i].pointer;
- table_desc->address =
- acpi_gbl_root_table_list.tables[i].address;
- status = AE_OK;
- goto print_header;
- }
+ if (table_index == ACPI_TABLE_INDEX_DSDT) {
+ acpi_ut_set_integer_width(new_table_desc->pointer->revision);
}
-
- /*
- * ACPI Table Override:
- * Allow the host to override dynamically loaded tables.
- * NOTE: the table is fully mapped at this point, and the mapping will
- * be deleted by tb_table_override if the table is actually overridden.
- */
- (void)acpi_tb_table_override(table_desc->pointer, table_desc);
-
- /* Add the table to the global root table list */
-
- status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
- table_desc->length, table_desc->flags,
- table_index);
- if (ACPI_FAILURE(status)) {
- goto release;
- }
-
-print_header:
- acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
-
-release:
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return_ACPI_STATUS(status);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_table_override
+ * FUNCTION: acpi_tb_install_fixed_table
*
- * PARAMETERS: table_header - Header for the original table
- * table_desc - Table descriptor initialized for the
- * original table. May or may not be mapped.
+ * PARAMETERS: address - Physical address of DSDT or FACS
+ * signature - Table signature, NULL if no need to
+ * match
+ * table_index - Index into root table array
*
- * RETURN: Pointer to the entire new table. NULL if table not overridden.
- * If overridden, installs the new table within the input table
- * descriptor.
+ * RETURN: Status
*
- * DESCRIPTION: Attempt table override by calling the OSL override functions.
- * Note: If the table is overridden, then the entire new table
- * is mapped and returned by this function.
+ * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
+ * structure.
*
******************************************************************************/
-struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
- *table_header,
- struct acpi_table_desc
- *table_desc)
+acpi_status
+acpi_tb_install_fixed_table(acpi_physical_address address,
+ char *signature, u32 table_index)
{
+ struct acpi_table_desc new_table_desc;
acpi_status status;
- struct acpi_table_header *new_table = NULL;
- acpi_physical_address new_address = 0;
- u32 new_table_length = 0;
- u8 new_flags;
- char *override_type;
- /* (1) Attempt logical override (returns a logical address) */
+ ACPI_FUNCTION_TRACE(tb_install_fixed_table);
- status = acpi_os_table_override(table_header, &new_table);
- if (ACPI_SUCCESS(status) && new_table) {
- new_address = ACPI_PTR_TO_PHYSADDR(new_table);
- new_table_length = new_table->length;
- new_flags = ACPI_TABLE_ORIGIN_OVERRIDE;
- override_type = "Logical";
- goto finish_override;
+ if (!address) {
+ ACPI_ERROR((AE_INFO,
+ "Null physical address for ACPI table [%s]",
+ signature));
+ return (AE_NO_MEMORY);
}
- /* (2) Attempt physical override (returns a physical address) */
+ /* Fill a table descriptor for validation */
- status = acpi_os_physical_table_override(table_header,
- &new_address,
- &new_table_length);
- if (ACPI_SUCCESS(status) && new_address && new_table_length) {
-
- /* Map the entire new table */
-
- new_table = acpi_os_map_memory(new_address, new_table_length);
- if (!new_table) {
- ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
- "%4.4s " ACPI_PRINTF_UINT
- " Attempted physical table override failed",
- table_header->signature,
- ACPI_FORMAT_TO_UINT(table_desc->
- address)));
- return (NULL);
- }
-
- override_type = "Physical";
- new_flags = ACPI_TABLE_ORIGIN_MAPPED;
- goto finish_override;
+ status = acpi_tb_acquire_temp_table(&new_table_desc, address,
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
+ ACPI_CAST_PTR(void, address)));
+ return_ACPI_STATUS(status);
}
- return (NULL); /* There was no override */
-
-finish_override:
-
- ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
- " %s table override, new table: " ACPI_PRINTF_UINT,
- table_header->signature,
- ACPI_FORMAT_TO_UINT(table_desc->address),
- override_type, ACPI_FORMAT_TO_UINT(new_table)));
+ /* Validate and verify a table before installation */
- /* We can now unmap/delete the original table (if fully mapped) */
+ status = acpi_tb_verify_table(&new_table_desc, signature);
+ if (ACPI_FAILURE(status)) {
+ goto release_and_exit;
+ }
- acpi_tb_delete_table(table_desc);
+ acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE);
- /* Setup descriptor for the new table */
+release_and_exit:
- table_desc->address = new_address;
- table_desc->pointer = new_table;
- table_desc->length = new_table_length;
- table_desc->flags = new_flags;
+ /* Release the temporary table descriptor */
- return (new_table);
+ acpi_tb_release_temp_table(&new_table_desc);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_resize_root_table_list
+ * FUNCTION: acpi_tb_install_standard_table
*
- * PARAMETERS: None
+ * PARAMETERS: address - Address of the table (might be a virtual
+ * address depending on the table_flags)
+ * flags - Flags for the table
+ * reload - Whether reload should be performed
+ * override - Whether override should be performed
+ * table_index - Where the table index is returned
*
* RETURN: Status
*
- * DESCRIPTION: Expand the size of global table array
+ * DESCRIPTION: This function is called to install an ACPI table that is
+ * neither DSDT nor FACS (a "standard" table.)
+ * When this function is called by "Load" or "LoadTable" opcodes,
+ * or by acpi_load_table() API, the "Reload" parameter is set.
+ * After sucessfully returning from this function, table is
+ * "INSTALLED" but not "VALIDATED".
*
******************************************************************************/
-acpi_status acpi_tb_resize_root_table_list(void)
+acpi_status
+acpi_tb_install_standard_table(acpi_physical_address address,
+ u8 flags,
+ u8 reload, u8 override, u32 *table_index)
{
- struct acpi_table_desc *tables;
- u32 table_count;
-
- ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
-
- /* allow_resize flag is a parameter to acpi_initialize_tables */
+ u32 i;
+ acpi_status status = AE_OK;
+ struct acpi_table_desc new_table_desc;
- if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
- ACPI_ERROR((AE_INFO,
- "Resize of Root Table Array is not allowed"));
- return_ACPI_STATUS(AE_SUPPORT);
- }
+ ACPI_FUNCTION_TRACE(tb_install_standard_table);
- /* Increase the Table Array size */
+ /* Acquire a temporary table descriptor for validation */
- if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
- table_count = acpi_gbl_root_table_list.max_table_count;
- } else {
- table_count = acpi_gbl_root_table_list.current_table_count;
+ status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
+ ACPI_CAST_PTR(void, address)));
+ return_ACPI_STATUS(status);
}
- tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
- ACPI_ROOT_TABLE_SIZE_INCREMENT) *
- sizeof(struct acpi_table_desc));
- if (!tables) {
- ACPI_ERROR((AE_INFO,
- "Could not allocate new root table array"));
- return_ACPI_STATUS(AE_NO_MEMORY);
+ /*
+ * Optionally do not load any SSDTs from the RSDT/XSDT. This can
+ * be useful for debugging ACPI problems on some machines.
+ */
+ if (!reload &&
+ acpi_gbl_disable_ssdt_table_install &&
+ ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
+ ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p",
+ new_table_desc.signature.ascii, ACPI_CAST_PTR(void,
+ address)));
+ goto release_and_exit;
}
- /* Copy and free the previous table array */
-
- if (acpi_gbl_root_table_list.tables) {
- ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
- (acpi_size) table_count *
- sizeof(struct acpi_table_desc));
+ /* Validate and verify a table before installation */
- if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
- ACPI_FREE(acpi_gbl_root_table_list.tables);
- }
+ status = acpi_tb_verify_table(&new_table_desc, NULL);
+ if (ACPI_FAILURE(status)) {
+ goto release_and_exit;
}
- acpi_gbl_root_table_list.tables = tables;
- acpi_gbl_root_table_list.max_table_count =
- table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
- acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
-
- return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_store_table
- *
- * PARAMETERS: address - Table address
- * table - Table header
- * length - Table length
- * flags - flags
- *
- * RETURN: Status and table index.
- *
- * DESCRIPTION: Add an ACPI table to the global table list
- *
- ******************************************************************************/
+ if (reload) {
+ /*
+ * Validate the incoming table signature.
+ *
+ * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
+ * 2) We added support for OEMx tables, signature "OEM".
+ * 3) Valid tables were encountered with a null signature, so we just
+ * gave up on validating the signature, (05/2008).
+ * 4) We encountered non-AML tables such as the MADT, which caused
+ * interpreter errors and kernel faults. So now, we once again allow
+ * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
+ */
+ if ((new_table_desc.signature.ascii[0] != 0x00) &&
+ (!ACPI_COMPARE_NAME
+ (&new_table_desc.signature, ACPI_SIG_SSDT))
+ && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
+ {
+ ACPI_BIOS_ERROR((AE_INFO,
+ "Table has invalid signature [%4.4s] (0x%8.8X), "
+ "must be SSDT or OEMx",
+ acpi_ut_valid_acpi_name(new_table_desc.
+ signature.
+ ascii) ?
+ new_table_desc.signature.
+ ascii : "????",
+ new_table_desc.signature.integer));
+
+ status = AE_BAD_SIGNATURE;
+ goto release_and_exit;
+ }
-acpi_status
-acpi_tb_store_table(acpi_physical_address address,
- struct acpi_table_header *table,
- u32 length, u8 flags, u32 *table_index)
-{
- acpi_status status;
- struct acpi_table_desc *new_table;
+ /* Check if table is already registered */
- /* Ensure that there is room for the table in the Root Table List */
+ for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
+ ++i) {
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ if (!acpi_tb_compare_tables(&new_table_desc, i)) {
+ continue;
+ }
- if (acpi_gbl_root_table_list.current_table_count >=
- acpi_gbl_root_table_list.max_table_count) {
- status = acpi_tb_resize_root_table_list();
- if (ACPI_FAILURE(status)) {
- return (status);
+ /*
+ * Note: the current mechanism does not unregister a table if it is
+ * dynamically unloaded. The related namespace entries are deleted,
+ * but the table remains in the root table list.
+ *
+ * The assumption here is that the number of different tables that
+ * will be loaded is actually small, and there is minimal overhead
+ * in just keeping the table in case it is needed again.
+ *
+ * If this assumption changes in the future (perhaps on large
+ * machines with many table load/unload operations), tables will
+ * need to be unregistered when they are unloaded, and slots in the
+ * root table list should be reused when empty.
+ */
+ if (acpi_gbl_root_table_list.tables[i].
+ flags & ACPI_TABLE_IS_LOADED) {
+
+ /* Table is still loaded, this is an error */
+
+ status = AE_ALREADY_EXISTS;
+ goto release_and_exit;
+ } else {
+ /*
+ * Table was unloaded, allow it to be reloaded.
+ * As we are going to return AE_OK to the caller, we should
+ * take the responsibility of freeing the input descriptor.
+ * Refill the input descriptor to ensure
+ * acpi_tb_install_table_with_override() can be called again to
+ * indicate the re-installation.
+ */
+ acpi_tb_uninstall_table(&new_table_desc);
+ *table_index = i;
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ return_ACPI_STATUS(AE_OK);
+ }
}
}
- new_table =
- &acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.
- current_table_count];
-
- /* Initialize added table */
-
- new_table->address = address;
- new_table->pointer = table;
- new_table->length = length;
- new_table->owner_id = 0;
- new_table->flags = flags;
-
- ACPI_MOVE_32_TO_32(&new_table->signature, table->signature);
-
- *table_index = acpi_gbl_root_table_list.current_table_count;
- acpi_gbl_root_table_list.current_table_count++;
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_delete_table
- *
- * PARAMETERS: table_index - Table index
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete one internal ACPI table
- *
- ******************************************************************************/
+ /* Add the table to the global root table list */
-void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
-{
- /* Table must be mapped or allocated */
- if (!table_desc->pointer) {
- return;
+ status = acpi_tb_get_next_root_index(&i);
+ if (ACPI_FAILURE(status)) {
+ goto release_and_exit;
}
- switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
- case ACPI_TABLE_ORIGIN_MAPPED:
-
- acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
- break;
-
- case ACPI_TABLE_ORIGIN_ALLOCATED:
- ACPI_FREE(table_desc->pointer);
- break;
+ *table_index = i;
+ acpi_tb_install_table_with_override(i, &new_table_desc, override);
- /* Not mapped or allocated, there is nothing we can do */
+release_and_exit:
- default:
+ /* Release the temporary table descriptor */
- return;
- }
-
- table_desc->pointer = NULL;
+ acpi_tb_release_temp_table(&new_table_desc);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_terminate
+ * FUNCTION: acpi_tb_override_table
*
- * PARAMETERS: None
+ * PARAMETERS: old_table_desc - Validated table descriptor to be
+ * overridden
*
* RETURN: None
*
- * DESCRIPTION: Delete all internal ACPI tables
+ * DESCRIPTION: Attempt table override by calling the OSL override functions.
+ * Note: If the table is overridden, then the entire new table
+ * is acquired and returned by this function.
+ * Before/after invocation, the table descriptor is in a state
+ * that is "VALIDATED".
*
******************************************************************************/
-void acpi_tb_terminate(void)
+void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
{
- u32 i;
-
- ACPI_FUNCTION_TRACE(tb_terminate);
-
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
-
- /* Delete the individual tables */
+ acpi_status status;
+ char *override_type;
+ struct acpi_table_desc new_table_desc;
+ struct acpi_table_header *table;
+ acpi_physical_address address;
+ u32 length;
- for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
- acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
- }
+ /* (1) Attempt logical override (returns a logical address) */
- /*
- * Delete the root table array if allocated locally. Array cannot be
- * mapped, so we don't need to check for that flag.
- */
- if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
- ACPI_FREE(acpi_gbl_root_table_list.tables);
+ status = acpi_os_table_override(old_table_desc->pointer, &table);
+ if (ACPI_SUCCESS(status) && table) {
+ acpi_tb_acquire_temp_table(&new_table_desc,
+ ACPI_PTR_TO_PHYSADDR(table),
+ ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
+ override_type = "Logical";
+ goto finish_override;
}
- acpi_gbl_root_table_list.tables = NULL;
- acpi_gbl_root_table_list.flags = 0;
- acpi_gbl_root_table_list.current_table_count = 0;
+ /* (2) Attempt physical override (returns a physical address) */
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ status = acpi_os_physical_table_override(old_table_desc->pointer,
+ &address, &length);
+ if (ACPI_SUCCESS(status) && address && length) {
+ acpi_tb_acquire_temp_table(&new_table_desc, address,
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
+ override_type = "Physical";
+ goto finish_override;
+ }
- return_VOID;
-}
+ return; /* There was no override */
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_delete_namespace_by_owner
- *
- * PARAMETERS: table_index - Table index
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete all namespace objects created when this table was loaded.
- *
- ******************************************************************************/
-
-acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
-{
- acpi_owner_id owner_id;
- acpi_status status;
+finish_override:
- ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
+ /* Validate and verify a table before overriding */
- status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ status = acpi_tb_verify_table(&new_table_desc, NULL);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ return;
}
- if (table_index >= acpi_gbl_root_table_list.current_table_count) {
-
- /* The table index does not exist */
-
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return_ACPI_STATUS(AE_NOT_EXIST);
- }
+ ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
+ " %s table override, new table: " ACPI_PRINTF_UINT,
+ old_table_desc->signature.ascii,
+ ACPI_FORMAT_TO_UINT(old_table_desc->address),
+ override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
- /* Get the owner ID for this table, used to delete namespace nodes */
+ /* We can now uninstall the original table */
- owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ acpi_tb_uninstall_table(old_table_desc);
/*
- * Need to acquire the namespace writer lock to prevent interference
- * with any concurrent namespace walks. The interpreter must be
- * released during the deletion since the acquisition of the deletion
- * lock may block, and also since the execution of a namespace walk
- * must be allowed to use the interpreter.
+ * Replace the original table descriptor and keep its state as
+ * "VALIDATED".
*/
- (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
- status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
+ acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
+ new_table_desc.flags,
+ new_table_desc.pointer);
+ acpi_tb_validate_table(old_table_desc);
- acpi_ns_delete_namespace_by_owner(owner_id);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ /* Release the temporary table descriptor */
- acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
- return_ACPI_STATUS(status);
+ acpi_tb_release_temp_table(&new_table_desc);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_allocate_owner_id
+ * FUNCTION: acpi_tb_store_table
*
- * PARAMETERS: table_index - Table index
+ * PARAMETERS: address - Table address
+ * table - Table header
+ * length - Table length
+ * flags - Install flags
+ * table_index - Where the table index is returned
*
- * RETURN: Status
+ * RETURN: Status and table index.
*
- * DESCRIPTION: Allocates owner_id in table_desc
+ * DESCRIPTION: Add an ACPI table to the global table list
*
******************************************************************************/
-acpi_status acpi_tb_allocate_owner_id(u32 table_index)
+acpi_status
+acpi_tb_store_table(acpi_physical_address address,
+ struct acpi_table_header * table,
+ u32 length, u8 flags, u32 *table_index)
{
- acpi_status status = AE_BAD_PARAMETER;
-
- ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
+ acpi_status status;
+ struct acpi_table_desc *table_desc;
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- if (table_index < acpi_gbl_root_table_list.current_table_count) {
- status = acpi_ut_allocate_owner_id
- (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
+ status = acpi_tb_get_next_root_index(table_index);
+ if (ACPI_FAILURE(status)) {
+ return (status);
}
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_release_owner_id
- *
- * PARAMETERS: table_index - Table index
- *
- * RETURN: Status
- *
- * DESCRIPTION: Releases owner_id in table_desc
- *
- ******************************************************************************/
-
-acpi_status acpi_tb_release_owner_id(u32 table_index)
-{
- acpi_status status = AE_BAD_PARAMETER;
-
- ACPI_FUNCTION_TRACE(tb_release_owner_id);
-
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- if (table_index < acpi_gbl_root_table_list.current_table_count) {
- acpi_ut_release_owner_id(&
- (acpi_gbl_root_table_list.
- tables[table_index].owner_id));
- status = AE_OK;
- }
+ /* Initialize added table */
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return_ACPI_STATUS(status);
+ table_desc = &acpi_gbl_root_table_list.tables[*table_index];
+ acpi_tb_init_table_descriptor(table_desc, address, flags, table);
+ table_desc->pointer = table;
+ return (AE_OK);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_get_owner_id
+ * FUNCTION: acpi_tb_uninstall_table
*
- * PARAMETERS: table_index - Table index
- * owner_id - Where the table owner_id is returned
+ * PARAMETERS: table_desc - Table descriptor
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: returns owner_id for the ACPI table
+ * DESCRIPTION: Delete one internal ACPI table
*
******************************************************************************/
-acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
+void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
{
- acpi_status status = AE_BAD_PARAMETER;
-
- ACPI_FUNCTION_TRACE(tb_get_owner_id);
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- if (table_index < acpi_gbl_root_table_list.current_table_count) {
- *owner_id =
- acpi_gbl_root_table_list.tables[table_index].owner_id;
- status = AE_OK;
- }
+ ACPI_FUNCTION_TRACE(tb_uninstall_table);
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_is_table_loaded
- *
- * PARAMETERS: table_index - Table index
- *
- * RETURN: Table Loaded Flag
- *
- ******************************************************************************/
+ /* Table must be installed */
-u8 acpi_tb_is_table_loaded(u32 table_index)
-{
- u8 is_loaded = FALSE;
-
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- if (table_index < acpi_gbl_root_table_list.current_table_count) {
- is_loaded = (u8)
- (acpi_gbl_root_table_list.tables[table_index].flags &
- ACPI_TABLE_IS_LOADED);
+ if (!table_desc->address) {
+ return_VOID;
}
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
- return (is_loaded);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_set_table_loaded_flag
- *
- * PARAMETERS: table_index - Table index
- * is_loaded - TRUE if table is loaded, FALSE otherwise
- *
- * RETURN: None
- *
- * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
- *
- ******************************************************************************/
-
-void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
-{
+ acpi_tb_invalidate_table(table_desc);
- (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
- if (table_index < acpi_gbl_root_table_list.current_table_count) {
- if (is_loaded) {
- acpi_gbl_root_table_list.tables[table_index].flags |=
- ACPI_TABLE_IS_LOADED;
- } else {
- acpi_gbl_root_table_list.tables[table_index].flags &=
- ~ACPI_TABLE_IS_LOADED;
- }
+ if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
+ ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
+ ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
}
- (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
+ return_VOID;
}
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 9fb85f38de90..e1638ad5db4c 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -178,9 +178,13 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
}
ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length);
- acpi_tb_delete_table(table_desc);
- table_desc->pointer = new_table;
- table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+ acpi_tb_uninstall_table(table_desc);
+
+ acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
+ tables[ACPI_TABLE_INDEX_DSDT],
+ ACPI_PTR_TO_PHYSADDR(new_table),
+ ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
+ new_table);
ACPI_INFO((AE_INFO,
"Forced DSDT copy: length 0x%05X copied locally, original unmapped",
@@ -191,116 +195,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
/*******************************************************************************
*
- * FUNCTION: acpi_tb_install_table
- *
- * PARAMETERS: address - Physical address of DSDT or FACS
- * signature - Table signature, NULL if no need to
- * match
- * table_index - Index into root table array
- *
- * RETURN: None
- *
- * DESCRIPTION: Install an ACPI table into the global data structure. The
- * table override mechanism is called to allow the host
- * OS to replace any table before it is installed in the root
- * table array.
- *
- ******************************************************************************/
-
-void
-acpi_tb_install_table(acpi_physical_address address,
- char *signature, u32 table_index)
-{
- struct acpi_table_header *table;
- struct acpi_table_header *final_table;
- struct acpi_table_desc *table_desc;
-
- if (!address) {
- ACPI_ERROR((AE_INFO,
- "Null physical address for ACPI table [%s]",
- signature));
- return;
- }
-
- /* Map just the table header */
-
- table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
- if (!table) {
- ACPI_ERROR((AE_INFO,
- "Could not map memory for table [%s] at %p",
- signature, ACPI_CAST_PTR(void, address)));
- return;
- }
-
- /* If a particular signature is expected (DSDT/FACS), it must match */
-
- if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
- ACPI_BIOS_ERROR((AE_INFO,
- "Invalid signature 0x%X for ACPI table, expected [%s]",
- *ACPI_CAST_PTR(u32, table->signature),
- signature));
- goto unmap_and_exit;
- }
-
- /*
- * Initialize the table entry. Set the pointer to NULL, since the
- * table is not fully mapped at this time.
- */
- table_desc = &acpi_gbl_root_table_list.tables[table_index];
-
- table_desc->address = address;
- table_desc->pointer = NULL;
- table_desc->length = table->length;
- table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED;
- ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
-
- /*
- * ACPI Table Override:
- *
- * Before we install the table, let the host OS override it with a new
- * one if desired. Any table within the RSDT/XSDT can be replaced,
- * including the DSDT which is pointed to by the FADT.
- *
- * NOTE: If the table is overridden, then final_table will contain a
- * mapped pointer to the full new table. If the table is not overridden,
- * or if there has been a physical override, then the table will be
- * fully mapped later (in verify table). In any case, we must
- * unmap the header that was mapped above.
- */
- final_table = acpi_tb_table_override(table, table_desc);
- if (!final_table) {
- final_table = table; /* There was no override */
- }
-
- acpi_tb_print_table_header(table_desc->address, final_table);
-
- /* Set the global integer width (based upon revision of the DSDT) */
-
- if (table_index == ACPI_TABLE_INDEX_DSDT) {
- acpi_ut_set_integer_width(final_table->revision);
- }
-
- /*
- * If we have a physical override during this early loading of the ACPI
- * tables, unmap the table for now. It will be mapped again later when
- * it is actually used. This supports very early loading of ACPI tables,
- * before virtual memory is fully initialized and running within the
- * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE
- * flag set and will not be deleted below.
- */
- if (final_table != table) {
- acpi_tb_delete_table(table_desc);
- }
-
-unmap_and_exit:
-
- /* Always unmap the table header that we mapped above */
-
- acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_tb_get_root_table_entry
*
* PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry
@@ -465,6 +359,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
u32 length;
u8 *table_entry;
acpi_status status;
+ u32 table_index;
ACPI_FUNCTION_TRACE(tb_parse_root_table);
@@ -576,31 +471,24 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
/* Initialize the root table array from the RSDT/XSDT */
for (i = 0; i < table_count; i++) {
- if (acpi_gbl_root_table_list.current_table_count >=
- acpi_gbl_root_table_list.max_table_count) {
-
- /* There is no more room in the root table array, attempt resize */
-
- status = acpi_tb_resize_root_table_list();
- if (ACPI_FAILURE(status)) {
- ACPI_WARNING((AE_INFO,
- "Truncating %u table entries!",
- (unsigned) (table_count -
- (acpi_gbl_root_table_list.
- current_table_count -
- 2))));
- break;
- }
- }
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
- acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.
- current_table_count].address =
- acpi_tb_get_root_table_entry(table_entry, table_entry_size);
+ status =
+ acpi_tb_install_standard_table(acpi_tb_get_root_table_entry
+ (table_entry,
+ table_entry_size),
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
+ FALSE, TRUE, &table_index);
+
+ if (ACPI_SUCCESS(status) &&
+ ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
+ tables[table_index].signature,
+ ACPI_SIG_FADT)) {
+ acpi_tb_parse_fadt(table_index);
+ }
table_entry += table_entry_size;
- acpi_gbl_root_table_list.current_table_count++;
}
/*
@@ -609,22 +497,5 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
*/
acpi_os_unmap_memory(table, length);
- /*
- * Complete the initialization of the root table array by examining
- * the header of each table
- */
- for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) {
- acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
- address, NULL, i);
-
- /* Special case for FADT - validate it then get the DSDT and FACS */
-
- if (ACPI_COMPARE_NAME
- (&acpi_gbl_root_table_list.tables[i].signature,
- ACPI_SIG_FADT)) {
- acpi_tb_parse_fadt(i);
- }
- }
-
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index a1593159d9ea..6482b0ded652 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -206,8 +206,8 @@ acpi_status
acpi_get_table_header(char *signature,
u32 instance, struct acpi_table_header *out_table_header)
{
- u32 i;
- u32 j;
+ u32 i;
+ u32 j;
struct acpi_table_header *header;
/* Parameter validation */
@@ -233,7 +233,7 @@ acpi_get_table_header(char *signature,
if (!acpi_gbl_root_table_list.tables[i].pointer) {
if ((acpi_gbl_root_table_list.tables[i].flags &
ACPI_TABLE_ORIGIN_MASK) ==
- ACPI_TABLE_ORIGIN_MAPPED) {
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
header =
acpi_os_map_memory(acpi_gbl_root_table_list.
tables[i].address,
@@ -321,8 +321,8 @@ acpi_get_table_with_size(char *signature,
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size)
{
- u32 i;
- u32 j;
+ u32 i;
+ u32 j;
acpi_status status;
/* Parameter validation */
@@ -346,7 +346,7 @@ acpi_get_table_with_size(char *signature,
}
status =
- acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
+ acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]);
if (ACPI_SUCCESS(status)) {
*out_table = acpi_gbl_root_table_list.tables[i].pointer;
*tbl_size = acpi_gbl_root_table_list.tables[i].length;
@@ -390,7 +390,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
*
******************************************************************************/
acpi_status
-acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header ** table)
{
acpi_status status;
@@ -416,8 +416,8 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
/* Table is not mapped, map it */
status =
- acpi_tb_verify_table(&acpi_gbl_root_table_list.
- tables[table_index]);
+ acpi_tb_validate_table(&acpi_gbl_root_table_list.
+ tables[table_index]);
if (ACPI_FAILURE(status)) {
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index 0909420fc776..ab5308b81aa8 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -117,7 +117,7 @@ static acpi_status acpi_tb_load_namespace(void)
tables[ACPI_TABLE_INDEX_DSDT].signature),
ACPI_SIG_DSDT)
||
- ACPI_FAILURE(acpi_tb_verify_table
+ ACPI_FAILURE(acpi_tb_validate_table
(&acpi_gbl_root_table_list.
tables[ACPI_TABLE_INDEX_DSDT]))) {
status = AE_NO_ACPI_TABLES;
@@ -128,7 +128,7 @@ static acpi_status acpi_tb_load_namespace(void)
* Save the DSDT pointer for simple access. This is the mapped memory
* address. We must take care here because the address of the .Tables
* array can change dynamically as tables are loaded at run-time. Note:
- * .Pointer field is not validated until after call to acpi_tb_verify_table.
+ * .Pointer field is not validated until after call to acpi_tb_validate_table.
*/
acpi_gbl_DSDT =
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
@@ -174,24 +174,11 @@ static acpi_status acpi_tb_load_namespace(void)
(acpi_gbl_root_table_list.tables[i].
signature), ACPI_SIG_PSDT))
||
- ACPI_FAILURE(acpi_tb_verify_table
+ ACPI_FAILURE(acpi_tb_validate_table
(&acpi_gbl_root_table_list.tables[i]))) {
continue;
}
- /*
- * Optionally do not load any SSDTs from the RSDT/XSDT. This can
- * be useful for debugging ACPI problems on some machines.
- */
- if (acpi_gbl_disable_ssdt_table_load) {
- ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p",
- acpi_gbl_root_table_list.tables[i].signature.
- ascii, ACPI_CAST_PTR(void,
- acpi_gbl_root_table_list.
- tables[i].address)));
- continue;
- }
-
/* Ignore errors while loading tables, get as many as possible */
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
@@ -208,6 +195,45 @@ unlock_and_exit:
/*******************************************************************************
*
+ * FUNCTION: acpi_install_table
+ *
+ * PARAMETERS: address - Address of the ACPI table to be installed.
+ * physical - Whether the address is a physical table
+ * address or not
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Dynamically install an ACPI table.
+ * Note: This function should only be invoked after
+ * acpi_initialize_tables() and before acpi_load_tables().
+ *
+ ******************************************************************************/
+
+acpi_status __init
+acpi_install_table(acpi_physical_address address, u8 physical)
+{
+ acpi_status status;
+ u8 flags;
+ u32 table_index;
+
+ ACPI_FUNCTION_TRACE(acpi_install_table);
+
+ if (physical) {
+ flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
+ } else {
+ flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
+ }
+
+ status = acpi_tb_install_standard_table(address, flags,
+ FALSE, FALSE, &table_index);
+
+ return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_load_table
*
* PARAMETERS: table - Pointer to a buffer containing the ACPI
@@ -222,11 +248,9 @@ unlock_and_exit:
* to ensure that the table is not deleted or unmapped.
*
******************************************************************************/
-
acpi_status acpi_load_table(struct acpi_table_header *table)
{
acpi_status status;
- struct acpi_table_desc table_desc;
u32 table_index;
ACPI_FUNCTION_TRACE(acpi_load_table);
@@ -237,14 +261,6 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Init local table descriptor */
-
- ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
- table_desc.address = ACPI_PTR_TO_PHYSADDR(table);
- table_desc.pointer = table;
- table_desc.length = table->length;
- table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
-
/* Must acquire the interpreter lock during this operation */
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
@@ -255,7 +271,24 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
/* Install the table and load it into the namespace */
ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
- status = acpi_tb_add_table(&table_desc, &table_index);
+ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+ status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
+ ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
+ TRUE, FALSE, &table_index);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
+ }
+
+ /*
+ * Note: Now table is "INSTALLED", it must be validated before
+ * using.
+ */
+ status =
+ acpi_tb_validate_table(&acpi_gbl_root_table_list.
+ tables[table_index]);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index fbfa9eca011f..90ec37c473c6 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -462,7 +462,7 @@ char *acpi_ut_get_mutex_name(u32 mutex_id)
/* Names for Notify() values, used for debug output */
-static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = {
+static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
/* 00 */ "Bus Check",
/* 01 */ "Device Check",
/* 02 */ "Device Wake",
@@ -473,23 +473,75 @@ static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = {
/* 07 */ "Power Fault",
/* 08 */ "Capabilities Check",
/* 09 */ "Device PLD Check",
- /* 10 */ "Reserved",
- /* 11 */ "System Locality Update",
- /* 12 */ "Shutdown Request"
+ /* 0A */ "Reserved",
+ /* 0B */ "System Locality Update",
+ /* 0C */ "Shutdown Request"
};
-const char *acpi_ut_get_notify_name(u32 notify_value)
+static const char *acpi_gbl_device_notify[4] = {
+ /* 80 */ "Status Change",
+ /* 81 */ "Information Change",
+ /* 82 */ "Device-Specific Change",
+ /* 83 */ "Device-Specific Change"
+};
+
+static const char *acpi_gbl_processor_notify[4] = {
+ /* 80 */ "Performance Capability Change",
+ /* 81 */ "C-State Change",
+ /* 82 */ "Throttling Capability Change",
+ /* 83 */ "Device-Specific Change"
+};
+
+static const char *acpi_gbl_thermal_notify[4] = {
+ /* 80 */ "Thermal Status Change",
+ /* 81 */ "Thermal Trip Point Change",
+ /* 82 */ "Thermal Device List Change",
+ /* 83 */ "Thermal Relationship Change"
+};
+
+const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
{
+ /* 00 - 0C are common to all object types */
+
if (notify_value <= ACPI_NOTIFY_MAX) {
- return (acpi_gbl_notify_value_names[notify_value]);
- } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
+ return (acpi_gbl_generic_notify[notify_value]);
+ }
+
+ /* 0D - 7F are reserved */
+
+ if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
- } else if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
- return ("Device Specific");
- } else {
- return ("Hardware Specific");
}
+
+ /* 80 - 83 are per-object-type */
+
+ if (notify_value <= 0x83) {
+ switch (type) {
+ case ACPI_TYPE_ANY:
+ case ACPI_TYPE_DEVICE:
+ return (acpi_gbl_device_notify[notify_value - 0x80]);
+
+ case ACPI_TYPE_PROCESSOR:
+ return (acpi_gbl_processor_notify[notify_value - 0x80]);
+
+ case ACPI_TYPE_THERMAL:
+ return (acpi_gbl_thermal_notify[notify_value - 0x80]);
+
+ default:
+ return ("Target object type does not support notifies");
+ }
+ }
+
+ /* 84 - BF are device-specific */
+
+ if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
+ return ("Device-Specific");
+ }
+
+ /* C0 and above are hardware-specific */
+
+ return ("Hardware-Specific");
}
#endif
diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c
index 77219336c7e0..6dc54b3c28b0 100644
--- a/drivers/acpi/acpica/utstring.c
+++ b/drivers/acpi/acpica/utstring.c
@@ -353,7 +353,7 @@ void acpi_ut_print_string(char *string, u16 max_length)
}
acpi_os_printf("\"");
- for (i = 0; string[i] && (i < max_length); i++) {
+ for (i = 0; (i < max_length) && string[i]; i++) {
/* Escape sequences */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6776c599816f..9aeae41e22fb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1770,16 +1770,15 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
}
#endif
-static int __init acpi_no_auto_ssdt_setup(char *s)
+static int __init acpi_no_static_ssdt_setup(char *s)
{
- printk(KERN_NOTICE PREFIX "SSDT auto-load disabled\n");
+ acpi_gbl_disable_ssdt_table_install = TRUE;
+ pr_info("ACPI: static SSDT installation disabled\n");
- acpi_gbl_disable_ssdt_table_load = TRUE;
-
- return 1;
+ return 0;
}
-__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
+early_param("acpi_no_static_ssdt", acpi_no_static_ssdt_setup);
static int __init acpi_disable_return_repair(char *s)
{