diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 02e4fb69111a..06331374d862 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -130,15 +130,25 @@ int pm_suspend_disk(void) | |||
130 | { | 130 | { |
131 | int error; | 131 | int error; |
132 | 132 | ||
133 | /* The snapshot device should not be opened while we're running */ | ||
134 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) | ||
135 | return -EBUSY; | ||
136 | |||
137 | /* Allocate memory management structures */ | ||
138 | error = create_basic_memory_bitmaps(); | ||
139 | if (error) | ||
140 | goto Exit; | ||
141 | |||
133 | error = prepare_processes(); | 142 | error = prepare_processes(); |
134 | if (error) | 143 | if (error) |
135 | return error; | 144 | goto Finish; |
136 | 145 | ||
137 | if (pm_disk_mode == PM_DISK_TESTPROC) { | 146 | if (pm_disk_mode == PM_DISK_TESTPROC) { |
138 | printk("swsusp debug: Waiting for 5 seconds.\n"); | 147 | printk("swsusp debug: Waiting for 5 seconds.\n"); |
139 | mdelay(5000); | 148 | mdelay(5000); |
140 | goto Thaw; | 149 | goto Thaw; |
141 | } | 150 | } |
151 | |||
142 | /* Free memory before shutting down devices. */ | 152 | /* Free memory before shutting down devices. */ |
143 | error = swsusp_shrink_memory(); | 153 | error = swsusp_shrink_memory(); |
144 | if (error) | 154 | if (error) |
@@ -196,6 +206,10 @@ int pm_suspend_disk(void) | |||
196 | resume_console(); | 206 | resume_console(); |
197 | Thaw: | 207 | Thaw: |
198 | unprepare_processes(); | 208 | unprepare_processes(); |
209 | Finish: | ||
210 | free_basic_memory_bitmaps(); | ||
211 | Exit: | ||
212 | atomic_inc(&snapshot_device_available); | ||
199 | return error; | 213 | return error; |
200 | } | 214 | } |
201 | 215 | ||
@@ -239,13 +253,21 @@ static int software_resume(void) | |||
239 | } | 253 | } |
240 | 254 | ||
241 | pr_debug("PM: Checking swsusp image.\n"); | 255 | pr_debug("PM: Checking swsusp image.\n"); |
242 | |||
243 | error = swsusp_check(); | 256 | error = swsusp_check(); |
244 | if (error) | 257 | if (error) |
245 | goto Done; | 258 | goto Unlock; |
246 | 259 | ||
247 | pr_debug("PM: Preparing processes for restore.\n"); | 260 | /* The snapshot device should not be opened while we're running */ |
261 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { | ||
262 | error = -EBUSY; | ||
263 | goto Unlock; | ||
264 | } | ||
248 | 265 | ||
266 | error = create_basic_memory_bitmaps(); | ||
267 | if (error) | ||
268 | goto Finish; | ||
269 | |||
270 | pr_debug("PM: Preparing processes for restore.\n"); | ||
249 | error = prepare_processes(); | 271 | error = prepare_processes(); |
250 | if (error) { | 272 | if (error) { |
251 | swsusp_close(); | 273 | swsusp_close(); |
@@ -280,7 +302,11 @@ static int software_resume(void) | |||
280 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); | 302 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); |
281 | unprepare_processes(); | 303 | unprepare_processes(); |
282 | Done: | 304 | Done: |
305 | free_basic_memory_bitmaps(); | ||
306 | Finish: | ||
307 | atomic_inc(&snapshot_device_available); | ||
283 | /* For success case, the suspend path will release the lock */ | 308 | /* For success case, the suspend path will release the lock */ |
309 | Unlock: | ||
284 | mutex_unlock(&pm_mutex); | 310 | mutex_unlock(&pm_mutex); |
285 | pr_debug("PM: Resume from disk failed.\n"); | 311 | pr_debug("PM: Resume from disk failed.\n"); |
286 | return 0; | 312 | return 0; |
@@ -322,13 +348,40 @@ static const char * const pm_disk_modes[] = { | |||
322 | * supports it (as determined from pm_ops->pm_disk_mode). | 348 | * supports it (as determined from pm_ops->pm_disk_mode). |
323 | */ | 349 | */ |
324 | 350 | ||
325 | static ssize_t disk_show(struct subsystem * subsys, char * buf) | 351 | static ssize_t disk_show(struct kset *kset, char *buf) |
326 | { | 352 | { |
327 | return sprintf(buf, "%s\n", pm_disk_modes[pm_disk_mode]); | 353 | int i; |
354 | char *start = buf; | ||
355 | |||
356 | for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) { | ||
357 | if (!pm_disk_modes[i]) | ||
358 | continue; | ||
359 | switch (i) { | ||
360 | case PM_DISK_SHUTDOWN: | ||
361 | case PM_DISK_REBOOT: | ||
362 | case PM_DISK_TEST: | ||
363 | case PM_DISK_TESTPROC: | ||
364 | break; | ||
365 | default: | ||
366 | if (pm_ops && pm_ops->enter && | ||
367 | (i == pm_ops->pm_disk_mode)) | ||
368 | break; | ||
369 | /* not a valid mode, continue with loop */ | ||
370 | continue; | ||
371 | } | ||
372 | if (i == pm_disk_mode) | ||
373 | buf += sprintf(buf, "[%s]", pm_disk_modes[i]); | ||
374 | else | ||
375 | buf += sprintf(buf, "%s", pm_disk_modes[i]); | ||
376 | if (i+1 != PM_DISK_MAX) | ||
377 | buf += sprintf(buf, " "); | ||
378 | } | ||
379 | buf += sprintf(buf, "\n"); | ||
380 | return buf-start; | ||
328 | } | 381 | } |
329 | 382 | ||
330 | 383 | ||
331 | static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) | 384 | static ssize_t disk_store(struct kset *kset, const char *buf, size_t n) |
332 | { | 385 | { |
333 | int error = 0; | 386 | int error = 0; |
334 | int i; | 387 | int i; |
@@ -373,13 +426,13 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n) | |||
373 | 426 | ||
374 | power_attr(disk); | 427 | power_attr(disk); |
375 | 428 | ||
376 | static ssize_t resume_show(struct subsystem * subsys, char *buf) | 429 | static ssize_t resume_show(struct kset *kset, char *buf) |
377 | { | 430 | { |
378 | return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), | 431 | return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), |
379 | MINOR(swsusp_resume_device)); | 432 | MINOR(swsusp_resume_device)); |
380 | } | 433 | } |
381 | 434 | ||
382 | static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n) | 435 | static ssize_t resume_store(struct kset *kset, const char *buf, size_t n) |
383 | { | 436 | { |
384 | unsigned int maj, min; | 437 | unsigned int maj, min; |
385 | dev_t res; | 438 | dev_t res; |
@@ -405,12 +458,12 @@ static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n) | |||
405 | 458 | ||
406 | power_attr(resume); | 459 | power_attr(resume); |
407 | 460 | ||
408 | static ssize_t image_size_show(struct subsystem * subsys, char *buf) | 461 | static ssize_t image_size_show(struct kset *kset, char *buf) |
409 | { | 462 | { |
410 | return sprintf(buf, "%lu\n", image_size); | 463 | return sprintf(buf, "%lu\n", image_size); |
411 | } | 464 | } |
412 | 465 | ||
413 | static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n) | 466 | static ssize_t image_size_store(struct kset *kset, const char *buf, size_t n) |
414 | { | 467 | { |
415 | unsigned long size; | 468 | unsigned long size; |
416 | 469 | ||
@@ -439,7 +492,7 @@ static struct attribute_group attr_group = { | |||
439 | 492 | ||
440 | static int __init pm_disk_init(void) | 493 | static int __init pm_disk_init(void) |
441 | { | 494 | { |
442 | return sysfs_create_group(&power_subsys.kset.kobj,&attr_group); | 495 | return sysfs_create_group(&power_subsys.kobj, &attr_group); |
443 | } | 496 | } |
444 | 497 | ||
445 | core_initcall(pm_disk_init); | 498 | core_initcall(pm_disk_init); |