aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/sleep/main.c12
-rw-r--r--include/linux/suspend.h38
-rw-r--r--kernel/power/disk.c27
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
233static int acpi_hibernation_start(void)
234{
235 acpi_target_sleep_state = ACPI_STATE_S4;
236 return 0;
237}
238
233static int acpi_hibernation_prepare(void) 239static 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
263static int acpi_hibernation_pre_restore(void) 271static int acpi_hibernation_pre_restore(void)
@@ -275,9 +283,11 @@ static void acpi_hibernation_restore_cleanup(void)
275} 283}
276 284
277static struct hibernation_ops acpi_hibernation_ops = { 285static 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 */
143struct hibernation_ops { 167struct 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
55void hibernation_set_ops(struct hibernation_ops *ops) 55void 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
78static 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
78static int platform_prepare(int platform_mode) 89static 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