summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/tables
diff options
context:
space:
mode:
authorRobert Moore <robert.moore@intel.com>2005-07-29 15:15:00 -0700
committerLen Brown <len.brown@intel.com>2005-07-30 00:51:39 -0400
commit0c9938cc75057c0fca1af55a55dcfc2842436695 (patch)
treed18e809bf9e3811f20c609b6515d4d1b8520cfbc /drivers/acpi/tables
parentdd8f39bbf5154cdbfd698fc70c66faba33eafa44 (diff)
downloadlinux-0c9938cc75057c0fca1af55a55dcfc2842436695.tar.gz
linux-0c9938cc75057c0fca1af55a55dcfc2842436695.tar.bz2
linux-0c9938cc75057c0fca1af55a55dcfc2842436695.zip
[ACPI] ACPICA 20050729 from Bob Moore
Implemented support to ignore an attempt to install/load a particular ACPI table more than once. Apparently there exists BIOS code that repeatedly attempts to load the same SSDT upon certain events. Thanks to Venkatesh Pallipadi. Restructured the main interface to the AML parser in order to correctly handle all exceptional conditions. This will prevent leakage of the OwnerId resource and should eliminate the AE_OWNER_ID_LIMIT exceptions seen on some machines. Thanks to Alexey Starikovskiy. Support for "module level code" has been disabled in this version due to a number of issues that have appeared on various machines. The support can be enabled by defining ACPI_ENABLE_MODULE_LEVEL_CODE during subsystem compilation. When the issues are fully resolved, the code will be enabled by default again. Modified the internal functions for debug print support to define the FunctionName parameter as a (const char *) for compatibility with compiler built-in macros such as __FUNCTION__, etc. Linted the entire ACPICA source tree for both 32-bit and 64-bit. Signed-off-by: Robert Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/tables')
-rw-r--r--drivers/acpi/tables/tbinstal.c22
-rw-r--r--drivers/acpi/tables/tbutils.c67
-rw-r--r--drivers/acpi/tables/tbxface.c14
-rw-r--r--drivers/acpi/tables/tbxfroot.c4
4 files changed, 96 insertions, 11 deletions
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 2ad72f204551..698799901f55 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -124,9 +124,7 @@ acpi_tb_match_signature (
*
* RETURN: Status
*
- * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must
- * already be loaded and validated.
- * Install the table into the global data structs.
+ * DESCRIPTION: Install the table into the global data structures.
*
******************************************************************************/
@@ -136,6 +134,7 @@ acpi_tb_install_table (
{
acpi_status status;
+
ACPI_FUNCTION_TRACE ("tb_install_table");
@@ -143,22 +142,33 @@ acpi_tb_install_table (
status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n",
- table_info->pointer->signature, acpi_format_exception (status)));
+ ACPI_REPORT_ERROR (("Could not acquire table mutex, %s\n",
+ acpi_format_exception (status)));
return_ACPI_STATUS (status);
}
+ /*
+ * Ignore a table that is already installed. For example, some BIOS
+ * ASL code will repeatedly attempt to load the same SSDT.
+ */
+ status = acpi_tb_is_table_installed (table_info);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+
/* Install the table into the global data structure */
status = acpi_tb_init_table_descriptor (table_info->type, table_info);
if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n",
+ ACPI_REPORT_ERROR (("Could not install table [%4.4s], %s\n",
table_info->pointer->signature, acpi_format_exception (status)));
}
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n",
acpi_gbl_table_data[table_info->type].name, table_info->pointer));
+
+unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
return_ACPI_STATUS (status);
}
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index e69d01d443d2..6fc1e36e6042 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -61,6 +61,67 @@ acpi_tb_handle_to_object (
/*******************************************************************************
*
+ * FUNCTION: acpi_tb_is_table_installed
+ *
+ * PARAMETERS: new_table_desc - Descriptor for new table being installed
+ *
+ * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed
+ *
+ * DESCRIPTION: Determine if an ACPI table is already installed
+ *
+ * MUTEX: Table data structures should be locked
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_is_table_installed (
+ struct acpi_table_desc *new_table_desc)
+{
+ struct acpi_table_desc *table_desc;
+
+
+ ACPI_FUNCTION_TRACE ("tb_is_table_installed");
+
+
+ /* Get the list descriptor and first table descriptor */
+
+ table_desc = acpi_gbl_table_lists[new_table_desc->type].next;
+
+ /* Examine all installed tables of this type */
+
+ while (table_desc) {
+ /* Compare Revision and oem_table_id */
+
+ if ((table_desc->loaded_into_namespace) &&
+ (table_desc->pointer->revision ==
+ new_table_desc->pointer->revision) &&
+ (!ACPI_MEMCMP (table_desc->pointer->oem_table_id,
+ new_table_desc->pointer->oem_table_id, 8))) {
+ /* This table is already installed */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
+ "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n",
+ new_table_desc->pointer->signature,
+ new_table_desc->pointer->revision,
+ new_table_desc->pointer->oem_table_id));
+
+ new_table_desc->owner_id = table_desc->owner_id;
+ new_table_desc->installed_desc = table_desc;
+
+ return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ }
+
+ /* Get next table on the list */
+
+ table_desc = table_desc->next;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_tb_validate_table_header
*
* PARAMETERS: table_header - Logical pointer to the table
@@ -157,7 +218,7 @@ acpi_tb_verify_table_checksum (
/* Compute the checksum on the table */
- checksum = acpi_tb_checksum (table_header, table_header->length);
+ checksum = acpi_tb_generate_checksum (table_header, table_header->length);
/* Return the appropriate exception */
@@ -175,7 +236,7 @@ acpi_tb_verify_table_checksum (
/*******************************************************************************
*
- * FUNCTION: acpi_tb_checksum
+ * FUNCTION: acpi_tb_generate_checksum
*
* PARAMETERS: Buffer - Buffer to checksum
* Length - Size of the buffer
@@ -187,7 +248,7 @@ acpi_tb_verify_table_checksum (
******************************************************************************/
u8
-acpi_tb_checksum (
+acpi_tb_generate_checksum (
void *buffer,
u32 length)
{
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index ca2dbdd23ed3..e18a05d1b9b3 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -182,10 +182,23 @@ acpi_load_table (
return_ACPI_STATUS (status);
}
+ /* Check signature for a valid table type */
+
+ status = acpi_tb_recognize_table (&table_info, ACPI_TABLE_ALL);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
/* Install the new table into the local data structures */
status = acpi_tb_install_table (&table_info);
if (ACPI_FAILURE (status)) {
+ if (status == AE_ALREADY_EXISTS) {
+ /* Table already exists, no error */
+
+ status = AE_OK;
+ }
+
/* Free table allocated by acpi_tb_get_table_body */
acpi_tb_delete_single_table (&table_info);
@@ -261,6 +274,7 @@ acpi_unload_table (
* simply a position within the hierarchy
*/
acpi_ns_delete_namespace_by_owner (table_desc->owner_id);
+ acpi_ut_release_owner_id (&table_desc->owner_id);
table_desc = table_desc->next;
}
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index abb4c9346560..87dccdda9ae2 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -93,14 +93,14 @@ acpi_tb_validate_rsdp (
/* Check the standard checksum */
- if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
+ if (acpi_tb_generate_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
return (AE_BAD_CHECKSUM);
}
/* Check extended checksum if table version >= 2 */
if ((rsdp->revision >= 2) &&
- (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
+ (acpi_tb_generate_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
return (AE_BAD_CHECKSUM);
}