RSDT and XSDT may export different FACS tables. Some of the BIOSes only checks one of them when resuming. And Linux reboots instead of resuming because BIOS can't find the waking vector. For example, I have a platform which suspends well, but always reboots instead of resuming when pressing the power button. I found that there are two FACS tables on this platform, XSDT-->FADT1-->Xfacs-->FACS1 |----->facs-| |->FACS2 RSDT-->FADT2-->facs-| Linux uses XSDT on this platform and sets the waking vector in FACS1 when suspending. But it seems that the BIOS only cares for the waking vector in FACS2, thus it reboots when resuming because the waking vector is not set at all. Set the waking vector in inactive FACS table in this patch. Signed-off-by: Zhang Rui <rui.zhang@xxxxxxxxx> --- drivers/acpi/hardware/hwsleep.c | 20 ++++++++++++++++++++ drivers/acpi/tables/tbfadt.c | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) Index: linux-2.6/drivers/acpi/hardware/hwsleep.c =================================================================== --- linux-2.6.orig/drivers/acpi/hardware/hwsleep.c +++ linux-2.6/drivers/acpi/hardware/hwsleep.c @@ -65,6 +65,7 @@ acpi_set_firmware_waking_vector(acpi_phy { struct acpi_table_facs *facs; acpi_status status; + u32 table_index; ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); @@ -92,6 +93,25 @@ acpi_set_firmware_waking_vector(acpi_phy facs->xfirmware_waking_vector = physical_address; } + /* set the firmware vector in the inactive facs table */ + for (table_index = 0, facs = NULL; ; table_index++) { + status = acpi_get_inactive_table_by_index(table_index, + ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, + &facs)); + if (status == AE_TABLE_NOT_SUPPORTED) + continue; + if (ACPI_FAILURE(status)) + break; + + if (!ACPI_COMPARE_NAME(&facs->signature, ACPI_SIG_FACS)) + continue; + + if (facs->version >= 1) + facs->xfirmware_waking_vector = 0; + facs->firmware_waking_vector = (u32)physical_address; + break; + } + return_ACPI_STATUS(AE_OK); } Index: linux-2.6/drivers/acpi/tables/tbfadt.c =================================================================== --- linux-2.6.orig/drivers/acpi/tables/tbfadt.c +++ linux-2.6/drivers/acpi/tables/tbfadt.c @@ -290,11 +290,13 @@ static void acpi_tb_convert_fadt(void) if (!acpi_gbl_FADT.Xfacs) { acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; - } + } else if (acpi_gbl_FADT.Xfacs != acpi_gbl_FADT.facs) + ACPI_WARNING((AE_INFO, "32 bit FACS and 64 bit FACS not match\n")); if (!acpi_gbl_FADT.Xdsdt) { acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; - } + } else if (acpi_gbl_FADT.Xdsdt != acpi_gbl_FADT.dsdt) + ACPI_WARNING((AE_INFO, "32 bit DSDT and 64 bit DSDT not match\n")); /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html