aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/sleep/main.c14
-rw-r--r--include/linux/suspend.h14
-rw-r--r--kernel/power/disk.c33
3 files changed, 45 insertions, 16 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index c37c4ead95c9..31e8e58e1cec 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -281,7 +281,7 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
281#endif /* CONFIG_SUSPEND */ 281#endif /* CONFIG_SUSPEND */
282 282
283#ifdef CONFIG_HIBERNATION 283#ifdef CONFIG_HIBERNATION
284static int acpi_hibernation_start(void) 284static int acpi_hibernation_begin(void)
285{ 285{
286 acpi_target_sleep_state = ACPI_STATE_S4; 286 acpi_target_sleep_state = ACPI_STATE_S4;
287 return 0; 287 return 0;
@@ -341,6 +341,15 @@ static void acpi_hibernation_finish(void)
341 acpi_target_sleep_state = ACPI_STATE_S0; 341 acpi_target_sleep_state = ACPI_STATE_S0;
342} 342}
343 343
344static void acpi_hibernation_end(void)
345{
346 /*
347 * This is necessary in case acpi_hibernation_finish() is not called
348 * during a failing transition to the sleep state.
349 */
350 acpi_target_sleep_state = ACPI_STATE_S0;
351}
352
344static int acpi_hibernation_pre_restore(void) 353static int acpi_hibernation_pre_restore(void)
345{ 354{
346 acpi_status status; 355 acpi_status status;
@@ -356,7 +365,8 @@ static void acpi_hibernation_restore_cleanup(void)
356} 365}
357 366
358static struct platform_hibernation_ops acpi_hibernation_ops = { 367static struct platform_hibernation_ops acpi_hibernation_ops = {
359 .start = acpi_hibernation_start, 368 .begin = acpi_hibernation_begin,
369 .end = acpi_hibernation_end,
360 .pre_snapshot = acpi_hibernation_prepare, 370 .pre_snapshot = acpi_hibernation_prepare,
361 .finish = acpi_hibernation_finish, 371 .finish = acpi_hibernation_finish,
362 .prepare = acpi_hibernation_prepare, 372 .prepare = acpi_hibernation_prepare,
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index a0b1dbb5919f..646ce2d068d4 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -136,14 +136,17 @@ extern void mark_free_pages(struct zone *zone);
136/** 136/**
137 * struct platform_hibernation_ops - hibernation platform support 137 * struct platform_hibernation_ops - hibernation platform support
138 * 138 *
139 * The methods in this structure allow a platform to override the default 139 * The methods in this structure allow a platform to carry out special
140 * mechanism of shutting down the machine during a hibernation transition. 140 * operations required by it during a hibernation transition.
141 * 141 *
142 * All three methods must be assigned. 142 * All the methods below must be implemented.
143 * 143 *
144 * @start: Tell the platform driver that we're starting hibernation. 144 * @begin: Tell the platform driver that we're starting hibernation.
145 * Called right after shrinking memory and before freezing devices. 145 * Called right after shrinking memory and before freezing devices.
146 * 146 *
147 * @end: Called by the PM core right after resuming devices, to indicate to
148 * the platform that the system has returned to the working state.
149 *
147 * @pre_snapshot: Prepare the platform for creating the hibernation image. 150 * @pre_snapshot: Prepare the platform for creating the hibernation image.
148 * Called right after devices have been frozen and before the nonboot 151 * Called right after devices have been frozen and before the nonboot
149 * CPUs are disabled (runs with IRQs on). 152 * CPUs are disabled (runs with IRQs on).
@@ -178,7 +181,8 @@ extern void mark_free_pages(struct zone *zone);
178 * thawing devices (runs with IRQs on). 181 * thawing devices (runs with IRQs on).
179 */ 182 */
180struct platform_hibernation_ops { 183struct platform_hibernation_ops {
181 int (*start)(void); 184 int (*begin)(void);
185 void (*end)(void);
182 int (*pre_snapshot)(void); 186 int (*pre_snapshot)(void);
183 void (*finish)(void); 187 void (*finish)(void);
184 int (*prepare)(void); 188 int (*prepare)(void);
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 64e42ab8b57c..53c22d9cf577 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -54,8 +54,8 @@ static struct platform_hibernation_ops *hibernation_ops;
54 54
55void hibernation_set_ops(struct platform_hibernation_ops *ops) 55void hibernation_set_ops(struct platform_hibernation_ops *ops)
56{ 56{
57 if (ops && !(ops->start && ops->pre_snapshot && ops->finish 57 if (ops && !(ops->begin && ops->end && ops->pre_snapshot
58 && ops->prepare && ops->enter && ops->pre_restore 58 && ops->prepare && ops->finish && ops->enter && ops->pre_restore
59 && ops->restore_cleanup)) { 59 && ops->restore_cleanup)) {
60 WARN_ON(1); 60 WARN_ON(1);
61 return; 61 return;
@@ -100,14 +100,25 @@ static int hibernation_test(int level) { return 0; }
100#endif /* !CONFIG_PM_DEBUG */ 100#endif /* !CONFIG_PM_DEBUG */
101 101
102/** 102/**
103 * platform_start - tell the platform driver that we're starting 103 * platform_begin - tell the platform driver that we're starting
104 * hibernation 104 * hibernation
105 */ 105 */
106 106
107static int platform_start(int platform_mode) 107static int platform_begin(int platform_mode)
108{ 108{
109 return (platform_mode && hibernation_ops) ? 109 return (platform_mode && hibernation_ops) ?
110 hibernation_ops->start() : 0; 110 hibernation_ops->begin() : 0;
111}
112
113/**
114 * platform_end - tell the platform driver that we've entered the
115 * working state
116 */
117
118static void platform_end(int platform_mode)
119{
120 if (platform_mode && hibernation_ops)
121 hibernation_ops->end();
111} 122}
112 123
113/** 124/**
@@ -237,9 +248,9 @@ int hibernation_snapshot(int platform_mode)
237 if (error) 248 if (error)
238 return error; 249 return error;
239 250
240 error = platform_start(platform_mode); 251 error = platform_begin(platform_mode);
241 if (error) 252 if (error)
242 return error; 253 goto Close;
243 254
244 suspend_console(); 255 suspend_console();
245 error = device_suspend(PMSG_FREEZE); 256 error = device_suspend(PMSG_FREEZE);
@@ -272,6 +283,8 @@ int hibernation_snapshot(int platform_mode)
272 device_resume(); 283 device_resume();
273 Resume_console: 284 Resume_console:
274 resume_console(); 285 resume_console();
286 Close:
287 platform_end(platform_mode);
275 return error; 288 return error;
276} 289}
277 290
@@ -373,9 +386,9 @@ int hibernation_platform_enter(void)
373 * hibernation_ops->finish() before saving the image, so we should let 386 * hibernation_ops->finish() before saving the image, so we should let
374 * the firmware know that we're going to enter the sleep state after all 387 * the firmware know that we're going to enter the sleep state after all
375 */ 388 */
376 error = hibernation_ops->start(); 389 error = hibernation_ops->begin();
377 if (error) 390 if (error)
378 return error; 391 goto Close;
379 392
380 suspend_console(); 393 suspend_console();
381 error = device_suspend(PMSG_SUSPEND); 394 error = device_suspend(PMSG_SUSPEND);
@@ -409,6 +422,8 @@ int hibernation_platform_enter(void)
409 device_resume(); 422 device_resume();
410 Resume_console: 423 Resume_console:
411 resume_console(); 424 resume_console();
425 Close:
426 hibernation_ops->end();
412 return error; 427 return error;
413} 428}
414 429