aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2008-07-24 00:28:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:24 -0400
commitbdfe6b7c681669148dae4db27eb24ee5408ba371 (patch)
tree644b84a7e4a329a635d9a9bc02102424cfb616e2 /drivers/acpi
parent2f15fc4bdf91eb399da3f47a09c55831d9f22826 (diff)
pm: acpi hibernation: utilize hardware signature
ACPI defines a hardware signature. BIOS calculates the signature according to hardware configure and if hardware changes while hibernated, the signature will change. In that case, S4 resume should fail. Still, there may be systems on which this mechanism does not work correctly, so it is better to provide a workaround for them. For this reason, add a new switch to the acpi_sleep= command line argument allowing one to disable hardware signature checking. [shaohua.li@intel.com: build fix] Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Andi Kleen <andi@firstfloor.org> Cc: Len Brown <lenb@kernel.org> Acked-by: Pavel Machek <pavel@ucw.cz> Cc: <Valdis.Kletnieks@vt.edu> Cc: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/sleep/main.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 0489a7d1d42c..313507accf18 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -283,6 +283,15 @@ static struct platform_suspend_ops acpi_suspend_ops_old = {
283#endif /* CONFIG_SUSPEND */ 283#endif /* CONFIG_SUSPEND */
284 284
285#ifdef CONFIG_HIBERNATION 285#ifdef CONFIG_HIBERNATION
286static unsigned long s4_hardware_signature;
287static struct acpi_table_facs *facs;
288static bool nosigcheck;
289
290void __init acpi_no_s4_hw_signature(void)
291{
292 nosigcheck = true;
293}
294
286static int acpi_hibernation_begin(void) 295static int acpi_hibernation_begin(void)
287{ 296{
288 acpi_target_sleep_state = ACPI_STATE_S4; 297 acpi_target_sleep_state = ACPI_STATE_S4;
@@ -316,6 +325,12 @@ static void acpi_hibernation_leave(void)
316 acpi_enable(); 325 acpi_enable();
317 /* Reprogram control registers and execute _BFS */ 326 /* Reprogram control registers and execute _BFS */
318 acpi_leave_sleep_state_prep(ACPI_STATE_S4); 327 acpi_leave_sleep_state_prep(ACPI_STATE_S4);
328 /* Check the hardware signature */
329 if (facs && s4_hardware_signature != facs->hardware_signature) {
330 printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
331 "cannot resume!\n");
332 panic("ACPI S4 hardware signature mismatch");
333 }
319} 334}
320 335
321static void acpi_pm_enable_gpes(void) 336static void acpi_pm_enable_gpes(void)
@@ -544,6 +559,13 @@ int __init acpi_sleep_init(void)
544 &acpi_hibernation_ops_old : &acpi_hibernation_ops); 559 &acpi_hibernation_ops_old : &acpi_hibernation_ops);
545 sleep_states[ACPI_STATE_S4] = 1; 560 sleep_states[ACPI_STATE_S4] = 1;
546 printk(" S4"); 561 printk(" S4");
562 if (!nosigcheck) {
563 acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
564 (struct acpi_table_header **)&facs);
565 if (facs)
566 s4_hardware_signature =
567 facs->hardware_signature;
568 }
547 } 569 }
548#endif 570#endif
549 status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); 571 status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);