diff options
-rw-r--r-- | drivers/acpi/sleep/main.c | 12 | ||||
-rw-r--r-- | include/linux/suspend.h | 38 | ||||
-rw-r--r-- | kernel/power/disk.c | 27 |
3 files changed, 64 insertions, 13 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c58dd0bb5506..f20b0ab9ef54 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -230,6 +230,12 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
230 | #endif /* CONFIG_SUSPEND */ | 230 | #endif /* CONFIG_SUSPEND */ |
231 | 231 | ||
232 | #ifdef CONFIG_HIBERNATION | 232 | #ifdef CONFIG_HIBERNATION |
233 | static int acpi_hibernation_start(void) | ||
234 | { | ||
235 | acpi_target_sleep_state = ACPI_STATE_S4; | ||
236 | return 0; | ||
237 | } | ||
238 | |||
233 | static int acpi_hibernation_prepare(void) | 239 | static int acpi_hibernation_prepare(void) |
234 | { | 240 | { |
235 | return acpi_sleep_prepare(ACPI_STATE_S4); | 241 | return acpi_sleep_prepare(ACPI_STATE_S4); |
@@ -258,6 +264,8 @@ static void acpi_hibernation_finish(void) | |||
258 | 264 | ||
259 | /* reset firmware waking vector */ | 265 | /* reset firmware waking vector */ |
260 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 266 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
267 | |||
268 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
261 | } | 269 | } |
262 | 270 | ||
263 | static int acpi_hibernation_pre_restore(void) | 271 | static int acpi_hibernation_pre_restore(void) |
@@ -275,9 +283,11 @@ static void acpi_hibernation_restore_cleanup(void) | |||
275 | } | 283 | } |
276 | 284 | ||
277 | static struct hibernation_ops acpi_hibernation_ops = { | 285 | static struct hibernation_ops acpi_hibernation_ops = { |
286 | .start = acpi_hibernation_start, | ||
287 | .pre_snapshot = acpi_hibernation_prepare, | ||
288 | .finish = acpi_hibernation_finish, | ||
278 | .prepare = acpi_hibernation_prepare, | 289 | .prepare = acpi_hibernation_prepare, |
279 | .enter = acpi_hibernation_enter, | 290 | .enter = acpi_hibernation_enter, |
280 | .finish = acpi_hibernation_finish, | ||
281 | .pre_restore = acpi_hibernation_pre_restore, | 291 | .pre_restore = acpi_hibernation_pre_restore, |
282 | .restore_cleanup = acpi_hibernation_restore_cleanup, | 292 | .restore_cleanup = acpi_hibernation_restore_cleanup, |
283 | }; | 293 | }; |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index dee416c5477f..0044483dd477 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -134,16 +134,42 @@ extern void mark_free_pages(struct zone *zone); | |||
134 | * | 134 | * |
135 | * All three methods must be assigned. | 135 | * All three methods must be assigned. |
136 | * | 136 | * |
137 | * @prepare: prepare system for hibernation | 137 | * @start: Tell the platform driver that we're starting hibernation. |
138 | * @enter: shut down system after state has been saved to disk | 138 | * Called right after shrinking memory and before freezing devices. |
139 | * @finish: finish/clean up after state has been reloaded | 139 | * |
140 | * @pre_restore: prepare system for the restoration from a hibernation image | 140 | * @pre_snapshot: Prepare the platform for creating the hibernation image. |
141 | * @restore_cleanup: clean up after a failing image restoration | 141 | * Called right after devices have been frozen and before the nonboot |
142 | * CPUs are disabled (runs with IRQs on). | ||
143 | * | ||
144 | * @finish: Restore the previous state of the platform after the hibernation | ||
145 | * image has been created *or* put the platform into the normal operation | ||
146 | * mode after the hibernation (the same method is executed in both cases). | ||
147 | * Called right after the nonboot CPUs have been enabled and before | ||
148 | * thawing devices (runs with IRQs on). | ||
149 | * | ||
150 | * @prepare: Prepare the platform for entering the low power state. | ||
151 | * Called right after the hibernation image has been saved and before | ||
152 | * devices are prepared for entering the low power state. | ||
153 | * | ||
154 | * @enter: Put the system into the low power state after the hibernation image | ||
155 | * has been saved to disk. | ||
156 | * Called after the nonboot CPUs have been disabled and all of the low | ||
157 | * level devices have been shut down (runs with IRQs off). | ||
158 | * | ||
159 | * @pre_restore: Prepare system for the restoration from a hibernation image. | ||
160 | * Called right after devices have been frozen and before the nonboot | ||
161 | * CPUs are disabled (runs with IRQs on). | ||
162 | * | ||
163 | * @restore_cleanup: Clean up after a failing image restoration. | ||
164 | * Called right after the nonboot CPUs have been enabled and before | ||
165 | * thawing devices (runs with IRQs on). | ||
142 | */ | 166 | */ |
143 | struct hibernation_ops { | 167 | struct hibernation_ops { |
168 | int (*start)(void); | ||
169 | int (*pre_snapshot)(void); | ||
170 | void (*finish)(void); | ||
144 | int (*prepare)(void); | 171 | int (*prepare)(void); |
145 | int (*enter)(void); | 172 | int (*enter)(void); |
146 | void (*finish)(void); | ||
147 | int (*pre_restore)(void); | 173 | int (*pre_restore)(void); |
148 | void (*restore_cleanup)(void); | 174 | void (*restore_cleanup)(void); |
149 | }; | 175 | }; |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index eb72255b5c86..d17bb14bce7b 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -54,8 +54,9 @@ static struct hibernation_ops *hibernation_ops; | |||
54 | 54 | ||
55 | void hibernation_set_ops(struct hibernation_ops *ops) | 55 | void hibernation_set_ops(struct hibernation_ops *ops) |
56 | { | 56 | { |
57 | if (ops && !(ops->prepare && ops->enter && ops->finish | 57 | if (ops && !(ops->start && ops->pre_snapshot && ops->finish |
58 | && ops->pre_restore && ops->restore_cleanup)) { | 58 | && ops->prepare && ops->enter && ops->pre_restore |
59 | && ops->restore_cleanup)) { | ||
59 | WARN_ON(1); | 60 | WARN_ON(1); |
60 | return; | 61 | return; |
61 | } | 62 | } |
@@ -69,16 +70,26 @@ void hibernation_set_ops(struct hibernation_ops *ops) | |||
69 | mutex_unlock(&pm_mutex); | 70 | mutex_unlock(&pm_mutex); |
70 | } | 71 | } |
71 | 72 | ||
73 | /** | ||
74 | * platform_start - tell the platform driver that we're starting | ||
75 | * hibernation | ||
76 | */ | ||
77 | |||
78 | static int platform_start(int platform_mode) | ||
79 | { | ||
80 | return (platform_mode && hibernation_ops) ? | ||
81 | hibernation_ops->start() : 0; | ||
82 | } | ||
72 | 83 | ||
73 | /** | 84 | /** |
74 | * platform_prepare - prepare the machine for hibernation using the | 85 | * platform_pre_snapshot - prepare the machine for hibernation using the |
75 | * platform driver if so configured and return an error code if it fails | 86 | * platform driver if so configured and return an error code if it fails |
76 | */ | 87 | */ |
77 | 88 | ||
78 | static int platform_prepare(int platform_mode) | 89 | static int platform_pre_snapshot(int platform_mode) |
79 | { | 90 | { |
80 | return (platform_mode && hibernation_ops) ? | 91 | return (platform_mode && hibernation_ops) ? |
81 | hibernation_ops->prepare() : 0; | 92 | hibernation_ops->pre_snapshot() : 0; |
82 | } | 93 | } |
83 | 94 | ||
84 | /** | 95 | /** |
@@ -135,12 +146,16 @@ int hibernation_snapshot(int platform_mode) | |||
135 | if (error) | 146 | if (error) |
136 | return error; | 147 | return error; |
137 | 148 | ||
149 | error = platform_start(platform_mode); | ||
150 | if (error) | ||
151 | return error; | ||
152 | |||
138 | suspend_console(); | 153 | suspend_console(); |
139 | error = device_suspend(PMSG_FREEZE); | 154 | error = device_suspend(PMSG_FREEZE); |
140 | if (error) | 155 | if (error) |
141 | goto Resume_console; | 156 | goto Resume_console; |
142 | 157 | ||
143 | error = platform_prepare(platform_mode); | 158 | error = platform_pre_snapshot(platform_mode); |
144 | if (error) | 159 | if (error) |
145 | goto Resume_devices; | 160 | goto Resume_devices; |
146 | 161 | ||