Bug#598104: does not load i915 driver [Toshiba Satellite C650]
retitle 598104 Toshiba Satellite C650: DSDT is borked (acpi errors, slow boot, wifi fails, etc)
reassign 598104 src:linux-2.6 2.6.32-23
fixed 598104 linux-2.6/2.6.36-1~experimental.1
tags 598104 + patch
quit
Hi,
Mirosław Zalewski wrote:
> After testing Ubuntu kernel on Debian, I decided to compile my own
> kernel from sources. At first I checked Debian patches, where I found
> about Debian bug #596709 [1]. Then I learned about kernel bug #14679 [2] and
> patch which solves it [3].
Could you test with 2.6.36 and 2.6.36~rc6 from http://snapshot.debian.org/
to confirm the fix, or apply the following three patches to a squeeze
kernel as described at [1]?
[1] http://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s4.2.2
Thanks, and sorry for the slow response.
commit 1b6ea24923f1
Author: Lin Ming <ming.m.lin@intel.com>
Date: Thu Apr 1 10:47:56 2010 +0800
ACPICA: Add detection of corrupted/replaced DSDT
commit 729df0f848daf2f17d02107199fa92efe909d995 upstream.
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
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 29ba66d5a790..db509183876e 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -160,6 +160,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
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index 01c76b8ea7ba..37bcb67a61e4 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -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);
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index dd9731c29a79..6133894936be 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -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) {
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 1f15497f00d1..2d860ab8990c 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -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
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index a88f02bd6c94..f6d79415bf9a 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -505,33 +505,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);
commit 418ce222c0a5
Author: Lin Ming <ming.m.lin@intel.com>
Date: Thu Apr 8 14:34:27 2010 +0800
ACPI: add boot option acpi=copy_dsdt to fix corrupt DSDT
commit aa2110cb1a7510f9b834adfb39b05d4843a35d35 upstream.
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
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c840e7d6c4a4..7ef886cf240e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -151,6 +151,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
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8ba08c7abd04..35d2d25cc22f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1653,6 +1653,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;
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 2d860ab8990c..314d3f43d7a8 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -376,6 +376,10 @@ void acpi_tb_check_dsdt_header(void)
acpi_tb_print_table_header(acpi_gbl_DSDT->address,
acpi_gbl_DSDT->pointer);
+ ACPI_ERROR((AE_INFO,
+ "Please send DMI info to linux-acpi@vger.kernel.org\n"
+ "If system does not work as expected, please boot with acpi=copy_dsdt"));
+
/* Disable further error messages */
acpi_gbl_original_dsdt_header.length =
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 49f6ededb6b5..26f220b093c6 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -68,6 +68,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
-------------------------------------------------------------------------- */
@@ -812,6 +843,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
commit 535b0c435033
Author: Len Brown <len.brown@intel.com>
Date: Tue Sep 28 22:57:02 2010 -0400
ACPI: invoke DSDT corruption workaround on all Toshiba Satellite
commit 100cf87788c0e9104f6fb1b0ff5f72f73fbbbea3 upstream.
Our list of Toshiba Satellite models that require this workaround
is growing -- so invoke the workaround for the entire product line.
https://bugzilla.kernel.org/show_bug.cgi?id=14679
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 26f220b093c6..c24b21967ad7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -78,23 +78,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id)
static struct dmi_system_id dsdt_dmi_table[] __initdata = {
/*
- * Insyde BIOS on some TOSHIBA machines corrupt the DSDT.
+ * Invoke DSDT corruption work-around on all Toshiba Satellite.
* https://bugzilla.kernel.org/show_bug.cgi?id=14679
*/
{
.callback = set_copy_dsdt,
- .ident = "TOSHIBA Satellite A505",
+ .ident = "TOSHIBA Satellite",
.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"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
},
}
};
Reply to: