diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 4 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 22 | ||||
-rw-r--r-- | include/linux/acpi.h | 1 |
4 files changed, 30 insertions, 1 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4d705713cab..497a98dafda 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -148,10 +148,12 @@ and is between 256 and 4096 characters. It is defined in the file | |||
148 | default: 0 | 148 | default: 0 |
149 | 149 | ||
150 | acpi_sleep= [HW,ACPI] Sleep options | 150 | acpi_sleep= [HW,ACPI] Sleep options |
151 | Format: { s3_bios, s3_mode, s3_beep, old_ordering } | 151 | Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering } |
152 | See Documentation/power/video.txt for s3_bios and s3_mode. | 152 | See Documentation/power/video.txt for s3_bios and s3_mode. |
153 | s3_beep is for debugging; it makes the PC's speaker beep | 153 | s3_beep is for debugging; it makes the PC's speaker beep |
154 | as soon as the kernel's real-mode entry point is called. | 154 | as soon as the kernel's real-mode entry point is called. |
155 | s4_nohwsig prevents ACPI hardware signature from being | ||
156 | used during resume from hibernation. | ||
155 | old_ordering causes the ACPI 1.0 ordering of the _PTS | 157 | old_ordering causes the ACPI 1.0 ordering of the _PTS |
156 | control method, wrt putting devices into low power | 158 | control method, wrt putting devices into low power |
157 | states, to be enforced (the ACPI 2.0 ordering of _PTS is | 159 | states, to be enforced (the ACPI 2.0 ordering of _PTS is |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index a3ddad18aaa..fa2161d5003 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -150,6 +150,10 @@ static int __init acpi_sleep_setup(char *str) | |||
150 | acpi_realmode_flags |= 2; | 150 | acpi_realmode_flags |= 2; |
151 | if (strncmp(str, "s3_beep", 7) == 0) | 151 | if (strncmp(str, "s3_beep", 7) == 0) |
152 | acpi_realmode_flags |= 4; | 152 | acpi_realmode_flags |= 4; |
153 | #ifdef CONFIG_HIBERNATION | ||
154 | if (strncmp(str, "s4_nohwsig", 10) == 0) | ||
155 | acpi_no_s4_hw_signature(); | ||
156 | #endif | ||
153 | if (strncmp(str, "old_ordering", 12) == 0) | 157 | if (strncmp(str, "old_ordering", 12) == 0) |
154 | acpi_old_suspend_ordering(); | 158 | acpi_old_suspend_ordering(); |
155 | str = strchr(str, ','); | 159 | str = strchr(str, ','); |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 0489a7d1d42..313507accf1 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 |
286 | static unsigned long s4_hardware_signature; | ||
287 | static struct acpi_table_facs *facs; | ||
288 | static bool nosigcheck; | ||
289 | |||
290 | void __init acpi_no_s4_hw_signature(void) | ||
291 | { | ||
292 | nosigcheck = true; | ||
293 | } | ||
294 | |||
286 | static int acpi_hibernation_begin(void) | 295 | static 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 | ||
321 | static void acpi_pm_enable_gpes(void) | 336 | static 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); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a1717763937..702f79dad16 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -236,6 +236,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, | |||
236 | const char *name); | 236 | const char *name); |
237 | 237 | ||
238 | #ifdef CONFIG_PM_SLEEP | 238 | #ifdef CONFIG_PM_SLEEP |
239 | void __init acpi_no_s4_hw_signature(void); | ||
239 | void __init acpi_old_suspend_ordering(void); | 240 | void __init acpi_old_suspend_ordering(void); |
240 | #endif /* CONFIG_PM_SLEEP */ | 241 | #endif /* CONFIG_PM_SLEEP */ |
241 | #else /* CONFIG_ACPI */ | 242 | #else /* CONFIG_ACPI */ |