diff options
| author | Matthew Garrett <mjg@redhat.com> | 2010-05-28 16:32:14 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2010-06-10 11:02:34 -0400 |
| commit | dd4c4f17d722ffeb2515bf781400675a30fcead7 (patch) | |
| tree | 0190eff340ffeac7800a3d7d1e0c1232c09397ef | |
| parent | 67a3e12b05e055c0415c556a315a3d3eb637e29e (diff) | |
suspend: Move NVS save/restore code to generic suspend functionality
Saving platform non-volatile state may be required for suspend to RAM as
well as hibernation. Move it to more generic code.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | arch/x86/kernel/e820.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/sleep.c | 12 | ||||
| -rw-r--r-- | include/linux/suspend.h | 26 | ||||
| -rw-r--r-- | kernel/power/Kconfig | 9 | ||||
| -rw-r--r-- | kernel/power/Makefile | 2 | ||||
| -rw-r--r-- | kernel/power/nvs.c (renamed from kernel/power/hibernate_nvs.c) | 24 | ||||
| -rw-r--r-- | kernel/power/suspend.c | 6 |
7 files changed, 44 insertions, 37 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 7bca3c6a02fb..0d6fc71bedb1 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
| @@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void) | |||
| 729 | struct e820entry *ei = &e820.map[i]; | 729 | struct e820entry *ei = &e820.map[i]; |
| 730 | 730 | ||
| 731 | if (ei->type == E820_NVS) | 731 | if (ei->type == E820_NVS) |
| 732 | hibernate_nvs_register(ei->addr, ei->size); | 732 | suspend_nvs_register(ei->addr, ei->size); |
| 733 | } | 733 | } |
| 734 | 734 | ||
| 735 | return 0; | 735 | return 0; |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4ab2275b4461..bcaa6efa8136 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -393,7 +393,7 @@ static int acpi_hibernation_begin(void) | |||
| 393 | { | 393 | { |
| 394 | int error; | 394 | int error; |
| 395 | 395 | ||
| 396 | error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); | 396 | error = s4_no_nvs ? 0 : suspend_nvs_alloc(); |
| 397 | if (!error) { | 397 | if (!error) { |
| 398 | acpi_target_sleep_state = ACPI_STATE_S4; | 398 | acpi_target_sleep_state = ACPI_STATE_S4; |
| 399 | acpi_sleep_tts_switch(acpi_target_sleep_state); | 399 | acpi_sleep_tts_switch(acpi_target_sleep_state); |
| @@ -407,7 +407,7 @@ static int acpi_hibernation_pre_snapshot(void) | |||
| 407 | int error = acpi_pm_prepare(); | 407 | int error = acpi_pm_prepare(); |
| 408 | 408 | ||
| 409 | if (!error) | 409 | if (!error) |
| 410 | hibernate_nvs_save(); | 410 | suspend_nvs_save(); |
| 411 | 411 | ||
| 412 | return error; | 412 | return error; |
| 413 | } | 413 | } |
| @@ -432,7 +432,7 @@ static int acpi_hibernation_enter(void) | |||
| 432 | 432 | ||
| 433 | static void acpi_hibernation_finish(void) | 433 | static void acpi_hibernation_finish(void) |
| 434 | { | 434 | { |
| 435 | hibernate_nvs_free(); | 435 | suspend_nvs_free(); |
| 436 | acpi_pm_finish(); | 436 | acpi_pm_finish(); |
| 437 | } | 437 | } |
| 438 | 438 | ||
| @@ -452,7 +452,7 @@ static void acpi_hibernation_leave(void) | |||
| 452 | panic("ACPI S4 hardware signature mismatch"); | 452 | panic("ACPI S4 hardware signature mismatch"); |
| 453 | } | 453 | } |
| 454 | /* Restore the NVS memory area */ | 454 | /* Restore the NVS memory area */ |
| 455 | hibernate_nvs_restore(); | 455 | suspend_nvs_restore(); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | static int acpi_pm_pre_restore(void) | 458 | static int acpi_pm_pre_restore(void) |
| @@ -501,7 +501,7 @@ static int acpi_hibernation_begin_old(void) | |||
| 501 | 501 | ||
| 502 | if (!error) { | 502 | if (!error) { |
| 503 | if (!s4_no_nvs) | 503 | if (!s4_no_nvs) |
| 504 | error = hibernate_nvs_alloc(); | 504 | error = suspend_nvs_alloc(); |
| 505 | if (!error) | 505 | if (!error) |
| 506 | acpi_target_sleep_state = ACPI_STATE_S4; | 506 | acpi_target_sleep_state = ACPI_STATE_S4; |
| 507 | } | 507 | } |
| @@ -513,7 +513,7 @@ static int acpi_hibernation_pre_snapshot_old(void) | |||
| 513 | int error = acpi_pm_disable_gpes(); | 513 | int error = acpi_pm_disable_gpes(); |
| 514 | 514 | ||
| 515 | if (!error) | 515 | if (!error) |
| 516 | hibernate_nvs_save(); | 516 | suspend_nvs_save(); |
| 517 | 517 | ||
| 518 | return error; | 518 | return error; |
| 519 | } | 519 | } |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5e781d824e6d..bc7d6bb4cd8e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
| @@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; } | |||
| 256 | static inline bool system_entering_hibernation(void) { return false; } | 256 | static inline bool system_entering_hibernation(void) { return false; } |
| 257 | #endif /* CONFIG_HIBERNATION */ | 257 | #endif /* CONFIG_HIBERNATION */ |
| 258 | 258 | ||
| 259 | #ifdef CONFIG_HIBERNATION_NVS | 259 | #ifdef CONFIG_SUSPEND_NVS |
| 260 | extern int hibernate_nvs_register(unsigned long start, unsigned long size); | 260 | extern int suspend_nvs_register(unsigned long start, unsigned long size); |
| 261 | extern int hibernate_nvs_alloc(void); | 261 | extern int suspend_nvs_alloc(void); |
| 262 | extern void hibernate_nvs_free(void); | 262 | extern void suspend_nvs_free(void); |
| 263 | extern void hibernate_nvs_save(void); | 263 | extern void suspend_nvs_save(void); |
| 264 | extern void hibernate_nvs_restore(void); | 264 | extern void suspend_nvs_restore(void); |
| 265 | #else /* CONFIG_HIBERNATION_NVS */ | 265 | #else /* CONFIG_SUSPEND_NVS */ |
| 266 | static inline int hibernate_nvs_register(unsigned long a, unsigned long b) | 266 | static inline int suspend_nvs_register(unsigned long a, unsigned long b) |
| 267 | { | 267 | { |
| 268 | return 0; | 268 | return 0; |
| 269 | } | 269 | } |
| 270 | static inline int hibernate_nvs_alloc(void) { return 0; } | 270 | static inline int suspend_nvs_alloc(void) { return 0; } |
| 271 | static inline void hibernate_nvs_free(void) {} | 271 | static inline void suspend_nvs_free(void) {} |
| 272 | static inline void hibernate_nvs_save(void) {} | 272 | static inline void suspend_nvs_save(void) {} |
| 273 | static inline void hibernate_nvs_restore(void) {} | 273 | static inline void suspend_nvs_restore(void) {} |
| 274 | #endif /* CONFIG_HIBERNATION_NVS */ | 274 | #endif /* CONFIG_SUSPEND_NVS */ |
| 275 | 275 | ||
| 276 | #ifdef CONFIG_PM_SLEEP | 276 | #ifdef CONFIG_PM_SLEEP |
| 277 | void save_processor_state(void); | 277 | void save_processor_state(void); |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 5c36ea9d55d2..ca6066a6952e 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
| @@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG | |||
| 99 | depends on PM_ADVANCED_DEBUG | 99 | depends on PM_ADVANCED_DEBUG |
| 100 | default n | 100 | default n |
| 101 | 101 | ||
| 102 | config SUSPEND_NVS | ||
| 103 | bool | ||
| 104 | |||
| 102 | config SUSPEND | 105 | config SUSPEND |
| 103 | bool "Suspend to RAM and standby" | 106 | bool "Suspend to RAM and standby" |
| 104 | depends on PM && ARCH_SUSPEND_POSSIBLE | 107 | depends on PM && ARCH_SUSPEND_POSSIBLE |
| 108 | select SUSPEND_NVS if HAS_IOMEM | ||
| 105 | default y | 109 | default y |
| 106 | ---help--- | 110 | ---help--- |
| 107 | Allow the system to enter sleep states in which main memory is | 111 | Allow the system to enter sleep states in which main memory is |
| @@ -130,13 +134,10 @@ config SUSPEND_FREEZER | |||
| 130 | 134 | ||
| 131 | Turning OFF this setting is NOT recommended! If in doubt, say Y. | 135 | Turning OFF this setting is NOT recommended! If in doubt, say Y. |
| 132 | 136 | ||
| 133 | config HIBERNATION_NVS | ||
| 134 | bool | ||
| 135 | |||
| 136 | config HIBERNATION | 137 | config HIBERNATION |
| 137 | bool "Hibernation (aka 'suspend to disk')" | 138 | bool "Hibernation (aka 'suspend to disk')" |
| 138 | depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE | 139 | depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE |
| 139 | select HIBERNATION_NVS if HAS_IOMEM | 140 | select SUSPEND_NVS if HAS_IOMEM |
| 140 | ---help--- | 141 | ---help--- |
| 141 | Enable the suspend to disk (STD) functionality, which is usually | 142 | Enable the suspend to disk (STD) functionality, which is usually |
| 142 | called "hibernation" in user interfaces. STD checkpoints the | 143 | called "hibernation" in user interfaces. STD checkpoints the |
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 524e058dcf06..f9063c6b185d 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
| @@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o | |||
| 10 | obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o | 10 | obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o |
| 11 | obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ | 11 | obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ |
| 12 | block_io.o | 12 | block_io.o |
| 13 | obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o | 13 | obj-$(CONFIG_SUSPEND_NVS) += nvs.o |
| 14 | 14 | ||
| 15 | obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o | 15 | obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o |
diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/nvs.c index fdcad9ed5a7b..1836db60bbb6 100644 --- a/kernel/power/hibernate_nvs.c +++ b/kernel/power/nvs.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | /* | 16 | /* |
| 17 | * Platforms, like ACPI, may want us to save some memory used by them during | 17 | * Platforms, like ACPI, may want us to save some memory used by them during |
| 18 | * hibernation and to restore the contents of this memory during the subsequent | 18 | * suspend and to restore the contents of this memory during the subsequent |
| 19 | * resume. The code below implements a mechanism allowing us to do that. | 19 | * resume. The code below implements a mechanism allowing us to do that. |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| @@ -30,7 +30,7 @@ struct nvs_page { | |||
| 30 | static LIST_HEAD(nvs_list); | 30 | static LIST_HEAD(nvs_list); |
| 31 | 31 | ||
| 32 | /** | 32 | /** |
| 33 | * hibernate_nvs_register - register platform NVS memory region to save | 33 | * suspend_nvs_register - register platform NVS memory region to save |
| 34 | * @start - physical address of the region | 34 | * @start - physical address of the region |
| 35 | * @size - size of the region | 35 | * @size - size of the region |
| 36 | * | 36 | * |
| @@ -38,7 +38,7 @@ static LIST_HEAD(nvs_list); | |||
| 38 | * things so that the data from page-aligned addresses in this region will | 38 | * things so that the data from page-aligned addresses in this region will |
| 39 | * be copied into separate RAM pages. | 39 | * be copied into separate RAM pages. |
| 40 | */ | 40 | */ |
| 41 | int hibernate_nvs_register(unsigned long start, unsigned long size) | 41 | int suspend_nvs_register(unsigned long start, unsigned long size) |
| 42 | { | 42 | { |
| 43 | struct nvs_page *entry, *next; | 43 | struct nvs_page *entry, *next; |
| 44 | 44 | ||
| @@ -68,9 +68,9 @@ int hibernate_nvs_register(unsigned long start, unsigned long size) | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /** | 70 | /** |
| 71 | * hibernate_nvs_free - free data pages allocated for saving NVS regions | 71 | * suspend_nvs_free - free data pages allocated for saving NVS regions |
| 72 | */ | 72 | */ |
| 73 | void hibernate_nvs_free(void) | 73 | void suspend_nvs_free(void) |
| 74 | { | 74 | { |
| 75 | struct nvs_page *entry; | 75 | struct nvs_page *entry; |
| 76 | 76 | ||
| @@ -86,16 +86,16 @@ void hibernate_nvs_free(void) | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | /** | 88 | /** |
| 89 | * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions | 89 | * suspend_nvs_alloc - allocate memory necessary for saving NVS regions |
| 90 | */ | 90 | */ |
| 91 | int hibernate_nvs_alloc(void) | 91 | int suspend_nvs_alloc(void) |
| 92 | { | 92 | { |
| 93 | struct nvs_page *entry; | 93 | struct nvs_page *entry; |
| 94 | 94 | ||
| 95 | list_for_each_entry(entry, &nvs_list, node) { | 95 | list_for_each_entry(entry, &nvs_list, node) { |
| 96 | entry->data = (void *)__get_free_page(GFP_KERNEL); | 96 | entry->data = (void *)__get_free_page(GFP_KERNEL); |
| 97 | if (!entry->data) { | 97 | if (!entry->data) { |
| 98 | hibernate_nvs_free(); | 98 | suspend_nvs_free(); |
| 99 | return -ENOMEM; | 99 | return -ENOMEM; |
| 100 | } | 100 | } |
| 101 | } | 101 | } |
| @@ -103,9 +103,9 @@ int hibernate_nvs_alloc(void) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| 106 | * hibernate_nvs_save - save NVS memory regions | 106 | * suspend_nvs_save - save NVS memory regions |
| 107 | */ | 107 | */ |
| 108 | void hibernate_nvs_save(void) | 108 | void suspend_nvs_save(void) |
| 109 | { | 109 | { |
| 110 | struct nvs_page *entry; | 110 | struct nvs_page *entry; |
| 111 | 111 | ||
| @@ -119,12 +119,12 @@ void hibernate_nvs_save(void) | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | /** | 121 | /** |
| 122 | * hibernate_nvs_restore - restore NVS memory regions | 122 | * suspend_nvs_restore - restore NVS memory regions |
| 123 | * | 123 | * |
| 124 | * This function is going to be called with interrupts disabled, so it | 124 | * This function is going to be called with interrupts disabled, so it |
| 125 | * cannot iounmap the virtual addresses used to access the NVS region. | 125 | * cannot iounmap the virtual addresses used to access the NVS region. |
| 126 | */ | 126 | */ |
| 127 | void hibernate_nvs_restore(void) | 127 | void suspend_nvs_restore(void) |
| 128 | { | 128 | { |
| 129 | struct nvs_page *entry; | 129 | struct nvs_page *entry; |
| 130 | 130 | ||
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 56e7dbb8b996..f37cb7dd4402 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
| @@ -16,6 +16,12 @@ | |||
| 16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
| 17 | #include <linux/syscalls.h> | 17 | #include <linux/syscalls.h> |
| 18 | #include <linux/gfp.h> | 18 | #include <linux/gfp.h> |
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/suspend.h> | ||
| 19 | 25 | ||
| 20 | #include "power.h" | 26 | #include "power.h" |
| 21 | 27 | ||
