diff options
Diffstat (limited to 'kernel/power/hibernate.c')
| -rw-r--r-- | kernel/power/hibernate.c | 955 |
1 files changed, 955 insertions, 0 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c new file mode 100644 index 000000000000..81d2e7464893 --- /dev/null +++ b/kernel/power/hibernate.c | |||
| @@ -0,0 +1,955 @@ | |||
| 1 | /* | ||
| 2 | * kernel/power/hibernate.c - Hibernation (a.k.a suspend-to-disk) support. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003 Patrick Mochel | ||
| 5 | * Copyright (c) 2003 Open Source Development Lab | ||
| 6 | * Copyright (c) 2004 Pavel Machek <pavel@suse.cz> | ||
| 7 | * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc. | ||
| 8 | * | ||
| 9 | * This file is released under the GPLv2. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/suspend.h> | ||
| 13 | #include <linux/syscalls.h> | ||
| 14 | #include <linux/reboot.h> | ||
| 15 | #include <linux/string.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/kmod.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/mount.h> | ||
| 21 | #include <linux/pm.h> | ||
| 22 | #include <linux/console.h> | ||
| 23 | #include <linux/cpu.h> | ||
| 24 | #include <linux/freezer.h> | ||
| 25 | #include <scsi/scsi_scan.h> | ||
| 26 | #include <asm/suspend.h> | ||
| 27 | |||
| 28 | #include "power.h" | ||
| 29 | |||
| 30 | |||
| 31 | static int noresume = 0; | ||
| 32 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; | ||
| 33 | dev_t swsusp_resume_device; | ||
| 34 | sector_t swsusp_resume_block; | ||
| 35 | |||
| 36 | enum { | ||
| 37 | HIBERNATION_INVALID, | ||
| 38 | HIBERNATION_PLATFORM, | ||
| 39 | HIBERNATION_TEST, | ||
| 40 | HIBERNATION_TESTPROC, | ||
| 41 | HIBERNATION_SHUTDOWN, | ||
| 42 | HIBERNATION_REBOOT, | ||
| 43 | /* keep last */ | ||
| 44 | __HIBERNATION_AFTER_LAST | ||
| 45 | }; | ||
| 46 | #define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1) | ||
| 47 | #define HIBERNATION_FIRST (HIBERNATION_INVALID + 1) | ||
| 48 | |||
| 49 | static int hibernation_mode = HIBERNATION_SHUTDOWN; | ||
| 50 | |||
| 51 | static struct platform_hibernation_ops *hibernation_ops; | ||
| 52 | |||
| 53 | /** | ||
| 54 | * hibernation_set_ops - set the global hibernate operations | ||
| 55 | * @ops: the hibernation operations to use in subsequent hibernation transitions | ||
| 56 | */ | ||
| 57 | |||
| 58 | void hibernation_set_ops(struct platform_hibernation_ops *ops) | ||
| 59 | { | ||
| 60 | if (ops && !(ops->begin && ops->end && ops->pre_snapshot | ||
| 61 | && ops->prepare && ops->finish && ops->enter && ops->pre_restore | ||
| 62 | && ops->restore_cleanup)) { | ||
| 63 | WARN_ON(1); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | mutex_lock(&pm_mutex); | ||
| 67 | hibernation_ops = ops; | ||
| 68 | if (ops) | ||
| 69 | hibernation_mode = HIBERNATION_PLATFORM; | ||
| 70 | else if (hibernation_mode == HIBERNATION_PLATFORM) | ||
| 71 | hibernation_mode = HIBERNATION_SHUTDOWN; | ||
| 72 | |||
| 73 | mutex_unlock(&pm_mutex); | ||
| 74 | } | ||
| 75 | |||
| 76 | static bool entering_platform_hibernation; | ||
| 77 | |||
| 78 | bool system_entering_hibernation(void) | ||
| 79 | { | ||
| 80 | return entering_platform_hibernation; | ||
| 81 | } | ||
| 82 | EXPORT_SYMBOL(system_entering_hibernation); | ||
| 83 | |||
| 84 | #ifdef CONFIG_PM_DEBUG | ||
| 85 | static void hibernation_debug_sleep(void) | ||
| 86 | { | ||
| 87 | printk(KERN_INFO "hibernation debug: Waiting for 5 seconds.\n"); | ||
| 88 | mdelay(5000); | ||
| 89 | } | ||
| 90 | |||
| 91 | static int hibernation_testmode(int mode) | ||
| 92 | { | ||
| 93 | if (hibernation_mode == mode) { | ||
| 94 | hibernation_debug_sleep(); | ||
| 95 | return 1; | ||
| 96 | } | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int hibernation_test(int level) | ||
| 101 | { | ||
| 102 | if (pm_test_level == level) { | ||
| 103 | hibernation_debug_sleep(); | ||
| 104 | return 1; | ||
| 105 | } | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | #else /* !CONFIG_PM_DEBUG */ | ||
| 109 | static int hibernation_testmode(int mode) { return 0; } | ||
| 110 | static int hibernation_test(int level) { return 0; } | ||
| 111 | #endif /* !CONFIG_PM_DEBUG */ | ||
| 112 | |||
| 113 | /** | ||
| 114 | * platform_begin - tell the platform driver that we're starting | ||
| 115 | * hibernation | ||
| 116 | */ | ||
| 117 | |||
| 118 | static int platform_begin(int platform_mode) | ||
| 119 | { | ||
| 120 | return (platform_mode && hibernation_ops) ? | ||
| 121 | hibernation_ops->begin() : 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * platform_end - tell the platform driver that we've entered the | ||
| 126 | * working state | ||
| 127 | */ | ||
| 128 | |||
| 129 | static void platform_end(int platform_mode) | ||
| 130 | { | ||
| 131 | if (platform_mode && hibernation_ops) | ||
| 132 | hibernation_ops->end(); | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * platform_pre_snapshot - prepare the machine for hibernation using the | ||
| 137 | * platform driver if so configured and return an error code if it fails | ||
| 138 | */ | ||
| 139 | |||
| 140 | static int platform_pre_snapshot(int platform_mode) | ||
| 141 | { | ||
| 142 | return (platform_mode && hibernation_ops) ? | ||
| 143 | hibernation_ops->pre_snapshot() : 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * platform_leave - prepare the machine for switching to the normal mode | ||
| 148 | * of operation using the platform driver (called with interrupts disabled) | ||
| 149 | */ | ||
| 150 | |||
| 151 | static void platform_leave(int platform_mode) | ||
| 152 | { | ||
| 153 | if (platform_mode && hibernation_ops) | ||
| 154 | hibernation_ops->leave(); | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * platform_finish - switch the machine to the normal mode of operation | ||
| 159 | * using the platform driver (must be called after platform_prepare()) | ||
| 160 | */ | ||
| 161 | |||
| 162 | static void platform_finish(int platform_mode) | ||
| 163 | { | ||
| 164 | if (platform_mode && hibernation_ops) | ||
| 165 | hibernation_ops->finish(); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * platform_pre_restore - prepare the platform for the restoration from a | ||
| 170 | * hibernation image. If the restore fails after this function has been | ||
| 171 | * called, platform_restore_cleanup() must be called. | ||
| 172 | */ | ||
| 173 | |||
| 174 | static int platform_pre_restore(int platform_mode) | ||
| 175 | { | ||
| 176 | return (platform_mode && hibernation_ops) ? | ||
| 177 | hibernation_ops->pre_restore() : 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | /** | ||
| 181 | * platform_restore_cleanup - switch the platform to the normal mode of | ||
| 182 | * operation after a failing restore. If platform_pre_restore() has been | ||
| 183 | * called before the failing restore, this function must be called too, | ||
| 184 | * regardless of the result of platform_pre_restore(). | ||
| 185 | */ | ||
| 186 | |||
| 187 | static void platform_restore_cleanup(int platform_mode) | ||
| 188 | { | ||
| 189 | if (platform_mode && hibernation_ops) | ||
| 190 | hibernation_ops->restore_cleanup(); | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * platform_recover - recover the platform from a failure to suspend | ||
| 195 | * devices. | ||
| 196 | */ | ||
| 197 | |||
| 198 | static void platform_recover(int platform_mode) | ||
| 199 | { | ||
| 200 | if (platform_mode && hibernation_ops && hibernation_ops->recover) | ||
| 201 | hibernation_ops->recover(); | ||
| 202 | } | ||
| 203 | |||
| 204 | /** | ||
| 205 | * create_image - freeze devices that need to be frozen with interrupts | ||
| 206 | * off, create the hibernation image and thaw those devices. Control | ||
| 207 | * reappears in this routine after a restore. | ||
| 208 | */ | ||
| 209 | |||
| 210 | static int create_image(int platform_mode) | ||
| 211 | { | ||
| 212 | int error; | ||
| 213 | |||
| 214 | error = arch_prepare_suspend(); | ||
| 215 | if (error) | ||
| 216 | return error; | ||
| 217 | |||
| 218 | /* At this point, dpm_suspend_start() has been called, but *not* | ||
| 219 | * dpm_suspend_noirq(). We *must* call dpm_suspend_noirq() now. | ||
| 220 | * Otherwise, drivers for some devices (e.g. interrupt controllers) | ||
| 221 | * become desynchronized with the actual state of the hardware | ||
| 222 | * at resume time, and evil weirdness ensues. | ||
| 223 | */ | ||
| 224 | error = dpm_suspend_noirq(PMSG_FREEZE); | ||
| 225 | if (error) { | ||
| 226 | printk(KERN_ERR "PM: Some devices failed to power down, " | ||
| 227 | "aborting hibernation\n"); | ||
| 228 | return error; | ||
| 229 | } | ||
| 230 | |||
| 231 | error = platform_pre_snapshot(platform_mode); | ||
| 232 | if (error || hibernation_test(TEST_PLATFORM)) | ||
| 233 | goto Platform_finish; | ||
| 234 | |||
| 235 | error = disable_nonboot_cpus(); | ||
| 236 | if (error || hibernation_test(TEST_CPUS) | ||
| 237 | || hibernation_testmode(HIBERNATION_TEST)) | ||
| 238 | goto Enable_cpus; | ||
| 239 | |||
| 240 | local_irq_disable(); | ||
| 241 | |||
| 242 | error = sysdev_suspend(PMSG_FREEZE); | ||
| 243 | if (error) { | ||
| 244 | printk(KERN_ERR "PM: Some system devices failed to power down, " | ||
| 245 | "aborting hibernation\n"); | ||
| 246 | goto Enable_irqs; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (hibernation_test(TEST_CORE)) | ||
| 250 | goto Power_up; | ||
| 251 | |||
| 252 | in_suspend = 1; | ||
| 253 | save_processor_state(); | ||
| 254 | error = swsusp_arch_suspend(); | ||
| 255 | if (error) | ||
| 256 | printk(KERN_ERR "PM: Error %d creating hibernation image\n", | ||
| 257 | error); | ||
| 258 | /* Restore control flow magically appears here */ | ||
| 259 | restore_processor_state(); | ||
| 260 | if (!in_suspend) | ||
| 261 | platform_leave(platform_mode); | ||
| 262 | |||
| 263 | Power_up: | ||
| 264 | sysdev_resume(); | ||
| 265 | /* NOTE: dpm_resume_noirq() is just a resume() for devices | ||
| 266 | * that suspended with irqs off ... no overall powerup. | ||
| 267 | */ | ||
| 268 | |||
| 269 | Enable_irqs: | ||
| 270 | local_irq_enable(); | ||
| 271 | |||
| 272 | Enable_cpus: | ||
| 273 | enable_nonboot_cpus(); | ||
| 274 | |||
| 275 | Platform_finish: | ||
| 276 | platform_finish(platform_mode); | ||
| 277 | |||
| 278 | dpm_resume_noirq(in_suspend ? | ||
| 279 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | ||
| 280 | |||
| 281 | return error; | ||
| 282 | } | ||
| 283 | |||
| 284 | /** | ||
| 285 | * hibernation_snapshot - quiesce devices and create the hibernation | ||
| 286 | * snapshot image. | ||
| 287 | * @platform_mode - if set, use the platform driver, if available, to | ||
| 288 | * prepare the platform firmware for the power transition. | ||
| 289 | * | ||
| 290 | * Must be called with pm_mutex held | ||
| 291 | */ | ||
| 292 | |||
| 293 | int hibernation_snapshot(int platform_mode) | ||
| 294 | { | ||
| 295 | int error; | ||
| 296 | |||
| 297 | error = platform_begin(platform_mode); | ||
| 298 | if (error) | ||
| 299 | return error; | ||
| 300 | |||
| 301 | /* Free memory before shutting down devices. */ | ||
| 302 | error = swsusp_shrink_memory(); | ||
| 303 | if (error) | ||
| 304 | goto Close; | ||
| 305 | |||
| 306 | suspend_console(); | ||
| 307 | error = dpm_suspend_start(PMSG_FREEZE); | ||
| 308 | if (error) | ||
| 309 | goto Recover_platform; | ||
| 310 | |||
| 311 | if (hibernation_test(TEST_DEVICES)) | ||
| 312 | goto Recover_platform; | ||
| 313 | |||
| 314 | error = create_image(platform_mode); | ||
| 315 | /* Control returns here after successful restore */ | ||
| 316 | |||
| 317 | Resume_devices: | ||
| 318 | dpm_resume_end(in_suspend ? | ||
| 319 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | ||
| 320 | resume_console(); | ||
| 321 | Close: | ||
| 322 | platform_end(platform_mode); | ||
| 323 | return error; | ||
| 324 | |||
| 325 | Recover_platform: | ||
| 326 | platform_recover(platform_mode); | ||
| 327 | goto Resume_devices; | ||
| 328 | } | ||
| 329 | |||
| 330 | /** | ||
| 331 | * resume_target_kernel - prepare devices that need to be suspended with | ||
| 332 | * interrupts off, restore the contents of highmem that have not been | ||
| 333 | * restored yet from the image and run the low level code that will restore | ||
| 334 | * the remaining contents of memory and switch to the just restored target | ||
| 335 | * kernel. | ||
| 336 | */ | ||
| 337 | |||
| 338 | static int resume_target_kernel(bool platform_mode) | ||
| 339 | { | ||
| 340 | int error; | ||
| 341 | |||
| 342 | error = dpm_suspend_noirq(PMSG_QUIESCE); | ||
| 343 | if (error) { | ||
| 344 | printk(KERN_ERR "PM: Some devices failed to power down, " | ||
| 345 | "aborting resume\n"); | ||
| 346 | return error; | ||
| 347 | } | ||
| 348 | |||
| 349 | error = platform_pre_restore(platform_mode); | ||
| 350 | if (error) | ||
| 351 | goto Cleanup; | ||
| 352 | |||
| 353 | error = disable_nonboot_cpus(); | ||
| 354 | if (error) | ||
| 355 | goto Enable_cpus; | ||
| 356 | |||
| 357 | local_irq_disable(); | ||
| 358 | |||
| 359 | error = sysdev_suspend(PMSG_QUIESCE); | ||
| 360 | if (error) | ||
| 361 | goto Enable_irqs; | ||
| 362 | |||
| 363 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | ||
| 364 | save_processor_state(); | ||
| 365 | error = restore_highmem(); | ||
| 366 | if (!error) { | ||
| 367 | error = swsusp_arch_resume(); | ||
| 368 | /* | ||
| 369 | * The code below is only ever reached in case of a failure. | ||
| 370 | * Otherwise execution continues at place where | ||
| 371 | * swsusp_arch_suspend() was called | ||
| 372 | */ | ||
| 373 | BUG_ON(!error); | ||
| 374 | /* This call to restore_highmem() undos the previous one */ | ||
| 375 | restore_highmem(); | ||
| 376 | } | ||
| 377 | /* | ||
| 378 | * The only reason why swsusp_arch_resume() can fail is memory being | ||
| 379 | * very tight, so we have to free it as soon as we can to avoid | ||
| 380 | * subsequent failures | ||
| 381 | */ | ||
| 382 | swsusp_free(); | ||
| 383 | restore_processor_state(); | ||
| 384 | touch_softlockup_watchdog(); | ||
| 385 | |||
| 386 | sysdev_resume(); | ||
| 387 | |||
| 388 | Enable_irqs: | ||
| 389 | local_irq_enable(); | ||
| 390 | |||
| 391 | Enable_cpus: | ||
| 392 | enable_nonboot_cpus(); | ||
| 393 | |||
| 394 | Cleanup: | ||
| 395 | platform_restore_cleanup(platform_mode); | ||
| 396 | |||
| 397 | dpm_resume_noirq(PMSG_RECOVER); | ||
| 398 | |||
| 399 | return error; | ||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * hibernation_restore - quiesce devices and restore the hibernation | ||
| 404 | * snapshot image. If successful, control returns in hibernation_snaphot() | ||
| 405 | * @platform_mode - if set, use the platform driver, if available, to | ||
| 406 | * prepare the platform firmware for the transition. | ||
| 407 | * | ||
| 408 | * Must be called with pm_mutex held | ||
| 409 | */ | ||
| 410 | |||
| 411 | int hibernation_restore(int platform_mode) | ||
| 412 | { | ||
| 413 | int error; | ||
| 414 | |||
| 415 | pm_prepare_console(); | ||
| 416 | suspend_console(); | ||
| 417 | error = dpm_suspend_start(PMSG_QUIESCE); | ||
| 418 | if (!error) { | ||
| 419 | error = resume_target_kernel(platform_mode); | ||
| 420 | dpm_resume_end(PMSG_RECOVER); | ||
| 421 | } | ||
| 422 | resume_console(); | ||
| 423 | pm_restore_console(); | ||
| 424 | return error; | ||
| 425 | } | ||
| 426 | |||
| 427 | /** | ||
| 428 | * hibernation_platform_enter - enter the hibernation state using the | ||
| 429 | * platform driver (if available) | ||
| 430 | */ | ||
| 431 | |||
| 432 | int hibernation_platform_enter(void) | ||
| 433 | { | ||
| 434 | int error; | ||
| 435 | |||
| 436 | if (!hibernation_ops) | ||
| 437 | return -ENOSYS; | ||
| 438 | |||
| 439 | /* | ||
| 440 | * We have cancelled the power transition by running | ||
| 441 | * hibernation_ops->finish() before saving the image, so we should let | ||
| 442 | * the firmware know that we're going to enter the sleep state after all | ||
| 443 | */ | ||
| 444 | error = hibernation_ops->begin(); | ||
| 445 | if (error) | ||
| 446 | goto Close; | ||
| 447 | |||
| 448 | entering_platform_hibernation = true; | ||
| 449 | suspend_console(); | ||
| 450 | error = dpm_suspend_start(PMSG_HIBERNATE); | ||
| 451 | if (error) { | ||
| 452 | if (hibernation_ops->recover) | ||
| 453 | hibernation_ops->recover(); | ||
| 454 | goto Resume_devices; | ||
| 455 | } | ||
| 456 | |||
| 457 | error = dpm_suspend_noirq(PMSG_HIBERNATE); | ||
| 458 | if (error) | ||
| 459 | goto Resume_devices; | ||
| 460 | |||
| 461 | error = hibernation_ops->prepare(); | ||
| 462 | if (error) | ||
| 463 | goto Platofrm_finish; | ||
| 464 | |||
| 465 | error = disable_nonboot_cpus(); | ||
| 466 | if (error) | ||
| 467 | goto Platofrm_finish; | ||
| 468 | |||
| 469 | local_irq_disable(); | ||
| 470 | sysdev_suspend(PMSG_HIBERNATE); | ||
| 471 | hibernation_ops->enter(); | ||
| 472 | /* We should never get here */ | ||
| 473 | while (1); | ||
| 474 | |||
| 475 | /* | ||
| 476 | * We don't need to reenable the nonboot CPUs or resume consoles, since | ||
| 477 | * the system is going to be halted anyway. | ||
| 478 | */ | ||
| 479 | Platofrm_finish: | ||
| 480 | hibernation_ops->finish(); | ||
| 481 | |||
| 482 | dpm_suspend_noirq(PMSG_RESTORE); | ||
| 483 | |||
| 484 | Resume_devices: | ||
| 485 | entering_platform_hibernation = false; | ||
| 486 | dpm_resume_end(PMSG_RESTORE); | ||
| 487 | resume_console(); | ||
| 488 | |||
| 489 | Close: | ||
| 490 | hibernation_ops->end(); | ||
| 491 | |||
| 492 | return error; | ||
| 493 | } | ||
| 494 | |||
| 495 | /** | ||
| 496 | * power_down - Shut the machine down for hibernation. | ||
| 497 | * | ||
| 498 | * Use the platform driver, if configured so; otherwise try | ||
| 499 | * to power off or reboot. | ||
| 500 | */ | ||
| 501 | |||
| 502 | static void power_down(void) | ||
| 503 | { | ||
| 504 | switch (hibernation_mode) { | ||
| 505 | case HIBERNATION_TEST: | ||
| 506 | case HIBERNATION_TESTPROC: | ||
| 507 | break; | ||
| 508 | case HIBERNATION_REBOOT: | ||
| 509 | kernel_restart(NULL); | ||
| 510 | break; | ||
| 511 | case HIBERNATION_PLATFORM: | ||
| 512 | hibernation_platform_enter(); | ||
| 513 | case HIBERNATION_SHUTDOWN: | ||
| 514 | kernel_power_off(); | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | kernel_halt(); | ||
| 518 | /* | ||
| 519 | * Valid image is on the disk, if we continue we risk serious data | ||
| 520 | * corruption after resume. | ||
| 521 | */ | ||
| 522 | printk(KERN_CRIT "PM: Please power down manually\n"); | ||
| 523 | while(1); | ||
| 524 | } | ||
| 525 | |||
| 526 | static int prepare_processes(void) | ||
| 527 | { | ||
| 528 | int error = 0; | ||
| 529 | |||
| 530 | if (freeze_processes()) { | ||
| 531 | error = -EBUSY; | ||
| 532 | thaw_processes(); | ||
| 533 | } | ||
| 534 | return error; | ||
| 535 | } | ||
| 536 | |||
| 537 | /** | ||
| 538 | * hibernate - The granpappy of the built-in hibernation management | ||
| 539 | */ | ||
| 540 | |||
| 541 | int hibernate(void) | ||
| 542 | { | ||
| 543 | int error; | ||
| 544 | |||
| 545 | mutex_lock(&pm_mutex); | ||
| 546 | /* The snapshot device should not be opened while we're running */ | ||
| 547 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { | ||
| 548 | error = -EBUSY; | ||
| 549 | goto Unlock; | ||
| 550 | } | ||
| 551 | |||
| 552 | pm_prepare_console(); | ||
| 553 | error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); | ||
| 554 | if (error) | ||
| 555 | goto Exit; | ||
| 556 | |||
| 557 | error = usermodehelper_disable(); | ||
| 558 | if (error) | ||
| 559 | goto Exit; | ||
| 560 | |||
| 561 | /* Allocate memory management structures */ | ||
| 562 | error = create_basic_memory_bitmaps(); | ||
| 563 | if (error) | ||
| 564 | goto Exit; | ||
| 565 | |||
| 566 | printk(KERN_INFO "PM: Syncing filesystems ... "); | ||
| 567 | sys_sync(); | ||
| 568 | printk("done.\n"); | ||
| 569 | |||
| 570 | error = prepare_processes(); | ||
| 571 | if (error) | ||
| 572 | goto Finish; | ||
| 573 | |||
| 574 | if (hibernation_test(TEST_FREEZER)) | ||
| 575 | goto Thaw; | ||
| 576 | |||
| 577 | if (hibernation_testmode(HIBERNATION_TESTPROC)) | ||
| 578 | goto Thaw; | ||
| 579 | |||
| 580 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); | ||
| 581 | if (in_suspend && !error) { | ||
| 582 | unsigned int flags = 0; | ||
| 583 | |||
| 584 | if (hibernation_mode == HIBERNATION_PLATFORM) | ||
| 585 | flags |= SF_PLATFORM_MODE; | ||
| 586 | pr_debug("PM: writing image.\n"); | ||
| 587 | error = swsusp_write(flags); | ||
| 588 | swsusp_free(); | ||
| 589 | if (!error) | ||
| 590 | power_down(); | ||
| 591 | } else { | ||
| 592 | pr_debug("PM: Image restored successfully.\n"); | ||
| 593 | swsusp_free(); | ||
| 594 | } | ||
| 595 | Thaw: | ||
| 596 | thaw_processes(); | ||
| 597 | Finish: | ||
| 598 | free_basic_memory_bitmaps(); | ||
| 599 | usermodehelper_enable(); | ||
| 600 | Exit: | ||
| 601 | pm_notifier_call_chain(PM_POST_HIBERNATION); | ||
| 602 | pm_restore_console(); | ||
| 603 | atomic_inc(&snapshot_device_available); | ||
| 604 | Unlock: | ||
| 605 | mutex_unlock(&pm_mutex); | ||
| 606 | return error; | ||
| 607 | } | ||
| 608 | |||
| 609 | |||
| 610 | /** | ||
| 611 | * software_resume - Resume from a saved image. | ||
| 612 | * | ||
| 613 | * Called as a late_initcall (so all devices are discovered and | ||
| 614 | * initialized), we call swsusp to see if we have a saved image or not. | ||
| 615 | * If so, we quiesce devices, the restore the saved image. We will | ||
| 616 | * return above (in hibernate() ) if everything goes well. | ||
| 617 | * Otherwise, we fail gracefully and return to the normally | ||
| 618 | * scheduled program. | ||
| 619 | * | ||
| 620 | */ | ||
| 621 | |||
| 622 | static int software_resume(void) | ||
| 623 | { | ||
| 624 | int error; | ||
| 625 | unsigned int flags; | ||
| 626 | |||
| 627 | /* | ||
| 628 | * If the user said "noresume".. bail out early. | ||
| 629 | */ | ||
| 630 | if (noresume) | ||
| 631 | return 0; | ||
| 632 | |||
| 633 | /* | ||
| 634 | * name_to_dev_t() below takes a sysfs buffer mutex when sysfs | ||
| 635 | * is configured into the kernel. Since the regular hibernate | ||
| 636 | * trigger path is via sysfs which takes a buffer mutex before | ||
| 637 | * calling hibernate functions (which take pm_mutex) this can | ||
| 638 | * cause lockdep to complain about a possible ABBA deadlock | ||
| 639 | * which cannot happen since we're in the boot code here and | ||
| 640 | * sysfs can't be invoked yet. Therefore, we use a subclass | ||
| 641 | * here to avoid lockdep complaining. | ||
| 642 | */ | ||
| 643 | mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); | ||
| 644 | |||
| 645 | if (swsusp_resume_device) | ||
| 646 | goto Check_image; | ||
| 647 | |||
| 648 | if (!strlen(resume_file)) { | ||
| 649 | error = -ENOENT; | ||
| 650 | goto Unlock; | ||
| 651 | } | ||
| 652 | |||
| 653 | pr_debug("PM: Checking image partition %s\n", resume_file); | ||
| 654 | |||
| 655 | /* Check if the device is there */ | ||
| 656 | swsusp_resume_device = name_to_dev_t(resume_file); | ||
| 657 | if (!swsusp_resume_device) { | ||
| 658 | /* | ||
| 659 | * Some device discovery might still be in progress; we need | ||
| 660 | * to wait for this to finish. | ||
| 661 | */ | ||
| 662 | wait_for_device_probe(); | ||
| 663 | /* | ||
| 664 | * We can't depend on SCSI devices being available after loading | ||
| 665 | * one of their modules until scsi_complete_async_scans() is | ||
| 666 | * called and the resume device usually is a SCSI one. | ||
| 667 | */ | ||
| 668 | scsi_complete_async_scans(); | ||
| 669 | |||
| 670 | swsusp_resume_device = name_to_dev_t(resume_file); | ||
| 671 | if (!swsusp_resume_device) { | ||
| 672 | error = -ENODEV; | ||
| 673 | goto Unlock; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | Check_image: | ||
| 678 | pr_debug("PM: Resume from partition %d:%d\n", | ||
| 679 | MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); | ||
| 680 | |||
| 681 | pr_debug("PM: Checking hibernation image.\n"); | ||
| 682 | error = swsusp_check(); | ||
| 683 | if (error) | ||
| 684 | goto Unlock; | ||
| 685 | |||
| 686 | /* The snapshot device should not be opened while we're running */ | ||
| 687 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { | ||
| 688 | error = -EBUSY; | ||
| 689 | goto Unlock; | ||
| 690 | } | ||
| 691 | |||
| 692 | pm_prepare_console(); | ||
| 693 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | ||
| 694 | if (error) | ||
| 695 | goto Finish; | ||
| 696 | |||
| 697 | error = usermodehelper_disable(); | ||
| 698 | if (error) | ||
| 699 | goto Finish; | ||
| 700 | |||
| 701 | error = create_basic_memory_bitmaps(); | ||
| 702 | if (error) | ||
| 703 | goto Finish; | ||
| 704 | |||
| 705 | pr_debug("PM: Preparing processes for restore.\n"); | ||
| 706 | error = prepare_processes(); | ||
| 707 | if (error) { | ||
| 708 | swsusp_close(FMODE_READ); | ||
| 709 | goto Done; | ||
| 710 | } | ||
| 711 | |||
| 712 | pr_debug("PM: Reading hibernation image.\n"); | ||
| 713 | |||
| 714 | error = swsusp_read(&flags); | ||
| 715 | if (!error) | ||
| 716 | hibernation_restore(flags & SF_PLATFORM_MODE); | ||
| 717 | |||
| 718 | printk(KERN_ERR "PM: Restore failed, recovering.\n"); | ||
| 719 | swsusp_free(); | ||
| 720 | thaw_processes(); | ||
| 721 | Done: | ||
| 722 | free_basic_memory_bitmaps(); | ||
| 723 | usermodehelper_enable(); | ||
| 724 | Finish: | ||
| 725 | pm_notifier_call_chain(PM_POST_RESTORE); | ||
| 726 | pm_restore_console(); | ||
| 727 | atomic_inc(&snapshot_device_available); | ||
| 728 | /* For success case, the suspend path will release the lock */ | ||
| 729 | Unlock: | ||
| 730 | mutex_unlock(&pm_mutex); | ||
| 731 | pr_debug("PM: Resume from disk failed.\n"); | ||
| 732 | return error; | ||
| 733 | } | ||
| 734 | |||
| 735 | late_initcall(software_resume); | ||
| 736 | |||
| 737 | |||
| 738 | static const char * const hibernation_modes[] = { | ||
| 739 | [HIBERNATION_PLATFORM] = "platform", | ||
| 740 | [HIBERNATION_SHUTDOWN] = "shutdown", | ||
| 741 | [HIBERNATION_REBOOT] = "reboot", | ||
| 742 | [HIBERNATION_TEST] = "test", | ||
| 743 | [HIBERNATION_TESTPROC] = "testproc", | ||
| 744 | }; | ||
| 745 | |||
| 746 | /** | ||
| 747 | * disk - Control hibernation mode | ||
| 748 | * | ||
| 749 | * Suspend-to-disk can be handled in several ways. We have a few options | ||
| 750 | * for putting the system to sleep - using the platform driver (e.g. ACPI | ||
| 751 | * or other hibernation_ops), powering off the system or rebooting the | ||
| 752 | * system (for testing) as well as the two test modes. | ||
| 753 | * | ||
| 754 | * The system can support 'platform', and that is known a priori (and | ||
| 755 | * encoded by the presence of hibernation_ops). However, the user may | ||
| 756 | * choose 'shutdown' or 'reboot' as alternatives, as well as one fo the | ||
| 757 | * test modes, 'test' or 'testproc'. | ||
| 758 | * | ||
| 759 | * show() will display what the mode is currently set to. | ||
| 760 | * store() will accept one of | ||
| 761 | * | ||
| 762 | * 'platform' | ||
| 763 | * 'shutdown' | ||
| 764 | * 'reboot' | ||
| 765 | * 'test' | ||
| 766 | * 'testproc' | ||
| 767 | * | ||
| 768 | * It will only change to 'platform' if the system | ||
| 769 | * supports it (as determined by having hibernation_ops). | ||
| 770 | */ | ||
| 771 | |||
| 772 | static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 773 | char *buf) | ||
| 774 | { | ||
| 775 | int i; | ||
| 776 | char *start = buf; | ||
| 777 | |||
| 778 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { | ||
| 779 | if (!hibernation_modes[i]) | ||
| 780 | continue; | ||
| 781 | switch (i) { | ||
| 782 | case HIBERNATION_SHUTDOWN: | ||
| 783 | case HIBERNATION_REBOOT: | ||
| 784 | case HIBERNATION_TEST: | ||
| 785 | case HIBERNATION_TESTPROC: | ||
| 786 | break; | ||
| 787 | case HIBERNATION_PLATFORM: | ||
| 788 | if (hibernation_ops) | ||
| 789 | break; | ||
| 790 | /* not a valid mode, continue with loop */ | ||
| 791 | continue; | ||
| 792 | } | ||
| 793 | if (i == hibernation_mode) | ||
| 794 | buf += sprintf(buf, "[%s] ", hibernation_modes[i]); | ||
| 795 | else | ||
| 796 | buf += sprintf(buf, "%s ", hibernation_modes[i]); | ||
| 797 | } | ||
| 798 | buf += sprintf(buf, "\n"); | ||
| 799 | return buf-start; | ||
| 800 | } | ||
| 801 | |||
| 802 | |||
| 803 | static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 804 | const char *buf, size_t n) | ||
| 805 | { | ||
| 806 | int error = 0; | ||
| 807 | int i; | ||
| 808 | int len; | ||
| 809 | char *p; | ||
| 810 | int mode = HIBERNATION_INVALID; | ||
| 811 | |||
| 812 | p = memchr(buf, '\n', n); | ||
| 813 | len = p ? p - buf : n; | ||
| 814 | |||
| 815 | mutex_lock(&pm_mutex); | ||
| 816 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { | ||
| 817 | if (len == strlen(hibernation_modes[i]) | ||
| 818 | && !strncmp(buf, hibernation_modes[i], len)) { | ||
| 819 | mode = i; | ||
| 820 | break; | ||
| 821 | } | ||
| 822 | } | ||
| 823 | if (mode != HIBERNATION_INVALID) { | ||
| 824 | switch (mode) { | ||
| 825 | case HIBERNATION_SHUTDOWN: | ||
| 826 | case HIBERNATION_REBOOT: | ||
| 827 | case HIBERNATION_TEST: | ||
| 828 | case HIBERNATION_TESTPROC: | ||
| 829 | hibernation_mode = mode; | ||
| 830 | break; | ||
| 831 | case HIBERNATION_PLATFORM: | ||
| 832 | if (hibernation_ops) | ||
| 833 | hibernation_mode = mode; | ||
| 834 | else | ||
| 835 | error = -EINVAL; | ||
| 836 | } | ||
| 837 | } else | ||
| 838 | error = -EINVAL; | ||
| 839 | |||
| 840 | if (!error) | ||
| 841 | pr_debug("PM: Hibernation mode set to '%s'\n", | ||
| 842 | hibernation_modes[mode]); | ||
| 843 | mutex_unlock(&pm_mutex); | ||
| 844 | return error ? error : n; | ||
| 845 | } | ||
| 846 | |||
| 847 | power_attr(disk); | ||
| 848 | |||
| 849 | static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 850 | char *buf) | ||
| 851 | { | ||
| 852 | return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), | ||
| 853 | MINOR(swsusp_resume_device)); | ||
| 854 | } | ||
| 855 | |||
| 856 | static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 857 | const char *buf, size_t n) | ||
| 858 | { | ||
| 859 | unsigned int maj, min; | ||
| 860 | dev_t res; | ||
| 861 | int ret = -EINVAL; | ||
| 862 | |||
| 863 | if (sscanf(buf, "%u:%u", &maj, &min) != 2) | ||
| 864 | goto out; | ||
| 865 | |||
| 866 | res = MKDEV(maj,min); | ||
| 867 | if (maj != MAJOR(res) || min != MINOR(res)) | ||
| 868 | goto out; | ||
| 869 | |||
| 870 | mutex_lock(&pm_mutex); | ||
| 871 | swsusp_resume_device = res; | ||
| 872 | mutex_unlock(&pm_mutex); | ||
| 873 | printk(KERN_INFO "PM: Starting manual resume from disk\n"); | ||
| 874 | noresume = 0; | ||
| 875 | software_resume(); | ||
| 876 | ret = n; | ||
| 877 | out: | ||
| 878 | return ret; | ||
| 879 | } | ||
| 880 | |||
| 881 | power_attr(resume); | ||
| 882 | |||
| 883 | static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 884 | char *buf) | ||
| 885 | { | ||
| 886 | return sprintf(buf, "%lu\n", image_size); | ||
| 887 | } | ||
| 888 | |||
| 889 | static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
| 890 | const char *buf, size_t n) | ||
| 891 | { | ||
| 892 | unsigned long size; | ||
| 893 | |||
| 894 | if (sscanf(buf, "%lu", &size) == 1) { | ||
| 895 | image_size = size; | ||
| 896 | return n; | ||
| 897 | } | ||
| 898 | |||
| 899 | return -EINVAL; | ||
| 900 | } | ||
| 901 | |||
| 902 | power_attr(image_size); | ||
| 903 | |||
| 904 | static struct attribute * g[] = { | ||
| 905 | &disk_attr.attr, | ||
| 906 | &resume_attr.attr, | ||
| 907 | &image_size_attr.attr, | ||
| 908 | NULL, | ||
| 909 | }; | ||
| 910 | |||
| 911 | |||
| 912 | static struct attribute_group attr_group = { | ||
| 913 | .attrs = g, | ||
| 914 | }; | ||
| 915 | |||
| 916 | |||
| 917 | static int __init pm_disk_init(void) | ||
| 918 | { | ||
| 919 | return sysfs_create_group(power_kobj, &attr_group); | ||
| 920 | } | ||
| 921 | |||
| 922 | core_initcall(pm_disk_init); | ||
| 923 | |||
| 924 | |||
| 925 | static int __init resume_setup(char *str) | ||
| 926 | { | ||
| 927 | if (noresume) | ||
| 928 | return 1; | ||
| 929 | |||
| 930 | strncpy( resume_file, str, 255 ); | ||
| 931 | return 1; | ||
| 932 | } | ||
| 933 | |||
| 934 | static int __init resume_offset_setup(char *str) | ||
| 935 | { | ||
| 936 | unsigned long long offset; | ||
| 937 | |||
| 938 | if (noresume) | ||
| 939 | return 1; | ||
| 940 | |||
| 941 | if (sscanf(str, "%llu", &offset) == 1) | ||
| 942 | swsusp_resume_block = offset; | ||
| 943 | |||
| 944 | return 1; | ||
| 945 | } | ||
| 946 | |||
| 947 | static int __init noresume_setup(char *str) | ||
| 948 | { | ||
| 949 | noresume = 1; | ||
| 950 | return 1; | ||
| 951 | } | ||
| 952 | |||
| 953 | __setup("noresume", noresume_setup); | ||
| 954 | __setup("resume_offset=", resume_offset_setup); | ||
| 955 | __setup("resume=", resume_setup); | ||
