diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 47882bfa610e..fa3b43b7206d 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -54,7 +54,8 @@ 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->prepare && ops->enter && ops->finish |
58 | && ops->pre_restore && ops->restore_cleanup)) { | ||
58 | WARN_ON(1); | 59 | WARN_ON(1); |
59 | return; | 60 | return; |
60 | } | 61 | } |
@@ -92,6 +93,31 @@ static void platform_finish(int platform_mode) | |||
92 | } | 93 | } |
93 | 94 | ||
94 | /** | 95 | /** |
96 | * platform_pre_restore - prepare the platform for the restoration from a | ||
97 | * hibernation image. If the restore fails after this function has been | ||
98 | * called, platform_restore_cleanup() must be called. | ||
99 | */ | ||
100 | |||
101 | static int platform_pre_restore(int platform_mode) | ||
102 | { | ||
103 | return (platform_mode && hibernation_ops) ? | ||
104 | hibernation_ops->pre_restore() : 0; | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * platform_restore_cleanup - switch the platform to the normal mode of | ||
109 | * operation after a failing restore. If platform_pre_restore() has been | ||
110 | * called before the failing restore, this function must be called too, | ||
111 | * regardless of the result of platform_pre_restore(). | ||
112 | */ | ||
113 | |||
114 | static void platform_restore_cleanup(int platform_mode) | ||
115 | { | ||
116 | if (platform_mode && hibernation_ops) | ||
117 | hibernation_ops->restore_cleanup(); | ||
118 | } | ||
119 | |||
120 | /** | ||
95 | * hibernation_snapshot - quiesce devices and create the hibernation | 121 | * hibernation_snapshot - quiesce devices and create the hibernation |
96 | * snapshot image. | 122 | * snapshot image. |
97 | * @platform_mode - if set, use the platform driver, if available, to | 123 | * @platform_mode - if set, use the platform driver, if available, to |
@@ -141,11 +167,13 @@ int hibernation_snapshot(int platform_mode) | |||
141 | /** | 167 | /** |
142 | * hibernation_restore - quiesce devices and restore the hibernation | 168 | * hibernation_restore - quiesce devices and restore the hibernation |
143 | * snapshot image. If successful, control returns in hibernation_snaphot() | 169 | * snapshot image. If successful, control returns in hibernation_snaphot() |
170 | * @platform_mode - if set, use the platform driver, if available, to | ||
171 | * prepare the platform frimware for the transition. | ||
144 | * | 172 | * |
145 | * Must be called with pm_mutex held | 173 | * Must be called with pm_mutex held |
146 | */ | 174 | */ |
147 | 175 | ||
148 | int hibernation_restore(void) | 176 | int hibernation_restore(int platform_mode) |
149 | { | 177 | { |
150 | int error; | 178 | int error; |
151 | 179 | ||
@@ -155,11 +183,14 @@ int hibernation_restore(void) | |||
155 | if (error) | 183 | if (error) |
156 | goto Finish; | 184 | goto Finish; |
157 | 185 | ||
158 | error = disable_nonboot_cpus(); | 186 | error = platform_pre_restore(platform_mode); |
159 | if (!error) | 187 | if (!error) { |
160 | error = swsusp_resume(); | 188 | error = disable_nonboot_cpus(); |
161 | 189 | if (!error) | |
162 | enable_nonboot_cpus(); | 190 | error = swsusp_resume(); |
191 | enable_nonboot_cpus(); | ||
192 | } | ||
193 | platform_restore_cleanup(platform_mode); | ||
163 | Finish: | 194 | Finish: |
164 | device_resume(); | 195 | device_resume(); |
165 | resume_console(); | 196 | resume_console(); |
@@ -260,8 +291,12 @@ int hibernate(void) | |||
260 | } | 291 | } |
261 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | 292 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); |
262 | if (in_suspend && !error) { | 293 | if (in_suspend && !error) { |
294 | unsigned int flags = 0; | ||
295 | |||
296 | if (hibernation_mode == HIBERNATION_PLATFORM) | ||
297 | flags |= SF_PLATFORM_MODE; | ||
263 | pr_debug("PM: writing image.\n"); | 298 | pr_debug("PM: writing image.\n"); |
264 | error = swsusp_write(); | 299 | error = swsusp_write(flags); |
265 | swsusp_free(); | 300 | swsusp_free(); |
266 | if (!error) | 301 | if (!error) |
267 | power_down(); | 302 | power_down(); |
@@ -295,6 +330,7 @@ int hibernate(void) | |||
295 | static int software_resume(void) | 330 | static int software_resume(void) |
296 | { | 331 | { |
297 | int error; | 332 | int error; |
333 | unsigned int flags; | ||
298 | 334 | ||
299 | mutex_lock(&pm_mutex); | 335 | mutex_lock(&pm_mutex); |
300 | if (!swsusp_resume_device) { | 336 | if (!swsusp_resume_device) { |
@@ -342,9 +378,9 @@ static int software_resume(void) | |||
342 | 378 | ||
343 | pr_debug("PM: Reading swsusp image.\n"); | 379 | pr_debug("PM: Reading swsusp image.\n"); |
344 | 380 | ||
345 | error = swsusp_read(); | 381 | error = swsusp_read(&flags); |
346 | if (!error) | 382 | if (!error) |
347 | hibernation_restore(); | 383 | hibernation_restore(flags & SF_PLATFORM_MODE); |
348 | 384 | ||
349 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); | 385 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); |
350 | swsusp_free(); | 386 | swsusp_free(); |