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 <[email protected]> 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 <[email protected]> Signed-off-by: Bob Moore <[email protected]> Signed-off-by: Len Brown <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> 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 <[email protected]> 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 <[email protected]> Signed-off-by: Len Brown <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> 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 [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 = 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 <[email protected]> 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 <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> 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"), }, } }; -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected] Archive: http://lists.debian.org/20110912072749.GA25264@elie

