Skip to contentSkip to conversation

ACPICA Release 20100331 linuxized patches

PATCH Lin Ming 2 participants 2 messages Apr 8, 2010 – May 1, 2010

Subsystems (4)
lore
Share & tools
lore

Lin Ming

author
#0 lore raw

Hi, Len

This patch series applied cleanly on top of your acpi/test branch. Build and test on my machine and it works well.

[PATCH 1/9] ACPICA: Update comments/headers, no functional change
[PATCH 2/9] ACPICA: Fix for acpi_reallocate_root_table for incorrect root table copy [PATCH 3/9] ACPICA: Add write support for DataTable operation regions [PATCH 4/9] ACPICA: Add detection of corrupted/replaced DSDT
[PATCH 5/9] ACPICA: Add subsystem option to force copy of DSDT to local memory [PATCH 6/9] ACPICA: Update DSDT copy/detection.
[PATCH 7/9] ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT [PATCH 8/9] ACPICA: Minimize the differences between linux GPE code and ACPICA code base [PATCH 9/9] ACPICA: Update version to 20100331.

Patch 7 includes the acpi=copy_dsdt option, DMI backlist and customized ACPICA warning message for corrupt DSDT workaround (bug 14679).

Lin Ming

Quoted 1 line

From d900de0dfc3822022aa68ad1f9d33fe99c75b86a Mon Sep 17 00:00:00 2001

From: Bob Moore <[email protected]>
Date: Thu, 1 Apr 2010 11:04:54 +0800
Subject: [PATCH 1/9] ACPICA: Update comments/headers, no functional change

Also split some long lines.

---
 drivers/acpi/acpica/exmutex.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)
drivers/acpi/acpica/exmutex.c +11 -10
index bb2efcf..f73be97 100644
@@ -85,10 +85,10 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
 		(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
 
 		/*
-		 * Migrate the previous sync level associated with this mutex to the
-		 * previous mutex on the list so that it may be preserved. This handles
-		 * the case where several mutexes have been acquired at the same level,
-		 * but are not released in opposite order.
+		 * Migrate the previous sync level associated with this mutex to
+		 * the previous mutex on the list so that it may be preserved.
+		 * This handles the case where several mutexes have been acquired
+		 * at the same level, but are not released in opposite order.
 		 */
 		(obj_desc->mutex.prev)->mutex.original_sync_level =
 		    obj_desc->mutex.original_sync_level;
@@ -101,8 +101,8 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
  *
  * FUNCTION:    acpi_ex_link_mutex
  *
- * PARAMETERS:  obj_desc        - The mutex to be linked
- *              Thread          - Current executing thread object
+ * PARAMETERS:  obj_desc            - The mutex to be linked
+ *              Thread              - Current executing thread object
  *
  * RETURN:      None
  *
@@ -138,9 +138,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
  *
  * FUNCTION:    acpi_ex_acquire_mutex_object
  *
- * PARAMETERS:  time_desc           - Timeout in milliseconds
+ * PARAMETERS:  Timeout             - Timeout in milliseconds
  *              obj_desc            - Mutex object
- *              Thread              - Current thread state
+ *              thread_id           - Current thread state
  *
  * RETURN:      Status
  *
@@ -234,7 +234,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	/* Must have a valid thread ID */
+	/* Must have a valid thread state struct */
 
 	if (!walk_state->thread) {
 		ACPI_ERROR((AE_INFO,
@@ -435,6 +435,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
 		owner_thread->current_sync_level = previous_sync_level;
 	}
+
 	return_ACPI_STATUS(status);
 }
 
@@ -442,7 +443,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
  *
  * FUNCTION:    acpi_ex_release_all_mutexes
  *
- * PARAMETERS:  Thread          - Current executing thread object
+ * PARAMETERS:  Thread              - Current executing thread object
  *
  * RETURN:      Status
  *
Quoted 1 line

From 50ec566ee569d9890b47de5bf17b27f208eaa647 Mon Sep 17 00:00:00 2001

From: Alexey Starikovskiy <[email protected]>
Date: Thu, 1 Apr 2010 11:06:34 +0800
Subject: [PATCH 2/9] ACPICA: Fix for acpi_reallocate_root_table for incorrect root table copy

When copying the root table to the new allocation, the length used was incorrect. The new size was used instead of the current table size, meaning too much data was copied.

---
 drivers/acpi/acpica/tbxface.c |   23 ++++++++++++++++++-----
 1 files changed, 18 insertions(+), 5 deletions(-)
drivers/acpi/acpica/tbxface.c +18 -5
index 5217a61..684614d 100644
@@ -172,6 +172,7 @@ acpi_status acpi_reallocate_root_table(void)
 {
 	struct acpi_table_desc *tables;
 	acpi_size new_size;
+	acpi_size current_size;
 
 	ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
 
@@ -183,9 +184,15 @@ acpi_status acpi_reallocate_root_table(void)
 		return_ACPI_STATUS(AE_SUPPORT);
 	}
 
-	new_size = ((acpi_size) acpi_gbl_root_table_list.count +
-		    ACPI_ROOT_TABLE_SIZE_INCREMENT) *
-	    sizeof(struct acpi_table_desc);
+	/*
+	 * Get the current size of the root table and add the default
+	 * increment to create the new table size.
+	 */
+	current_size = (acpi_size)
+	    acpi_gbl_root_table_list.count * sizeof(struct acpi_table_desc);
+
+	new_size = current_size +
+	    (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc));
 
 	/* Create new array and copy the old array */
 
@@ -194,10 +201,16 @@ acpi_status acpi_reallocate_root_table(void)
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size);
+	ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size);
 
-	acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count;
+	/*
+	 * Update the root table descriptor. The new size will be the current
+	 * number of tables plus the increment, independent of the reserved
+	 * size of the original table list.
+	 */
 	acpi_gbl_root_table_list.tables = tables;
+	acpi_gbl_root_table_list.size =
+	    acpi_gbl_root_table_list.count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
 	acpi_gbl_root_table_list.flags =
 	    ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
 
Quoted 1 line

From 0b13a3dbf1d38e4d4cb2b5b6a3073db0059302bd Mon Sep 17 00:00:00 2001

From: Bob Moore <[email protected]>
Date: Thu, 1 Apr 2010 11:09:00 +0800
Subject: [PATCH 3/9] ACPICA: Add write support for DataTable operation regions

The original implementation only supported reading from a DataTable region. However, some machines have been seen that actually write to the ACPI table contained in such a region. This change adds support for writing to a DataTable region.

---
 drivers/acpi/acpica/exregion.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)
drivers/acpi/acpica/exregion.c +10 -3
index a8703cc..531000f 100644
@@ -491,8 +491,10 @@ acpi_ex_data_table_space_handler(u32 function,
 {
 	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
 
-	/* Perform the memory read or write */
-
+	/*
+	 * Perform the memory read or write. The bit_width was already
+	 * validated.
+	 */
 	switch (function) {
 	case ACPI_READ:
 
@@ -502,9 +504,14 @@ acpi_ex_data_table_space_handler(u32 function,
 		break;
 
 	case ACPI_WRITE:
+
+		ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address),
+			    ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
+		break;
+
 	default:
 
-		return_ACPI_STATUS(AE_SUPPORT);
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	return_ACPI_STATUS(AE_OK);
Quoted 1 line

From b435982a224b79470f05348d7e8f59f1c277e828 Mon Sep 17 00:00:00 2001

From: Lin Ming <[email protected]>
Date: Thu, 1 Apr 2010 10:47:56 +0800
Subject: [PATCH 4/9] ACPICA: Add detection of corrupted/replaced DSDT

This change adds support to detect a DSDT that has been corrupted and/or replaced from outside the OS (by firmware). This is typically catastrophic for the system, but has been seen on some machines.

https://bugzilla.kernel.org/show_bug.cgi?id=14679

---
 drivers/acpi/acpica/acglobal.h |    5 +++++
 drivers/acpi/acpica/actables.h |    2 ++
 drivers/acpi/acpica/psxface.c  |    4 ++++
 drivers/acpi/acpica/tbutils.c  |   38 ++++++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/tbxface.c  |   32 ++++++++++++--------------------
 5 files changed, 61 insertions(+), 20 deletions(-)
drivers/acpi/acpica/acglobal.h +5 -0
index 2b2e61e..a419fe9 100644
@@ -165,6 +165,11 @@ ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;
 ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status;
 ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
 
+/* DSDT information. Used to check for DSDT corruption */
+
+ACPI_EXTERN struct acpi_table_desc *acpi_gbl_DSDT;
+ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header;
+
 /*
  * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is
  * determined by the revision of the DSDT: If the DSDT revision is less than
drivers/acpi/acpica/actables.h +2 -0
index 8ff3b74..fc52b6f 100644
@@ -107,6 +107,8 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length);
 acpi_status
 acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
 
+void acpi_tb_check_dsdt_header(void);
+
 void
 acpi_tb_install_table(acpi_physical_address address,
 		      char *signature, u32 table_index);
drivers/acpi/acpica/psxface.c +4 -0
index 6064dd4..67e7ad5 100644
@@ -220,6 +220,10 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 
 	ACPI_FUNCTION_TRACE(ps_execute_method);
 
+	/* Quick validation of DSDT header */
+
+	acpi_tb_check_dsdt_header();
+
 	/* Validate the Info and method Node */
 
 	if (!info || !info->resolved_node) {
drivers/acpi/acpica/tbutils.c +38 -0
index f47a70e..07bc743 100644
@@ -349,6 +349,44 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_tb_check_dsdt_header
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
+ *              if the DSDT has been replaced from outside the OS and/or if
+ *              the DSDT header has been corrupted.
+ *
+ ******************************************************************************/
+
+void acpi_tb_check_dsdt_header(void)
+{
+
+	/* Compare original length and checksum to current values */
+
+	if (acpi_gbl_original_dsdt_header.length !=
+	    acpi_gbl_DSDT->pointer->length
+	    || acpi_gbl_original_dsdt_header.checksum !=
+	    acpi_gbl_DSDT->pointer->checksum) {
+		ACPI_ERROR((AE_INFO,
+			    "The DSDT has been corrupted or replaced - old, new headers below"));
+		acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
+		acpi_tb_print_table_header(acpi_gbl_DSDT->address,
+					   acpi_gbl_DSDT->pointer);
+
+		/* Disable further error messages */
+
+		acpi_gbl_original_dsdt_header.length =
+		    acpi_gbl_DSDT->pointer->length;
+		acpi_gbl_original_dsdt_header.checksum =
+		    acpi_gbl_DSDT->pointer->checksum;
+	}
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_tb_install_table
  *
  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
drivers/acpi/acpica/tbxface.c +12 -20
index 684614d..3056510 100644
@@ -518,33 +518,25 @@ static acpi_status acpi_tb_load_namespace(void)
 
 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
+	acpi_gbl_DSDT = &acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT];
+
 	/*
-	 * Load the namespace. The DSDT is required, but any SSDT and PSDT tables
-	 * are optional.
+	 * Load the namespace. The DSDT is required, but any SSDT and
+	 * PSDT tables are optional. Verify the DSDT.
 	 */
 	if (!acpi_gbl_root_table_list.count ||
-	    !ACPI_COMPARE_NAME(&
-			       (acpi_gbl_root_table_list.
-				tables[ACPI_TABLE_INDEX_DSDT].signature),
-			       ACPI_SIG_DSDT)
-	    ||
-	    ACPI_FAILURE(acpi_tb_verify_table
-			 (&acpi_gbl_root_table_list.
-			  tables[ACPI_TABLE_INDEX_DSDT]))) {
+	    !ACPI_COMPARE_NAME(&acpi_gbl_DSDT->signature, ACPI_SIG_DSDT) ||
+	    ACPI_FAILURE(acpi_tb_verify_table(acpi_gbl_DSDT))) {
 		status = AE_NO_ACPI_TABLES;
 		goto unlock_and_exit;
 	}
 
-	/* A valid DSDT is required */
-
-	status =
-	    acpi_tb_verify_table(&acpi_gbl_root_table_list.
-				 tables[ACPI_TABLE_INDEX_DSDT]);
-	if (ACPI_FAILURE(status)) {
-
-		status = AE_NO_ACPI_TABLES;
-		goto unlock_and_exit;
-	}
+	/*
+	 * Save the original DSDT header for detection of table corruption
+	 * and/or replacement of the DSDT from outside the OS.
+	 */
+	ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT->pointer,
+		    sizeof(struct acpi_table_header));
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 
Quoted 1 line

From 0412c9ab3d792c0c6c5ab641c811e45acfe61cd2 Mon Sep 17 00:00:00 2001

From: Lin Ming <[email protected]>
Date: Thu, 1 Apr 2010 11:14:12 +0800
Subject: [PATCH 5/9] ACPICA: Add subsystem option to force copy of DSDT to local memory

Optionally copy the entire DSDT to local memory (instead of simply mapping it.) There are some BIOSs that corrupt or replace the original DSDT, creating the need for this option. Default is FALSE, do not copy the DSDT.

https://bugzilla.kernel.org/show_bug.cgi?id=14679

---
 drivers/acpi/acpica/acglobal.h |    8 ++++++++
 drivers/acpi/acpica/actables.h |    2 ++
 drivers/acpi/acpica/psxface.c  |    1 +
 drivers/acpi/acpica/tbutils.c  |   35 +++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/tbxface.c  |   10 ++++++++++
 include/acpi/acpixf.h          |    1 +
 6 files changed, 57 insertions(+), 0 deletions(-)
drivers/acpi/acpica/acglobal.h +8 -0
index a419fe9..e3813d2 100644
@@ -117,6 +117,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
  */
 u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
 
+/*
+ * Optionally copy the entire DSDT to local memory (instead of simply
+ * mapping it.) There are some BIOSs that corrupt or replace the original
+ * DSDT, creating the need for this option. Default is FALSE, do not copy
+ * the DSDT.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
+
 /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
 
 struct acpi_table_fadt acpi_gbl_FADT;
drivers/acpi/acpica/actables.h +2 -0
index fc52b6f..b7197bf 100644
@@ -109,6 +109,8 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
 
 void acpi_tb_check_dsdt_header(void);
 
+void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc);
+
 void
 acpi_tb_install_table(acpi_physical_address address,
 		      char *signature, u32 table_index);
drivers/acpi/acpica/psxface.c +1 -0
index 67e7ad5..c42f067 100644
@@ -46,6 +46,7 @@
 #include "acparser.h"
 #include "acdispat.h"
 #include "acinterp.h"
+#include "actables.h"
 #include "amlcode.h"
 
 #define _COMPONENT          ACPI_PARSER
drivers/acpi/acpica/tbutils.c +35 -0
index 07bc743..1efb094 100644
@@ -387,6 +387,41 @@ void acpi_tb_check_dsdt_header(void)
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_tb_copy_dsdt
+ *
+ * PARAMETERS:  table_desc          - Installed table to copy
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
+ *              Some very bad BIOSs are known to either corrupt the DSDT or
+ *              install a new, bad DSDT. This copy works around the problem.
+ *
+ ******************************************************************************/
+
+void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc)
+{
+	struct acpi_table_header *new_table;
+
+	new_table = ACPI_ALLOCATE(table_desc->length);
+	if (!new_table) {
+		ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
+			    table_desc->length));
+		return;
+	}
+
+	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_INFO((AE_INFO,
+		   "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
+		   new_table->length));
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_tb_install_table
  *
  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
drivers/acpi/acpica/tbxface.c +10 -0
index 3056510..f5378fc 100644
@@ -532,6 +532,16 @@ static acpi_status acpi_tb_load_namespace(void)
 	}
 
 	/*
+	 * Optionally copy the entire DSDT to local memory (instead of simply
+	 * mapping it.) There are some BIOSs that corrupt or replace the original
+	 * DSDT, creating the need for this option. Default is FALSE, do not copy
+	 * the DSDT.
+	 */
+	if (acpi_gbl_copy_dsdt_locally) {
+		acpi_tb_copy_dsdt(acpi_gbl_DSDT);
+	}
+
+	/*
 	 * Save the original DSDT header for detection of table corruption
 	 * and/or replacement of the DSDT from outside the OS.
 	 */
include/acpi/acpixf.h +1 -0
index f753222..fd815f6 100644
@@ -68,6 +68,7 @@ extern u8 acpi_gbl_use_default_register_widths;
 extern acpi_name acpi_gbl_trace_method_name;
 extern u32 acpi_gbl_trace_flags;
 extern u8 acpi_gbl_enable_aml_debug_object;
+extern u8 acpi_gbl_copy_dsdt_locally;
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
Quoted 1 line

From 39de59b737a3cc09e125f5a11decc08fc5f0884e Mon Sep 17 00:00:00 2001

From: Bob Moore <[email protected]>
Date: Wed, 7 Apr 2010 11:05:11 +0800
Subject: [PATCH 6/9] ACPICA: Update DSDT copy/detection.

Move initialization of DSDT pointer. Emit address of DSDT in the dump of both table headers (good/bad DSDT). Now handles the case where the root table can be reallocated, which would invalidate the original pointer.

---
 drivers/acpi/acpica/acglobal.h |    2 +-
 drivers/acpi/acpica/actables.h |    2 +-
 drivers/acpi/acpica/tbutils.c  |   23 ++++++++++++-----------
 drivers/acpi/acpica/tbxface.c  |   29 +++++++++++++++++++++++------
 drivers/acpi/acpica/utglobal.c |    1 +
 5 files changed, 38 insertions(+), 19 deletions(-)
drivers/acpi/acpica/acglobal.h +1 -1
index e3813d2..87f21d9 100644
@@ -175,7 +175,7 @@ ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
 
 /* DSDT information. Used to check for DSDT corruption */
 
-ACPI_EXTERN struct acpi_table_desc *acpi_gbl_DSDT;
+ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT;
 ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header;
 
 /*
drivers/acpi/acpica/actables.h +1 -1
index b7197bf..62a576e 100644
@@ -109,7 +109,7 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
 
 void acpi_tb_check_dsdt_header(void);
 
-void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc);
+struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
 
 void
 acpi_tb_install_table(acpi_physical_address address,
drivers/acpi/acpica/tbutils.c +12 -11
index 1efb094..54a8712 100644
@@ -366,22 +366,18 @@ void acpi_tb_check_dsdt_header(void)
 
 	/* Compare original length and checksum to current values */
 
-	if (acpi_gbl_original_dsdt_header.length !=
-	    acpi_gbl_DSDT->pointer->length
-	    || acpi_gbl_original_dsdt_header.checksum !=
-	    acpi_gbl_DSDT->pointer->checksum) {
+	if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length ||
+	    acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) {
 		ACPI_ERROR((AE_INFO,
 			    "The DSDT has been corrupted or replaced - old, new headers below"));
 		acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
-		acpi_tb_print_table_header(acpi_gbl_DSDT->address,
-					   acpi_gbl_DSDT->pointer);
+		acpi_tb_print_table_header(0, acpi_gbl_DSDT);
 
 		/* Disable further error messages */
 
-		acpi_gbl_original_dsdt_header.length =
-		    acpi_gbl_DSDT->pointer->length;
+		acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
 		acpi_gbl_original_dsdt_header.checksum =
-		    acpi_gbl_DSDT->pointer->checksum;
+		    acpi_gbl_DSDT->checksum;
 	}
 }
 
@@ -399,15 +395,18 @@ void acpi_tb_check_dsdt_header(void)
  *
  ******************************************************************************/
 
-void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc)
+struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
 {
 	struct acpi_table_header *new_table;
+	struct acpi_table_desc *table_desc;
+
+	table_desc = &acpi_gbl_root_table_list.tables[table_index];
 
 	new_table = ACPI_ALLOCATE(table_desc->length);
 	if (!new_table) {
 		ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
 			    table_desc->length));
-		return;
+		return (NULL);
 	}
 
 	ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length);
@@ -418,6 +417,8 @@ void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc)
 	ACPI_INFO((AE_INFO,
 		   "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
 		   new_table->length));
+
+	return (new_table);
 }
 
 /*******************************************************************************
drivers/acpi/acpica/tbxface.c +23 -6
index f5378fc..adb7f56 100644
@@ -513,39 +513,56 @@ static acpi_status acpi_tb_load_namespace(void)
 {
 	acpi_status status;
 	u32 i;
+	struct acpi_table_header *new_dsdt;
 
 	ACPI_FUNCTION_TRACE(tb_load_namespace);
 
 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
-	acpi_gbl_DSDT = &acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT];
-
 	/*
 	 * Load the namespace. The DSDT is required, but any SSDT and
 	 * PSDT tables are optional. Verify the DSDT.
 	 */
 	if (!acpi_gbl_root_table_list.count ||
-	    !ACPI_COMPARE_NAME(&acpi_gbl_DSDT->signature, ACPI_SIG_DSDT) ||
-	    ACPI_FAILURE(acpi_tb_verify_table(acpi_gbl_DSDT))) {
+	    !ACPI_COMPARE_NAME(&
+			       (acpi_gbl_root_table_list.
+				tables[ACPI_TABLE_INDEX_DSDT].signature),
+			       ACPI_SIG_DSDT)
+	    ||
+	    ACPI_FAILURE(acpi_tb_verify_table
+			 (&acpi_gbl_root_table_list.
+			  tables[ACPI_TABLE_INDEX_DSDT]))) {
 		status = AE_NO_ACPI_TABLES;
 		goto unlock_and_exit;
 	}
 
 	/*
+	 * 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.
+	 */
+	acpi_gbl_DSDT =
+	    acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
+
+	/*
 	 * Optionally copy the entire DSDT to local memory (instead of simply
 	 * mapping it.) There are some BIOSs that corrupt or replace the original
 	 * DSDT, creating the need for this option. Default is FALSE, do not copy
 	 * the DSDT.
 	 */
 	if (acpi_gbl_copy_dsdt_locally) {
-		acpi_tb_copy_dsdt(acpi_gbl_DSDT);
+		new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT);
+		if (new_dsdt) {
+			acpi_gbl_DSDT = new_dsdt;
+		}
 	}
 
 	/*
 	 * Save the original DSDT header for detection of table corruption
 	 * and/or replacement of the DSDT from outside the OS.
 	 */
-	ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT->pointer,
+	ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
 		    sizeof(struct acpi_table_header));
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
drivers/acpi/acpica/utglobal.c +1 -0
index eda3e65..6611675 100644
@@ -785,6 +785,7 @@ acpi_status acpi_ut_init_globals(void)
 
 	/* Miscellaneous variables */
 
+	acpi_gbl_DSDT = NULL;
 	acpi_gbl_cm_single_step = FALSE;
 	acpi_gbl_db_terminate_threads = FALSE;
 	acpi_gbl_shutdown = FALSE;
Quoted 1 line

From 7e8098683e5b7375862d454fa05687270e509683 Mon Sep 17 00:00:00 2001

From: Lin Ming <[email protected]>
Date: Thu, 8 Apr 2010 14:34:27 +0800
Subject: [PATCH 7/9] ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT

Some BIOS on Toshiba machines corrupt the DSDT, so add a new
boot option acpi=copy_dsdt to workaround it.
Add warning message to ask users to use this option if corrupt DSDT detected.

Also build a DMI blacklist to check it and automatically copy DSDT.

https://bugzilla.kernel.org/show_bug.cgi?id=14679

---
 Documentation/kernel-parameters.txt |    1 +
 arch/x86/kernel/acpi/boot.c         |    4 +++
 drivers/acpi/acpica/tbutils.c       |    4 +++
 drivers/acpi/bus.c                  |   37 +++++++++++++++++++++++++++++++++++
 4 files changed, 46 insertions(+), 0 deletions(-)
Documentation/kernel-parameters.txt +1 -0
index 8d9b809..5f613b4 100644
@@ -150,6 +150,7 @@ and is between 256 and 4096 characters. It is defined in the file
 			strict -- Be less tolerant of platforms that are not
 				strictly ACPI specification compliant.
 			rsdt -- prefer RSDT over (default) XSDT
+			copy_dsdt -- copy DSDT to memory
 
 			See also Documentation/power/pm.txt, pci=noacpi
 
arch/x86/kernel/acpi/boot.c +4 -0
index b702343..601ed05 100644
@@ -1563,6 +1563,10 @@ static int __init parse_acpi(char *arg)
 	/* "acpi=noirq" disables ACPI interrupt routing */
 	else if (strcmp(arg, "noirq") == 0) {
 		acpi_noirq_set();
+	}
+	/* "acpi=copy_dsdt" copys DSDT */
+	else if (strcmp(arg, "copy_dsdt") == 0) {
+		acpi_gbl_copy_dsdt_locally = 1;
 	} else {
 		/* Core will printk when we return error. */
 		return -EINVAL;
drivers/acpi/acpica/tbutils.c +4 -0
index 54a8712..a9b105f 100644
@@ -373,6 +373,10 @@ void acpi_tb_check_dsdt_header(void)
 		acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
 		acpi_tb_print_table_header(0, acpi_gbl_DSDT);
 
+		ACPI_ERROR((AE_INFO,
+			    "Please send DMI info to [email protected]\n"
+			    "If system does not work as expected, please boot with acpi=copy_dsdt"));
+
 		/* Disable further error messages */
 
 		acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
drivers/acpi/bus.c +37 -0
index 37132dc..49af19b 100644
@@ -69,6 +69,37 @@ static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = {
 };
 
 
+static int set_copy_dsdt(const struct dmi_system_id *id)
+{
+	printk(KERN_NOTICE "%s detected - "
+		"force copy of DSDT to local memory\n", id->ident);
+	acpi_gbl_copy_dsdt_locally = 1;
+	return 0;
+}
+
+static struct dmi_system_id dsdt_dmi_table[] __initdata = {
+	/*
+	 * Insyde BIOS on some TOSHIBA machines corrupt the DSDT.
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=14679
+	 */
+	{
+	 .callback = set_copy_dsdt,
+	 .ident = "TOSHIBA Satellite A505",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"),
+		},
+	},
+	{
+	 .callback = set_copy_dsdt,
+	 .ident = "TOSHIBA Satellite L505D",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"),
+		},
+	}
+};
+
 /* --------------------------------------------------------------------------
                                 Device Management
    -------------------------------------------------------------------------- */
@@ -813,6 +844,12 @@ void __init acpi_early_init(void)
 
 	acpi_gbl_permanent_mmap = 1;
 
+	/*
+	 * If the machine falls into the DMI check table,
+	 * DSDT will be copied to memory
+	 */
+	dmi_check_system(dsdt_dmi_table);
+
 	status = acpi_reallocate_root_table();
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX
Quoted 1 line

From a3a65368d88237d7c45bc6578b9cf7a07caa56fc Mon Sep 17 00:00:00 2001

From: Lin Ming <[email protected]>
Date: Tue, 6 Apr 2010 14:52:37 +0800
Subject: [PATCH 8/9] ACPICA: Minimize the differences between linux GPE code and ACPICA code base

We have ported Rafael's major GPE changes
(ACPI: Use GPE reference counting to support shared GPEs) into ACPICA code base. But the port and Rafael's original patch have some differences, so we made below patch to make linux GPE code consistent with ACPICA code base.

Most changes are about comments and coding styles. Other noticeable changes are based on:

Rafael: Reduce code duplication related to GPE lookup
https://patchwork.kernel.org/patch/86237/

Rafeal: Always use the same lock for GPE locking
https://patchwork.kernel.org/patch/90471/

A new field gpe_count in struct acpi_gpe_block_info to record the number of individual GPEs in block.

Rename acpi_ev_save_method_info to acpi_ev_match_gpe_method.

---
 drivers/acpi/acpica/acevents.h |    7 +-
 drivers/acpi/acpica/aclocal.h  |    5 +-
 drivers/acpi/acpica/evgpe.c    |  153 +++++++++++++++++++++++---------
 drivers/acpi/acpica/evgpeblk.c |  143 ++++++++++++++++--------------
 drivers/acpi/acpica/evxface.c  |   20 +++--
 drivers/acpi/acpica/evxfevnt.c |  191 +++++++++++++++++++++++----------------
 drivers/acpi/acpica/exoparg2.c |   27 ------
 drivers/acpi/scan.c            |    2 +-
 drivers/acpi/system.c          |    5 +-
 include/acpi/acexcep.h         |    2 +-
 include/acpi/acpixf.h          |   11 ++-
 include/acpi/actypes.h         |   42 ++++-----
 12 files changed, 346 insertions(+), 262 deletions(-)
drivers/acpi/acpica/acevents.h +4 -3
index 3e6ba99..5e094a2 100644
@@ -85,6 +85,10 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
 struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 						       u32 gpe_number);
 
+struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
+						     struct acpi_gpe_block_info
+						     *gpe_block);
+
 /*
  * evgpeblk
  */
@@ -118,9 +122,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
 
 u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
 
-acpi_status
-acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
 acpi_status acpi_ev_gpe_initialize(void);
 
 /*
drivers/acpi/acpica/aclocal.h +3 -2
index 24b8faa..5a6203a 100644
@@ -427,8 +427,8 @@ struct acpi_gpe_event_info {
 	struct acpi_gpe_register_info *register_info;	/* Backpointer to register info */
 	u8 flags;		/* Misc info about this GPE */
 	u8 gpe_number;		/* This GPE */
-	u8 runtime_count;
-	u8 wakeup_count;
+	u8 runtime_count;	/* References to a run GPE */
+	u8 wakeup_count;	/* References to a wake GPE */
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -454,6 +454,7 @@ struct acpi_gpe_block_info {
 	struct acpi_gpe_event_info *event_info;	/* One for each GPE */
 	struct acpi_generic_address block_address;	/* Base address of the block */
 	u32 register_count;	/* Number of register pairs in block */
+	u16 gpe_count;		/* Number of individual GPEs in block */
 	u8 block_base_number;	/* Base GPE number for this block */
 };
 
drivers/acpi/acpica/evgpe.c +109 -44

250 lines not on this page · raw message

drivers/acpi/acpica/evgpeblk.c +76 -67

310 lines not on this page · raw message

drivers/acpi/acpica/evxface.c +11 -9
index ca04823..cc82502 100644
@@ -682,14 +682,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
 
 	/* Parameter validation */
 
-	if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
-		status = AE_BAD_PARAMETER;
-		goto exit;
+	if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
-		goto exit;
+		return_ACPI_STATUS(status);
 	}
 
 	/* Ensure that we have a valid GPE number */
@@ -720,6 +719,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
 	handler->context = context;
 	handler->method_node = gpe_event_info->dispatch.method_node;
 
+	/* Disable the GPE before installing the handler */
+
+	status = acpi_ev_disable_gpe(gpe_event_info);
+	if (ACPI_FAILURE (status)) {
+		goto unlock_and_exit;
+	}
+
 	/* Install the handler */
 
 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
@@ -733,12 +739,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
 
 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 
-      unlock_and_exit:
+unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
-      exit:
-	if (ACPI_FAILURE(status))
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Installing notify handler failed"));
 	return_ACPI_STATUS(status);
 }
 
drivers/acpi/acpica/evxfevnt.c +113 -78

353 lines not on this page · raw message

drivers/acpi/acpica/exoparg2.c +0 -27
index 3f3f48b..10e104c 100644
@@ -119,33 +119,6 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
-#ifdef ACPI_GPE_NOTIFY_CHECK
-		/*
-		 * GPE method wake/notify check.  Here, we want to ensure that we
-		 * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
-		 * GPE method during system runtime.  If we do, the GPE is marked
-		 * as "wake-only" and disabled.
-		 *
-		 * 1) Is the Notify() value == device_wake?
-		 * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
-		 * 3) Did the original GPE happen at system runtime?
-		 *    (versus during wake)
-		 *
-		 * If all three cases are true, this is a wake-only GPE that should
-		 * be disabled at runtime.
-		 */
-		if (value == 2) {	/* device_wake */
-			status =
-			    acpi_ev_check_for_wake_only_gpe(walk_state->
-							    gpe_event_info);
-			if (ACPI_FAILURE(status)) {
-
-				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
-
-				return_ACPI_STATUS(AE_OK)
-			}
-		}
-#endif
 
 		/*
 		 * Dispatch the notify to the appropriate handler
drivers/acpi/scan.c +1 -1
index 0338f51..7f2e051 100644
@@ -765,7 +765,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 	}
 
 	status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number,
-					ACPI_NOT_ISR, &event_status);
+					&event_status);
 	if (status == AE_OK)
 		device->wakeup.flags.run_wake =
 				!!(event_status & ACPI_EVENT_FLAG_HANDLE);
drivers/acpi/system.c +2 -3
index 4aaf249..e35525b 100644
@@ -303,8 +303,7 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
 				"Invalid GPE 0x%x\n", index));
 			goto end;
 		}
-		result = acpi_get_gpe_status(*handle, index,
-						ACPI_NOT_ISR, status);
+		result = acpi_get_gpe_status(*handle, index, status);
 	} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
 		result = acpi_get_event_status(index - num_gpes, status);
 
@@ -395,7 +394,7 @@ static ssize_t counter_set(struct kobject *kobj,
 			result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
 		else if (!strcmp(buf, "clear\n") &&
 				(status & ACPI_EVENT_FLAG_SET))
-			result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR);
+			result = acpi_clear_gpe(handle, index);
 		else
 			all_counters[index].count = strtoul(buf, NULL, 0);
 	} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
include/acpi/acexcep.h +1 -1
index 5b2e5e8..5958d78 100644
@@ -87,7 +87,7 @@
 #define AE_NO_GLOBAL_LOCK               (acpi_status) (0x0017 | AE_CODE_ENVIRONMENTAL)
 #define AE_ABORT_METHOD                 (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL)
 #define AE_SAME_HANDLER                 (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL)
-#define AE_WAKE_ONLY_GPE                (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL)
+#define AE_NO_HANDLER                   (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL)
 #define AE_OWNER_ID_LIMIT               (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
 
 #define AE_CODE_ENV_MAX                 0x001B
include/acpi/acpixf.h +6 -5
index fd815f6..be16f97 100644
@@ -285,16 +285,17 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status);
  */
 acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action);
 
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type);
+acpi_status
+acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type);
 
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type);
+acpi_status
+acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type);
 
-acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags);
+acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
 
 acpi_status
 acpi_get_gpe_status(acpi_handle gpe_device,
-		    u32 gpe_number,
-		    u32 flags, acpi_event_status * event_status);
+		    u32 gpe_number, acpi_event_status *event_status);
 
 acpi_status acpi_disable_all_gpes(void);
 
include/acpi/actypes.h +20 -22

64 lines not on this page · raw message

Quoted 1 line

From 881a682a278c7b9d956c3dc36581210880d109f5 Mon Sep 17 00:00:00 2001

From: Robert Moore <[email protected]>
Date: Thu, 8 Apr 2010 14:57:43 +0800
Subject: [PATCH 9/9] ACPICA: Update version to 20100331.

Version 20100331.

---
 include/acpi/acpixf.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/acpi/acpixf.h +1 -1
index be16f97..e5bce4c 100644
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20100304
+#define ACPI_CA_VERSION                 0x20100331
 
 #include "actypes.h"
 #include "actbl.h"
reviewer
#1 lore raw

applied to acpi-test
(and acpica branch re-based to 2.6.34-rc5 to allow 8/9 to apply)

thanks,
Len Brown, Intel Open Source Technology Center

Quoted 21 lines · Lin Ming

Hi, Len

This patch series applied cleanly on top of your acpi/test branch. Build and test on my machine and it works well.

[PATCH 1/9] ACPICA: Update comments/headers, no functional change
[PATCH 2/9] ACPICA: Fix for acpi_reallocate_root_table for incorrect root table copy [PATCH 3/9] ACPICA: Add write support for DataTable operation regions [PATCH 4/9] ACPICA: Add detection of corrupted/replaced DSDT
[PATCH 5/9] ACPICA: Add subsystem option to force copy of DSDT to local memory [PATCH 6/9] ACPICA: Update DSDT copy/detection.
[PATCH 7/9] ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT [PATCH 8/9] ACPICA: Minimize the differences between linux GPE code and ACPICA code base [PATCH 9/9] ACPICA: Update version to 20100331.

Patch 7 includes the acpi=copy_dsdt option, DMI backlist and customized ACPICA warning message for corrupt DSDT workaround (bug 14679).

Lin Ming