| 1 | |
| 2 | |
| 3 | * kernel/power/hibernate.c - Hibernation (a.k.a suspend-to-disk) support.
|
| 4 | *
|
| 5 | * Copyright (c) 2003 Patrick Mochel
|
| 6 | * Copyright (c) 2003 Open Source Development Lab
|
| 7 | * Copyright (c) 2004 Pavel Machek <[email protected]>
|
| 8 | * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
|
| 9 | * Copyright (C) 2012 Bojan Smojver <[email protected]>
|
| 10 |
|
| 11 |
|
| 12 | #define pr_fmt(fmt) "PM: hibernation: " fmt
|
| 13 |
|
| 14 | #include <crypto/acompress.h>
|
| 15 | #include <linux/blkdev.h>
|
| 16 | #include <linux/export.h>
|
| 17 | #include <linux/suspend.h>
|
| 18 | #include <linux/reboot.h>
|
| 19 | #include <linux/string.h>
|
| 20 | #include <linux/device.h>
|
| 21 | #include <linux/async.h>
|
| 22 | #include <linux/delay.h>
|
| 23 | #include <linux/fs.h>
|
| 24 | #include <linux/mount.h>
|
| 25 | #include <linux/pm.h>
|
| 26 | #include <linux/nmi.h>
|
| 27 | #include <linux/console.h>
|
| 28 | #include <linux/cpu.h>
|
| 29 | #include <linux/freezer.h>
|
| 30 | #include <linux/gfp.h>
|
| 31 | #include <linux/syscore_ops.h>
|
| 32 | #include <linux/ctype.h>
|
| 33 | #include <linux/ktime.h>
|
| 34 | #include <linux/security.h>
|
| 35 | #include <linux/secretmem.h>
|
| 36 | #include <trace/events/power.h>
|
| 37 |
|
| 38 | #include "power.h"
|
| 39 |
|
| 40 |
|
| 41 | static int nocompress;
|
| 42 | static int noresume;
|
| 43 | static int nohibernate;
|
| 44 | static int resume_wait;
|
| 45 | static unsigned int resume_delay;
|
| 46 | static char resume_file[256] = CONFIG_PM_STD_PARTITION;
|
| 47 | dev_t swsusp_resume_device;
|
| 48 | sector_t swsusp_resume_block;
|
| 49 | __visible int in_suspend __nosavedata;
|
| 50 |
|
| 51 | static char hibernate_compressor[CRYPTO_MAX_ALG_NAME] = CONFIG_HIBERNATION_DEF_COMP;
|
| 52 |
|
| 53 | |
| 54 | * Compression/decompression algorithm to be used while saving/loading
|
| 55 | * image to/from disk. This would later be used in 'kernel/power/swap.c'
|
| 56 | * to allocate comp streams.
|
| 57 |
|
| 58 | char hib_comp_algo[CRYPTO_MAX_ALG_NAME];
|
| 59 |
|
| 60 | enum {
|
| 61 | HIBERNATION_INVALID,
|
| 62 | HIBERNATION_PLATFORM,
|
| 63 | HIBERNATION_SHUTDOWN,
|
| 64 | HIBERNATION_REBOOT,
|
| 65 | #ifdef CONFIG_SUSPEND
|
| 66 | HIBERNATION_SUSPEND,
|
| 67 | #endif
|
| 68 | HIBERNATION_TEST_RESUME,
|
| 69 |
|
| 70 | __HIBERNATION_AFTER_LAST
|
| 71 | };
|
| 72 | #define HIBERNATION_MAX (__HIBERNATION_AFTER_LAST-1)
|
| 73 | #define HIBERNATION_FIRST (HIBERNATION_INVALID + 1)
|
| 74 |
|
| 75 | static int hibernation_mode = HIBERNATION_SHUTDOWN;
|
| 76 |
|
| 77 | bool freezer_test_done;
|
| 78 |
|
| 79 | static const struct platform_hibernation_ops *hibernation_ops;
|
| 80 |
|
| 81 | static atomic_t hibernate_atomic = ATOMIC_INIT(1);
|
| 82 |
|
| 83 | #ifdef CONFIG_SUSPEND
|
| 84 | |
| 85 | * pm_hibernation_mode_is_suspend - Check if hibernation has been set to suspend
|
| 86 |
|
| 87 | bool pm_hibernation_mode_is_suspend(void)
|
| 88 | {
|
| 89 | return hibernation_mode == HIBERNATION_SUSPEND;
|
| 90 | }
|
| 91 | EXPORT_SYMBOL_GPL(pm_hibernation_mode_is_suspend);
|
| 92 | #endif
|
| 93 |
|
| 94 | bool hibernate_acquire(void)
|
| 95 | {
|
| 96 | return atomic_add_unless(&hibernate_atomic, -1, 0);
|
| 97 | }
|
| 98 |
|
| 99 | void hibernate_release(void)
|
| 100 | {
|
| 101 | atomic_inc(&hibernate_atomic);
|
| 102 | }
|
| 103 |
|
| 104 | bool hibernation_in_progress(void)
|
| 105 | {
|
| 106 | return !atomic_read(&hibernate_atomic);
|
| 107 | }
|
| 108 |
|
| 109 | __weak bool arch_hibernation_available(void)
|
| 110 | {
|
| 111 | return true;
|
| 112 | }
|
| 113 |
|
| 114 | bool hibernation_available(void)
|
| 115 | {
|
| 116 | return nohibernate == 0 &&
|
| 117 | !security_locked_down(LOCKDOWN_HIBERNATION) &&
|
| 118 | !secretmem_active() && !cxl_mem_active() &&
|
| 119 | arch_hibernation_available();
|
| 120 | }
|
| 121 |
|
| 122 | |
| 123 | * hibernation_set_ops - Set the global hibernate operations.
|
| 124 | * @ops: Hibernation operations to use in subsequent hibernation transitions.
|
| 125 |
|
| 126 | void hibernation_set_ops(const struct platform_hibernation_ops *ops)
|
| 127 | {
|
| 128 | unsigned int sleep_flags;
|
| 129 |
|
| 130 | if (ops && !(ops->begin && ops->end && ops->pre_snapshot
|
| 131 | && ops->prepare && ops->finish && ops->enter && ops->pre_restore
|
| 132 | && ops->restore_cleanup && ops->leave)) {
|
| 133 | WARN_ON(1);
|
| 134 | return;
|
| 135 | }
|
| 136 |
|
| 137 | sleep_flags = lock_system_sleep();
|
| 138 |
|
| 139 | hibernation_ops = ops;
|
| 140 | if (ops)
|
| 141 | hibernation_mode = HIBERNATION_PLATFORM;
|
| 142 | else if (hibernation_mode == HIBERNATION_PLATFORM)
|
| 143 | hibernation_mode = HIBERNATION_SHUTDOWN;
|
| 144 |
|
| 145 | unlock_system_sleep(sleep_flags);
|
| 146 | }
|
| 147 | EXPORT_SYMBOL_GPL(hibernation_set_ops);
|
| 148 |
|
| 149 | static bool entering_platform_hibernation;
|
| 150 |
|
| 151 | bool system_entering_hibernation(void)
|
| 152 | {
|
| 153 | return entering_platform_hibernation;
|
| 154 | }
|
| 155 | EXPORT_SYMBOL(system_entering_hibernation);
|
| 156 |
|
| 157 | #ifdef CONFIG_PM_DEBUG
|
| 158 | static unsigned int pm_test_delay = 5;
|
| 159 | module_param(pm_test_delay, uint, 0644);
|
| 160 | MODULE_PARM_DESC(pm_test_delay,
|
| 161 | "Number of seconds to wait before resuming from hibernation test");
|
| 162 | static void hibernation_debug_sleep(void)
|
| 163 | {
|
| 164 | pr_info("hibernation debug: Waiting for %d second(s).\n",
|
| 165 | pm_test_delay);
|
| 166 | mdelay(pm_test_delay * 1000);
|
| 167 | }
|
| 168 |
|
| 169 | static int hibernation_test(int level)
|
| 170 | {
|
| 171 | if (pm_test_level == level) {
|
| 172 | hibernation_debug_sleep();
|
| 173 | return 1;
|
| 174 | }
|
| 175 | return 0;
|
| 176 | }
|
| 177 | #else
|
| 178 | static int hibernation_test(int level) { return 0; }
|
| 179 | #endif
|
| 180 |
|
| 181 | |
| 182 | * platform_begin - Call platform to start hibernation.
|
| 183 | * @platform_mode: Whether or not to use the platform driver.
|
| 184 |
|
| 185 | static int platform_begin(int platform_mode)
|
| 186 | {
|
| 187 | return (platform_mode && hibernation_ops) ?
|
| 188 | hibernation_ops->begin(PMSG_FREEZE) : 0;
|
| 189 | }
|
| 190 |
|
| 191 | |
| 192 | * platform_end - Call platform to finish transition to the working state.
|
| 193 | * @platform_mode: Whether or not to use the platform driver.
|
| 194 |
|
| 195 | static void platform_end(int platform_mode)
|
| 196 | {
|
| 197 | if (platform_mode && hibernation_ops)
|
| 198 | hibernation_ops->end();
|
| 199 | }
|
| 200 |
|
| 201 | |
| 202 | * platform_pre_snapshot - Call platform to prepare the machine for hibernation.
|
| 203 | * @platform_mode: Whether or not to use the platform driver.
|
| 204 | *
|
| 205 | * Use the platform driver to prepare the system for creating a hibernate image,
|
| 206 | * if so configured, and return an error code if that fails.
|
| 207 |
|
| 208 |
|
| 209 | static int platform_pre_snapshot(int platform_mode)
|
| 210 | {
|
| 211 | return (platform_mode && hibernation_ops) ?
|
| 212 | hibernation_ops->pre_snapshot() : 0;
|
| 213 | }
|
| 214 |
|
| 215 | |
| 216 | * platform_leave - Call platform to prepare a transition to the working state.
|
| 217 | * @platform_mode: Whether or not to use the platform driver.
|
| 218 | *
|
| 219 | * Use the platform driver prepare to prepare the machine for switching to the
|
| 220 | * normal mode of operation.
|
| 221 | *
|
| 222 | * This routine is called on one CPU with interrupts disabled.
|
| 223 |
|
| 224 | static void platform_leave(int platform_mode)
|
| 225 | {
|
| 226 | if (platform_mode && hibernation_ops)
|
| 227 | hibernation_ops->leave();
|
| 228 | }
|
| 229 |
|
| 230 | |
| 231 | * platform_finish - Call platform to switch the system to the working state.
|
| 232 | * @platform_mode: Whether or not to use the platform driver.
|
| 233 | *
|
| 234 | * Use the platform driver to switch the machine to the normal mode of
|
| 235 | * operation.
|
| 236 | *
|
| 237 | * This routine must be called after platform_prepare().
|
| 238 |
|
| 239 | static void platform_finish(int platform_mode)
|
| 240 | {
|
| 241 | if (platform_mode && hibernation_ops)
|
| 242 | hibernation_ops->finish();
|
| 243 | }
|
| 244 |
|
| 245 | |
| 246 | * platform_pre_restore - Prepare for hibernate image restoration.
|
| 247 | * @platform_mode: Whether or not to use the platform driver.
|
| 248 | *
|
| 249 | * Use the platform driver to prepare the system for resume from a hibernation
|
| 250 | * image.
|
| 251 | *
|
| 252 | * If the restore fails after this function has been called,
|
| 253 | * platform_restore_cleanup() must be called.
|
| 254 |
|
| 255 | static int platform_pre_restore(int platform_mode)
|
| 256 | {
|
| 257 | return (platform_mode && hibernation_ops) ?
|
| 258 | hibernation_ops->pre_restore() : 0;
|
| 259 | }
|
| 260 |
|
| 261 | |
| 262 | * platform_restore_cleanup - Switch to the working state after failing restore.
|
| 263 | * @platform_mode: Whether or not to use the platform driver.
|
| 264 | *
|
| 265 | * Use the platform driver to switch the system to the normal mode of operation
|
| 266 | * after a failing restore.
|
| 267 | *
|
| 268 | * If platform_pre_restore() has been called before the failing restore, this
|
| 269 | * function must be called too, regardless of the result of
|
| 270 | * platform_pre_restore().
|
| 271 |
|
| 272 | static void platform_restore_cleanup(int platform_mode)
|
| 273 | {
|
| 274 | if (platform_mode && hibernation_ops)
|
| 275 | hibernation_ops->restore_cleanup();
|
| 276 | }
|
| 277 |
|
| 278 | |
| 279 | * platform_recover - Recover from a failure to suspend devices.
|
| 280 | * @platform_mode: Whether or not to use the platform driver.
|
| 281 |
|
| 282 | static void platform_recover(int platform_mode)
|
| 283 | {
|
| 284 | if (platform_mode && hibernation_ops && hibernation_ops->recover)
|
| 285 | hibernation_ops->recover();
|
| 286 | }
|
| 287 |
|
| 288 | |
| 289 | * swsusp_show_speed - Print time elapsed between two events during hibernation.
|
| 290 | * @start: Starting event.
|
| 291 | * @stop: Final event.
|
| 292 | * @nr_pages: Number of memory pages processed between @start and @stop.
|
| 293 | * @msg: Additional diagnostic message to print.
|
| 294 |
|
| 295 | void swsusp_show_speed(ktime_t start, ktime_t stop,
|
| 296 | unsigned nr_pages, char *msg)
|
| 297 | {
|
| 298 | ktime_t diff;
|
| 299 | u64 elapsed_centisecs64;
|
| 300 | unsigned int centisecs;
|
| 301 | unsigned int k;
|
| 302 | unsigned int kps;
|
| 303 |
|
| 304 | diff = ktime_sub(stop, start);
|
| 305 | elapsed_centisecs64 = ktime_divns(diff, 10*NSEC_PER_MSEC);
|
| 306 | centisecs = elapsed_centisecs64;
|
| 307 | if (centisecs == 0)
|
| 308 | centisecs = 1;
|
| 309 | k = nr_pages * (PAGE_SIZE / 1024);
|
| 310 | kps = (k * 100) / centisecs;
|
| 311 | pr_info("%s %u kbytes in %u.%02u seconds (%u.%02u MB/s)\n",
|
| 312 | msg, k, centisecs / 100, centisecs % 100, kps / 1000,
|
| 313 | (kps % 1000) / 10);
|
| 314 | }
|
| 315 |
|
| 316 | __weak int arch_resume_nosmt(void)
|
| 317 | {
|
| 318 | return 0;
|
| 319 | }
|
| 320 |
|
| 321 | |
| 322 | * create_image - Create a hibernation image.
|
| 323 | * @platform_mode: Whether or not to use the platform driver.
|
| 324 | *
|
| 325 | * Execute device drivers' "late" and "noirq" freeze callbacks, create a
|
| 326 | * hibernation image and run the drivers' "noirq" and "early" thaw callbacks.
|
| 327 | *
|
| 328 | * Control reappears in this routine after the subsequent restore.
|
| 329 |
|
| 330 | static int create_image(int platform_mode)
|
| 331 | {
|
| 332 | int error;
|
| 333 |
|
| 334 | error = dpm_suspend_end(PMSG_FREEZE);
|
| 335 | if (error) {
|
| 336 | pr_err("Some devices failed to power down, aborting\n");
|
| 337 | return error;
|
| 338 | }
|
| 339 |
|
| 340 | error = platform_pre_snapshot(platform_mode);
|
| 341 | if (error || hibernation_test(TEST_PLATFORM))
|
| 342 | goto Platform_finish;
|
| 343 |
|
| 344 | error = pm_sleep_disable_secondary_cpus();
|
| 345 | if (error || hibernation_test(TEST_CPUS))
|
| 346 | goto Enable_cpus;
|
| 347 |
|
| 348 | local_irq_disable();
|
| 349 |
|
| 350 | system_state = SYSTEM_SUSPEND;
|
| 351 |
|
| 352 | error = syscore_suspend();
|
| 353 | if (error) {
|
| 354 | pr_err("Some system devices failed to power down, aborting\n");
|
| 355 | goto Enable_irqs;
|
| 356 | }
|
| 357 |
|
| 358 | if (hibernation_test(TEST_CORE) || pm_wakeup_pending())
|
| 359 | goto Power_up;
|
| 360 |
|
| 361 | in_suspend = 1;
|
| 362 | save_processor_state();
|
| 363 | trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
|
| 364 | error = swsusp_arch_suspend();
|
| 365 |
|
| 366 | restore_processor_state();
|
| 367 | trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
|
| 368 | if (error)
|
| 369 | pr_err("Error %d creating image\n", error);
|
| 370 |
|
| 371 | if (!in_suspend) {
|
| 372 | events_check_enabled = false;
|
| 373 | clear_or_poison_free_pages();
|
| 374 | }
|
| 375 |
|
| 376 | platform_leave(platform_mode);
|
| 377 |
|
| 378 | Power_up:
|
| 379 | syscore_resume();
|
| 380 |
|
| 381 | Enable_irqs:
|
| 382 | system_state = SYSTEM_RUNNING;
|
| 383 | local_irq_enable();
|
| 384 |
|
| 385 | Enable_cpus:
|
| 386 | pm_sleep_enable_secondary_cpus();
|
| 387 |
|
| 388 |
|
| 389 | if (!in_suspend)
|
| 390 | error = arch_resume_nosmt();
|
| 391 |
|
| 392 | Platform_finish:
|
| 393 | platform_finish(platform_mode);
|
| 394 |
|
| 395 | dpm_resume_start(in_suspend ?
|
| 396 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
| 397 |
|
| 398 | return error;
|
| 399 | }
|
| 400 |
|
| 401 | |
| 402 | * hibernation_snapshot - Quiesce devices and create a hibernation image.
|
| 403 | * @platform_mode: If set, use platform driver to prepare for the transition.
|
| 404 | *
|
| 405 | * This routine must be called with system_transition_mutex held.
|
| 406 |
|
| 407 | int hibernation_snapshot(int platform_mode)
|
| 408 | {
|
| 409 | pm_message_t msg;
|
| 410 | int error;
|
| 411 |
|
| 412 | pm_suspend_clear_flags();
|
| 413 | error = platform_begin(platform_mode);
|
| 414 | if (error)
|
| 415 | goto Close;
|
| 416 |
|
| 417 | error = dpm_prepare(PMSG_FREEZE);
|
| 418 | if (error)
|
| 419 | goto Complete;
|
| 420 |
|
| 421 |
|
| 422 | error = hibernate_preallocate_memory();
|
| 423 | if (error)
|
| 424 | goto Complete;
|
| 425 |
|
| 426 | error = freeze_kernel_threads();
|
| 427 | if (error)
|
| 428 | goto Cleanup;
|
| 429 |
|
| 430 | if (hibernation_test(TEST_FREEZER)) {
|
| 431 |
|
| 432 | |
| 433 | * Indicate to the caller that we are returning due to a
|
| 434 | * successful freezer test.
|
| 435 |
|
| 436 | freezer_test_done = true;
|
| 437 | goto Thaw;
|
| 438 | }
|
| 439 |
|
| 440 | console_suspend_all();
|
| 441 | pm_restrict_gfp_mask();
|
| 442 |
|
| 443 | error = dpm_suspend(PMSG_FREEZE);
|
| 444 |
|
| 445 | if (error || hibernation_test(TEST_DEVICES))
|
| 446 | platform_recover(platform_mode);
|
| 447 | else
|
| 448 | error = create_image(platform_mode);
|
| 449 |
|
| 450 | |
| 451 | * In the case that we call create_image() above, the control
|
| 452 | * returns here (1) after the image has been created or the
|
| 453 | * image creation has failed and (2) after a successful restore.
|
| 454 |
|
| 455 |
|
| 456 |
|
| 457 | if (error || !in_suspend)
|
| 458 | swsusp_free();
|
| 459 |
|
| 460 | msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE;
|
| 461 | dpm_resume(msg);
|
| 462 |
|
| 463 | if (error || !in_suspend)
|
| 464 | pm_restore_gfp_mask();
|
| 465 |
|
| 466 | console_resume_all();
|
| 467 | dpm_complete(msg);
|
| 468 |
|
| 469 | Close:
|
| 470 | platform_end(platform_mode);
|
| 471 | return error;
|
| 472 |
|
| 473 | Thaw:
|
| 474 | thaw_kernel_threads();
|
| 475 | Cleanup:
|
| 476 | swsusp_free();
|
| 477 | Complete:
|
| 478 | dpm_complete(PMSG_RECOVER);
|
| 479 | goto Close;
|
| 480 | }
|
| 481 |
|
| 482 | int __weak hibernate_resume_nonboot_cpu_disable(void)
|
| 483 | {
|
| 484 | return suspend_disable_secondary_cpus();
|
| 485 | }
|
| 486 |
|
| 487 | |
| 488 | * resume_target_kernel - Restore system state from a hibernation image.
|
| 489 | * @platform_mode: Whether or not to use the platform driver.
|
| 490 | *
|
| 491 | * Execute device drivers' "noirq" and "late" freeze callbacks, restore the
|
| 492 | * contents of highmem that have not been restored yet from the image and run
|
| 493 | * the low-level code that will restore the remaining contents of memory and
|
| 494 | * switch to the just restored target kernel.
|
| 495 |
|
| 496 | static int resume_target_kernel(bool platform_mode)
|
| 497 | {
|
| 498 | int error;
|
| 499 |
|
| 500 | error = dpm_suspend_end(PMSG_QUIESCE);
|
| 501 | if (error) {
|
| 502 | pr_err("Some devices failed to power down, aborting resume\n");
|
| 503 | return error;
|
| 504 | }
|
| 505 |
|
| 506 | error = platform_pre_restore(platform_mode);
|
| 507 | if (error)
|
| 508 | goto Cleanup;
|
| 509 |
|
| 510 | cpuidle_pause();
|
| 511 |
|
| 512 | error = hibernate_resume_nonboot_cpu_disable();
|
| 513 | if (error)
|
| 514 | goto Enable_cpus;
|
| 515 |
|
| 516 | local_irq_disable();
|
| 517 | system_state = SYSTEM_SUSPEND;
|
| 518 |
|
| 519 | error = syscore_suspend();
|
| 520 | if (error)
|
| 521 | goto Enable_irqs;
|
| 522 |
|
| 523 | save_processor_state();
|
| 524 | error = restore_highmem();
|
| 525 | if (!error) {
|
| 526 | error = swsusp_arch_resume();
|
| 527 | |
| 528 | * The code below is only ever reached in case of a failure.
|
| 529 | * Otherwise, execution continues at the place where
|
| 530 | * swsusp_arch_suspend() was called.
|
| 531 |
|
| 532 | BUG_ON(!error);
|
| 533 | |
| 534 | * This call to restore_highmem() reverts the changes made by
|
| 535 | * the previous one.
|
| 536 |
|
| 537 | restore_highmem();
|
| 538 | }
|
| 539 | |
| 540 | * The only reason why swsusp_arch_resume() can fail is memory being
|
| 541 | * very tight, so we have to free it as soon as we can to avoid
|
| 542 | * subsequent failures.
|
| 543 |
|
| 544 | swsusp_free();
|
| 545 | restore_processor_state();
|
| 546 | touch_softlockup_watchdog();
|
| 547 |
|
| 548 | syscore_resume();
|
| 549 |
|
| 550 | Enable_irqs:
|
| 551 | system_state = SYSTEM_RUNNING;
|
| 552 | local_irq_enable();
|
| 553 |
|
| 554 | Enable_cpus:
|
| 555 | pm_sleep_enable_secondary_cpus();
|
| 556 |
|
| 557 | Cleanup:
|
| 558 | platform_restore_cleanup(platform_mode);
|
| 559 |
|
| 560 | dpm_resume_start(PMSG_RECOVER);
|
| 561 |
|
| 562 | return error;
|
| 563 | }
|
| 564 |
|
| 565 | |
| 566 | * hibernation_restore - Quiesce devices and restore from a hibernation image.
|
| 567 | * @platform_mode: If set, use platform driver to prepare for the transition.
|
| 568 | *
|
| 569 | * This routine must be called with system_transition_mutex held. If it is
|
| 570 | * successful, control reappears in the restored target kernel in
|
| 571 | * hibernation_snapshot().
|
| 572 |
|
| 573 | int hibernation_restore(int platform_mode)
|
| 574 | {
|
| 575 | int error;
|
| 576 |
|
| 577 | pm_prepare_console();
|
| 578 | console_suspend_all();
|
| 579 | error = dpm_suspend_start(PMSG_QUIESCE);
|
| 580 | if (!error) {
|
| 581 | error = resume_target_kernel(platform_mode);
|
| 582 | |
| 583 | * The above should either succeed and jump to the new kernel,
|
| 584 | * or return with an error. Otherwise things are just
|
| 585 | * undefined, so let's be paranoid.
|
| 586 |
|
| 587 | BUG_ON(!error);
|
| 588 | }
|
| 589 | dpm_resume_end(PMSG_RECOVER);
|
| 590 | console_resume_all();
|
| 591 | pm_restore_console();
|
| 592 | return error;
|
| 593 | }
|
| 594 |
|
| 595 | |
| 596 | * hibernation_platform_enter - Power off the system using the platform driver.
|
| 597 |
|
| 598 | int hibernation_platform_enter(void)
|
| 599 | {
|
| 600 | int error;
|
| 601 |
|
| 602 | if (!hibernation_ops)
|
| 603 | return -ENOSYS;
|
| 604 |
|
| 605 | |
| 606 | * We have cancelled the power transition by running
|
| 607 | * hibernation_ops->finish() before saving the image, so we should let
|
| 608 | * the firmware know that we're going to enter the sleep state after all
|
| 609 |
|
| 610 | error = hibernation_ops->begin(PMSG_HIBERNATE);
|
| 611 | if (error)
|
| 612 | goto Close;
|
| 613 |
|
| 614 | entering_platform_hibernation = true;
|
| 615 | console_suspend_all();
|
| 616 | error = dpm_suspend_start(PMSG_HIBERNATE);
|
| 617 | if (error) {
|
| 618 | if (hibernation_ops->recover)
|
| 619 | hibernation_ops->recover();
|
| 620 | goto Resume_devices;
|
| 621 | }
|
| 622 |
|
| 623 | error = dpm_suspend_end(PMSG_HIBERNATE);
|
| 624 | if (error)
|
| 625 | goto Resume_devices;
|
| 626 |
|
| 627 | error = hibernation_ops->prepare();
|
| 628 | if (error)
|
| 629 | goto Platform_finish;
|
| 630 |
|
| 631 | error = pm_sleep_disable_secondary_cpus();
|
| 632 | if (error)
|
| 633 | goto Enable_cpus;
|
| 634 |
|
| 635 | local_irq_disable();
|
| 636 | system_state = SYSTEM_SUSPEND;
|
| 637 |
|
| 638 | error = syscore_suspend();
|
| 639 | if (error)
|
| 640 | goto Enable_irqs;
|
| 641 |
|
| 642 | if (pm_wakeup_pending()) {
|
| 643 | error = -EAGAIN;
|
| 644 | goto Power_up;
|
| 645 | }
|
| 646 |
|
| 647 | hibernation_ops->enter();
|
| 648 |
|
| 649 | while (1);
|
| 650 |
|
| 651 | Power_up:
|
| 652 | syscore_resume();
|
| 653 | Enable_irqs:
|
| 654 | system_state = SYSTEM_RUNNING;
|
| 655 | local_irq_enable();
|
| 656 |
|
| 657 | Enable_cpus:
|
| 658 | pm_sleep_enable_secondary_cpus();
|
| 659 |
|
| 660 | Platform_finish:
|
| 661 | hibernation_ops->finish();
|
| 662 |
|
| 663 | dpm_resume_start(PMSG_RESTORE);
|
| 664 |
|
| 665 | Resume_devices:
|
| 666 | entering_platform_hibernation = false;
|
| 667 | dpm_resume_end(PMSG_RESTORE);
|
| 668 | console_resume_all();
|
| 669 |
|
| 670 | Close:
|
| 671 | hibernation_ops->end();
|
| 672 |
|
| 673 | return error;
|
| 674 | }
|
| 675 |
|
| 676 | |
| 677 | * power_down - Shut the machine down for hibernation.
|
| 678 | *
|
| 679 | * Use the platform driver, if configured, to put the system into the sleep
|
| 680 | * state corresponding to hibernation, or try to power it off or reboot,
|
| 681 | * depending on the value of hibernation_mode.
|
| 682 |
|
| 683 | static void power_down(void)
|
| 684 | {
|
| 685 | int error;
|
| 686 |
|
| 687 | #ifdef CONFIG_SUSPEND
|
| 688 | if (hibernation_mode == HIBERNATION_SUSPEND) {
|
| 689 | error = suspend_devices_and_enter(mem_sleep_current);
|
| 690 | if (!error)
|
| 691 | goto exit;
|
| 692 |
|
| 693 | hibernation_mode = hibernation_ops ? HIBERNATION_PLATFORM :
|
| 694 | HIBERNATION_SHUTDOWN;
|
| 695 | }
|
| 696 | #endif
|
| 697 |
|
| 698 | switch (hibernation_mode) {
|
| 699 | case HIBERNATION_REBOOT:
|
| 700 | kernel_restart(NULL);
|
| 701 | break;
|
| 702 | case HIBERNATION_PLATFORM:
|
| 703 | error = hibernation_platform_enter();
|
| 704 | if (error == -EAGAIN || error == -EBUSY) {
|
| 705 | events_check_enabled = false;
|
| 706 | pr_info("Wakeup event detected during hibernation, rolling back.\n");
|
| 707 | goto exit;
|
| 708 | }
|
| 709 | fallthrough;
|
| 710 | case HIBERNATION_SHUTDOWN:
|
| 711 | if (kernel_can_power_off()) {
|
| 712 | entering_platform_hibernation = true;
|
| 713 | kernel_power_off();
|
| 714 | entering_platform_hibernation = false;
|
| 715 | }
|
| 716 | break;
|
| 717 | }
|
| 718 | kernel_halt();
|
| 719 | |
| 720 | * Valid image is on the disk, if we continue we risk serious data
|
| 721 | * corruption after resume.
|
| 722 |
|
| 723 | pr_crit("Power down manually\n");
|
| 724 | while (1)
|
| 725 | cpu_relax();
|
| 726 |
|
| 727 | exit:
|
| 728 |
|
| 729 | error = swsusp_unmark();
|
| 730 | if (error)
|
| 731 | pr_err("Swap will be unusable! Try swapon -a.\n");
|
| 732 | }
|
| 733 |
|
| 734 | static int load_image_and_restore(void)
|
| 735 | {
|
| 736 | int error;
|
| 737 | unsigned int flags;
|
| 738 |
|
| 739 | pm_pr_dbg("Loading hibernation image.\n");
|
| 740 |
|
| 741 | lock_device_hotplug();
|
| 742 | error = create_basic_memory_bitmaps();
|
| 743 | if (error) {
|
| 744 | swsusp_close();
|
| 745 | goto Unlock;
|
| 746 | }
|
| 747 |
|
| 748 | error = swsusp_read(&flags);
|
| 749 | swsusp_close();
|
| 750 | if (!error)
|
| 751 | error = hibernation_restore(flags & SF_PLATFORM_MODE);
|
| 752 |
|
| 753 | pr_err("Failed to load image, recovering.\n");
|
| 754 | swsusp_free();
|
| 755 | free_basic_memory_bitmaps();
|
| 756 | Unlock:
|
| 757 | unlock_device_hotplug();
|
| 758 |
|
| 759 | return error;
|
| 760 | }
|
| 761 |
|
| 762 | #define COMPRESSION_ALGO_LZO "lzo"
|
| 763 | #define COMPRESSION_ALGO_LZ4 "lz4"
|
| 764 |
|
| 765 | |
| 766 | * hibernate - Carry out system hibernation, including saving the image.
|
| 767 |
|
| 768 | int hibernate(void)
|
| 769 | {
|
| 770 | bool snapshot_test = false;
|
| 771 | unsigned int sleep_flags;
|
| 772 | int error;
|
| 773 |
|
| 774 | if (!hibernation_available()) {
|
| 775 | pm_pr_dbg("Hibernation not available.\n");
|
| 776 | return -EPERM;
|
| 777 | }
|
| 778 |
|
| 779 | |
| 780 | * Query for the compression algorithm support if compression is enabled.
|
| 781 |
|
| 782 | if (!nocompress) {
|
| 783 | strscpy(hib_comp_algo, hibernate_compressor);
|
| 784 | if (!crypto_has_acomp(hib_comp_algo, 0, CRYPTO_ALG_ASYNC)) {
|
| 785 | pr_err("%s compression is not available\n", hib_comp_algo);
|
| 786 | return -EOPNOTSUPP;
|
| 787 | }
|
| 788 | }
|
| 789 |
|
| 790 | sleep_flags = lock_system_sleep();
|
| 791 |
|
| 792 | if (!hibernate_acquire()) {
|
| 793 | error = -EBUSY;
|
| 794 | goto Unlock;
|
| 795 | }
|
| 796 |
|
| 797 | pr_info("hibernation entry\n");
|
| 798 | pm_prepare_console();
|
| 799 | error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION);
|
| 800 | if (error)
|
| 801 | goto Restore;
|
| 802 |
|
| 803 | error = pm_sleep_fs_sync();
|
| 804 | if (error)
|
| 805 | goto Notify;
|
| 806 |
|
| 807 | filesystems_freeze(filesystem_freeze_enabled);
|
| 808 |
|
| 809 | error = freeze_processes();
|
| 810 | if (error)
|
| 811 | goto Exit;
|
| 812 |
|
| 813 | lock_device_hotplug();
|
| 814 |
|
| 815 | error = create_basic_memory_bitmaps();
|
| 816 | if (error)
|
| 817 | goto Thaw;
|
| 818 |
|
| 819 | error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
|
| 820 | if (error || freezer_test_done)
|
| 821 | goto Free_bitmaps;
|
| 822 |
|
| 823 | if (in_suspend) {
|
| 824 | unsigned int flags = 0;
|
| 825 |
|
| 826 | if (hibernation_mode == HIBERNATION_PLATFORM)
|
| 827 | flags |= SF_PLATFORM_MODE;
|
| 828 | if (nocompress) {
|
| 829 | flags |= SF_NOCOMPRESS_MODE;
|
| 830 | } else {
|
| 831 | flags |= SF_CRC32_MODE;
|
| 832 |
|
| 833 | |
| 834 | * By default, LZO compression is enabled. Use SF_COMPRESSION_ALG_LZ4
|
| 835 | * to override this behaviour and use LZ4.
|
| 836 | *
|
| 837 | * Refer kernel/power/power.h for more details
|
| 838 |
|
| 839 |
|
| 840 | if (!strcmp(hib_comp_algo, COMPRESSION_ALGO_LZ4))
|
| 841 | flags |= SF_COMPRESSION_ALG_LZ4;
|
| 842 | else
|
| 843 | flags |= SF_COMPRESSION_ALG_LZO;
|
| 844 | }
|
| 845 |
|
| 846 | pm_pr_dbg("Writing hibernation image.\n");
|
| 847 | error = swsusp_write(flags);
|
| 848 | swsusp_free();
|
| 849 | if (!error) {
|
| 850 | if (hibernation_mode == HIBERNATION_TEST_RESUME)
|
| 851 | snapshot_test = true;
|
| 852 | else
|
| 853 | power_down();
|
| 854 | }
|
| 855 | in_suspend = 0;
|
| 856 | pm_restore_gfp_mask();
|
| 857 | } else {
|
| 858 | pm_pr_dbg("Hibernation image restored successfully.\n");
|
| 859 | }
|
| 860 |
|
| 861 | Free_bitmaps:
|
| 862 | free_basic_memory_bitmaps();
|
| 863 | Thaw:
|
| 864 | unlock_device_hotplug();
|
| 865 | if (snapshot_test) {
|
| 866 | pm_pr_dbg("Checking hibernation image\n");
|
| 867 | error = swsusp_check(false);
|
| 868 | if (!error)
|
| 869 | error = load_image_and_restore();
|
| 870 | }
|
| 871 | thaw_processes();
|
| 872 |
|
| 873 |
|
| 874 | freezer_test_done = false;
|
| 875 | Exit:
|
| 876 | filesystems_thaw();
|
| 877 | Notify:
|
| 878 | pm_notifier_call_chain(PM_POST_HIBERNATION);
|
| 879 | Restore:
|
| 880 | pm_restore_console();
|
| 881 | hibernate_release();
|
| 882 | Unlock:
|
| 883 | unlock_system_sleep(sleep_flags);
|
| 884 | pr_info("hibernation exit\n");
|
| 885 |
|
| 886 | return error;
|
| 887 | }
|
| 888 |
|
| 889 | |
| 890 | * hibernate_quiet_exec - Execute a function with all devices frozen.
|
| 891 | * @func: Function to execute.
|
| 892 | * @data: Data pointer to pass to @func.
|
| 893 | *
|
| 894 | * Return the @func return value or an error code if it cannot be executed.
|
| 895 |
|
| 896 | int hibernate_quiet_exec(int (*func)(void *data), void *data)
|
| 897 | {
|
| 898 | unsigned int sleep_flags;
|
| 899 | int error;
|
| 900 |
|
| 901 | sleep_flags = lock_system_sleep();
|
| 902 |
|
| 903 | if (!hibernate_acquire()) {
|
| 904 | error = -EBUSY;
|
| 905 | goto unlock;
|
| 906 | }
|
| 907 |
|
| 908 | pm_prepare_console();
|
| 909 |
|
| 910 | error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION);
|
| 911 | if (error)
|
| 912 | goto restore;
|
| 913 |
|
| 914 | filesystems_freeze(filesystem_freeze_enabled);
|
| 915 |
|
| 916 | error = freeze_processes();
|
| 917 | if (error)
|
| 918 | goto exit;
|
| 919 |
|
| 920 | lock_device_hotplug();
|
| 921 |
|
| 922 | pm_suspend_clear_flags();
|
| 923 |
|
| 924 | error = platform_begin(true);
|
| 925 | if (error)
|
| 926 | goto thaw;
|
| 927 |
|
| 928 | error = freeze_kernel_threads();
|
| 929 | if (error)
|
| 930 | goto thaw;
|
| 931 |
|
| 932 | error = dpm_prepare(PMSG_FREEZE);
|
| 933 | if (error)
|
| 934 | goto dpm_complete;
|
| 935 |
|
| 936 | console_suspend_all();
|
| 937 |
|
| 938 | error = dpm_suspend(PMSG_FREEZE);
|
| 939 | if (error)
|
| 940 | goto dpm_resume;
|
| 941 |
|
| 942 | error = dpm_suspend_end(PMSG_FREEZE);
|
| 943 | if (error)
|
| 944 | goto dpm_resume;
|
| 945 |
|
| 946 | error = platform_pre_snapshot(true);
|
| 947 | if (error)
|
| 948 | goto skip;
|
| 949 |
|
| 950 | error = func(data);
|
| 951 |
|
| 952 | skip:
|
| 953 | platform_finish(true);
|
| 954 |
|
| 955 | dpm_resume_start(PMSG_THAW);
|
| 956 |
|
| 957 | dpm_resume:
|
| 958 | dpm_resume(PMSG_THAW);
|
| 959 |
|
| 960 | console_resume_all();
|
| 961 |
|
| 962 | dpm_complete:
|
| 963 | dpm_complete(PMSG_THAW);
|
| 964 |
|
| 965 | thaw_kernel_threads();
|
| 966 |
|
| 967 | thaw:
|
| 968 | platform_end(true);
|
| 969 |
|
| 970 | unlock_device_hotplug();
|
| 971 |
|
| 972 | thaw_processes();
|
| 973 |
|
| 974 | exit:
|
| 975 | filesystems_thaw();
|
| 976 | pm_notifier_call_chain(PM_POST_HIBERNATION);
|
| 977 |
|
| 978 | restore:
|
| 979 | pm_restore_console();
|
| 980 |
|
| 981 | hibernate_release();
|
| 982 |
|
| 983 | unlock:
|
| 984 | unlock_system_sleep(sleep_flags);
|
| 985 |
|
| 986 | return error;
|
| 987 | }
|
| 988 | EXPORT_SYMBOL_GPL(hibernate_quiet_exec);
|
| 989 |
|
| 990 | static int __init find_resume_device(void)
|
| 991 | {
|
| 992 | if (!strlen(resume_file))
|
| 993 | return -ENOENT;
|
| 994 |
|
| 995 | pm_pr_dbg("Checking hibernation image partition %s\n", resume_file);
|
| 996 |
|
| 997 | if (resume_delay) {
|
| 998 | pr_info("Waiting %dsec before reading resume device ...\n",
|
| 999 | resume_delay);
|
| 1000 | ssleep(resume_delay);
|
| 1001 | }
|
| 1002 |
|
| 1003 |
|
| 1004 | if (!early_lookup_bdev(resume_file, &swsusp_resume_device))
|
| 1005 | return 0;
|
| 1006 |
|
| 1007 | |
| 1008 | * Some device discovery might still be in progress; we need to wait for
|
| 1009 | * this to finish.
|
| 1010 |
|
| 1011 | wait_for_device_probe();
|
| 1012 | if (resume_wait) {
|
| 1013 | while (early_lookup_bdev(resume_file, &swsusp_resume_device))
|
| 1014 | msleep(10);
|
| 1015 | async_synchronize_full();
|
| 1016 | }
|
| 1017 |
|
| 1018 | return early_lookup_bdev(resume_file, &swsusp_resume_device);
|
| 1019 | }
|
| 1020 |
|
| 1021 | static int software_resume(void)
|
| 1022 | {
|
| 1023 | int error;
|
| 1024 |
|
| 1025 | pm_pr_dbg("Hibernation image partition %d:%d present\n",
|
| 1026 | MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
|
| 1027 |
|
| 1028 | pm_pr_dbg("Looking for hibernation image.\n");
|
| 1029 |
|
| 1030 | mutex_lock(&system_transition_mutex);
|
| 1031 | error = swsusp_check(true);
|
| 1032 | if (error)
|
| 1033 | goto Unlock;
|
| 1034 |
|
| 1035 | |
| 1036 | * Check if the hibernation image is compressed. If so, query for
|
| 1037 | * the algorithm support.
|
| 1038 |
|
| 1039 | if (!(swsusp_header_flags & SF_NOCOMPRESS_MODE)) {
|
| 1040 | if (swsusp_header_flags & SF_COMPRESSION_ALG_LZ4)
|
| 1041 | strscpy(hib_comp_algo, COMPRESSION_ALGO_LZ4);
|
| 1042 | else
|
| 1043 | strscpy(hib_comp_algo, COMPRESSION_ALGO_LZO);
|
| 1044 | if (!crypto_has_acomp(hib_comp_algo, 0, CRYPTO_ALG_ASYNC)) {
|
| 1045 | pr_err("%s compression is not available\n", hib_comp_algo);
|
| 1046 | error = -EOPNOTSUPP;
|
| 1047 | goto Unlock;
|
| 1048 | }
|
| 1049 | }
|
| 1050 |
|
| 1051 |
|
| 1052 | if (!hibernate_acquire()) {
|
| 1053 | error = -EBUSY;
|
| 1054 | swsusp_close();
|
| 1055 | goto Unlock;
|
| 1056 | }
|
| 1057 |
|
| 1058 | pr_info("resume from hibernation\n");
|
| 1059 | pm_prepare_console();
|
| 1060 | error = pm_notifier_call_chain_robust(PM_RESTORE_PREPARE, PM_POST_RESTORE);
|
| 1061 | if (error)
|
| 1062 | goto Restore;
|
| 1063 |
|
| 1064 | filesystems_freeze(filesystem_freeze_enabled);
|
| 1065 |
|
| 1066 | pm_pr_dbg("Preparing processes for hibernation restore.\n");
|
| 1067 | error = freeze_processes();
|
| 1068 | if (error) {
|
| 1069 | filesystems_thaw();
|
| 1070 | goto Close_Finish;
|
| 1071 | }
|
| 1072 |
|
| 1073 | error = freeze_kernel_threads();
|
| 1074 | if (error) {
|
| 1075 | thaw_processes();
|
| 1076 | filesystems_thaw();
|
| 1077 | goto Close_Finish;
|
| 1078 | }
|
| 1079 |
|
| 1080 | error = load_image_and_restore();
|
| 1081 | thaw_processes();
|
| 1082 | filesystems_thaw();
|
| 1083 | Finish:
|
| 1084 | pm_notifier_call_chain(PM_POST_RESTORE);
|
| 1085 | Restore:
|
| 1086 | pm_restore_console();
|
| 1087 | pr_info("resume failed (%d)\n", error);
|
| 1088 | hibernate_release();
|
| 1089 |
|
| 1090 | Unlock:
|
| 1091 | mutex_unlock(&system_transition_mutex);
|
| 1092 | pm_pr_dbg("Hibernation image not present or could not be loaded.\n");
|
| 1093 | return error;
|
| 1094 | Close_Finish:
|
| 1095 | swsusp_close();
|
| 1096 | goto Finish;
|
| 1097 | }
|
| 1098 |
|
| 1099 | |
| 1100 | * software_resume_initcall - Resume from a saved hibernation image.
|
| 1101 | *
|
| 1102 | * This routine is called as a late initcall, when all devices have been
|
| 1103 | * discovered and initialized already.
|
| 1104 | *
|
| 1105 | * The image reading code is called to see if there is a hibernation image
|
| 1106 | * available for reading. If that is the case, devices are quiesced and the
|
| 1107 | * contents of memory is restored from the saved image.
|
| 1108 | *
|
| 1109 | * If this is successful, control reappears in the restored target kernel in
|
| 1110 | * hibernation_snapshot() which returns to hibernate(). Otherwise, the routine
|
| 1111 | * attempts to recover gracefully and make the kernel return to the normal mode
|
| 1112 | * of operation.
|
| 1113 |
|
| 1114 | static int __init software_resume_initcall(void)
|
| 1115 | {
|
| 1116 | |
| 1117 | * If the user said "noresume".. bail out early.
|
| 1118 |
|
| 1119 | if (noresume || !hibernation_available())
|
| 1120 | return 0;
|
| 1121 |
|
| 1122 | if (!swsusp_resume_device) {
|
| 1123 | int error = find_resume_device();
|
| 1124 |
|
| 1125 | if (error)
|
| 1126 | return error;
|
| 1127 | }
|
| 1128 |
|
| 1129 | return software_resume();
|
| 1130 | }
|
| 1131 | late_initcall_sync(software_resume_initcall);
|
| 1132 |
|
| 1133 |
|
| 1134 | static const char * const hibernation_modes[] = {
|
| 1135 | [HIBERNATION_PLATFORM] = "platform",
|
| 1136 | [HIBERNATION_SHUTDOWN] = "shutdown",
|
| 1137 | [HIBERNATION_REBOOT] = "reboot",
|
| 1138 | #ifdef CONFIG_SUSPEND
|
| 1139 | [HIBERNATION_SUSPEND] = "suspend",
|
| 1140 | #endif
|
| 1141 | [HIBERNATION_TEST_RESUME] = "test_resume",
|
| 1142 | };
|
| 1143 |
|
| 1144 | |
| 1145 | * /sys/power/disk - Control hibernation mode.
|
| 1146 | *
|
| 1147 | * Hibernation can be handled in several ways. There are a few different ways
|
| 1148 | * to put the system into the sleep state: using the platform driver (e.g. ACPI
|
| 1149 | * or other hibernation_ops), powering it off or rebooting it (for testing
|
| 1150 | * mostly).
|
| 1151 | *
|
| 1152 | * The sysfs file /sys/power/disk provides an interface for selecting the
|
| 1153 | * hibernation mode to use. Reading from this file causes the available modes
|
| 1154 | * to be printed. There are 3 modes that can be supported:
|
| 1155 | *
|
| 1156 | * 'platform'
|
| 1157 | * 'shutdown'
|
| 1158 | * 'reboot'
|
| 1159 | *
|
| 1160 | * If a platform hibernation driver is in use, 'platform' will be supported
|
| 1161 | * and will be used by default. Otherwise, 'shutdown' will be used by default.
|
| 1162 | * The selected option (i.e. the one corresponding to the current value of
|
| 1163 | * hibernation_mode) is enclosed by a square bracket.
|
| 1164 | *
|
| 1165 | * To select a given hibernation mode it is necessary to write the mode's
|
| 1166 | * string representation (as returned by reading from /sys/power/disk) back
|
| 1167 | * into /sys/power/disk.
|
| 1168 |
|
| 1169 |
|
| 1170 | static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1171 | char *buf)
|
| 1172 | {
|
| 1173 | ssize_t count = 0;
|
| 1174 | int i;
|
| 1175 |
|
| 1176 | if (!hibernation_available())
|
| 1177 | return sysfs_emit(buf, "[disabled]\n");
|
| 1178 |
|
| 1179 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
|
| 1180 | if (!hibernation_modes[i])
|
| 1181 | continue;
|
| 1182 | switch (i) {
|
| 1183 | case HIBERNATION_SHUTDOWN:
|
| 1184 | case HIBERNATION_REBOOT:
|
| 1185 | #ifdef CONFIG_SUSPEND
|
| 1186 | case HIBERNATION_SUSPEND:
|
| 1187 | #endif
|
| 1188 | case HIBERNATION_TEST_RESUME:
|
| 1189 | break;
|
| 1190 | case HIBERNATION_PLATFORM:
|
| 1191 | if (hibernation_ops)
|
| 1192 | break;
|
| 1193 |
|
| 1194 | continue;
|
| 1195 | }
|
| 1196 | if (i == hibernation_mode)
|
| 1197 | count += sysfs_emit_at(buf, count, "[%s] ", hibernation_modes[i]);
|
| 1198 | else
|
| 1199 | count += sysfs_emit_at(buf, count, "%s ", hibernation_modes[i]);
|
| 1200 | }
|
| 1201 |
|
| 1202 |
|
| 1203 | if (count > 0)
|
| 1204 | buf[count - 1] = '\n';
|
| 1205 |
|
| 1206 | return count;
|
| 1207 | }
|
| 1208 |
|
| 1209 | static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1210 | const char *buf, size_t n)
|
| 1211 | {
|
| 1212 | int mode = HIBERNATION_INVALID;
|
| 1213 | unsigned int sleep_flags;
|
| 1214 | int error = 0;
|
| 1215 | int len;
|
| 1216 | char *p;
|
| 1217 | int i;
|
| 1218 |
|
| 1219 | if (!hibernation_available())
|
| 1220 | return -EPERM;
|
| 1221 |
|
| 1222 | p = memchr(buf, '\n', n);
|
| 1223 | len = p ? p - buf : n;
|
| 1224 |
|
| 1225 | sleep_flags = lock_system_sleep();
|
| 1226 | for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
|
| 1227 | if (len == strlen(hibernation_modes[i])
|
| 1228 | && !strncmp(buf, hibernation_modes[i], len)) {
|
| 1229 | mode = i;
|
| 1230 | break;
|
| 1231 | }
|
| 1232 | }
|
| 1233 | if (mode != HIBERNATION_INVALID) {
|
| 1234 | switch (mode) {
|
| 1235 | case HIBERNATION_SHUTDOWN:
|
| 1236 | case HIBERNATION_REBOOT:
|
| 1237 | #ifdef CONFIG_SUSPEND
|
| 1238 | case HIBERNATION_SUSPEND:
|
| 1239 | #endif
|
| 1240 | case HIBERNATION_TEST_RESUME:
|
| 1241 | hibernation_mode = mode;
|
| 1242 | break;
|
| 1243 | case HIBERNATION_PLATFORM:
|
| 1244 | if (hibernation_ops)
|
| 1245 | hibernation_mode = mode;
|
| 1246 | else
|
| 1247 | error = -EINVAL;
|
| 1248 | }
|
| 1249 | } else
|
| 1250 | error = -EINVAL;
|
| 1251 |
|
| 1252 | if (!error)
|
| 1253 | pm_pr_dbg("Hibernation mode set to '%s'\n",
|
| 1254 | hibernation_modes[mode]);
|
| 1255 | unlock_system_sleep(sleep_flags);
|
| 1256 | return error ? error : n;
|
| 1257 | }
|
| 1258 |
|
| 1259 | power_attr(disk);
|
| 1260 |
|
| 1261 | static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1262 | char *buf)
|
| 1263 | {
|
| 1264 | return sysfs_emit(buf, "%d:%d\n", MAJOR(swsusp_resume_device),
|
| 1265 | MINOR(swsusp_resume_device));
|
| 1266 | }
|
| 1267 |
|
| 1268 | static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1269 | const char *buf, size_t n)
|
| 1270 | {
|
| 1271 | unsigned int sleep_flags;
|
| 1272 | int len = n;
|
| 1273 | char *name;
|
| 1274 | dev_t dev;
|
| 1275 | int error;
|
| 1276 |
|
| 1277 | if (!hibernation_available())
|
| 1278 | return n;
|
| 1279 |
|
| 1280 | if (len && buf[len-1] == '\n')
|
| 1281 | len--;
|
| 1282 | name = kstrndup(buf, len, GFP_KERNEL);
|
| 1283 | if (!name)
|
| 1284 | return -ENOMEM;
|
| 1285 |
|
| 1286 | error = lookup_bdev(name, &dev);
|
| 1287 | if (error) {
|
| 1288 | unsigned maj, min, offset;
|
| 1289 | char *p, dummy;
|
| 1290 |
|
| 1291 | error = 0;
|
| 1292 | if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 ||
|
| 1293 | sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset,
|
| 1294 | &dummy) == 3) {
|
| 1295 | dev = MKDEV(maj, min);
|
| 1296 | if (maj != MAJOR(dev) || min != MINOR(dev))
|
| 1297 | error = -EINVAL;
|
| 1298 | } else {
|
| 1299 | dev = new_decode_dev(simple_strtoul(name, &p, 16));
|
| 1300 | if (*p)
|
| 1301 | error = -EINVAL;
|
| 1302 | }
|
| 1303 | }
|
| 1304 | kfree(name);
|
| 1305 | if (error)
|
| 1306 | return error;
|
| 1307 |
|
| 1308 | sleep_flags = lock_system_sleep();
|
| 1309 | swsusp_resume_device = dev;
|
| 1310 | unlock_system_sleep(sleep_flags);
|
| 1311 |
|
| 1312 | pm_pr_dbg("Configured hibernation resume from disk to %u\n",
|
| 1313 | swsusp_resume_device);
|
| 1314 | noresume = 0;
|
| 1315 | software_resume();
|
| 1316 | return n;
|
| 1317 | }
|
| 1318 |
|
| 1319 | power_attr(resume);
|
| 1320 |
|
| 1321 | static ssize_t resume_offset_show(struct kobject *kobj,
|
| 1322 | struct kobj_attribute *attr, char *buf)
|
| 1323 | {
|
| 1324 | return sysfs_emit(buf, "%llu\n", (unsigned long long)swsusp_resume_block);
|
| 1325 | }
|
| 1326 |
|
| 1327 | static ssize_t resume_offset_store(struct kobject *kobj,
|
| 1328 | struct kobj_attribute *attr, const char *buf,
|
| 1329 | size_t n)
|
| 1330 | {
|
| 1331 | unsigned long long offset;
|
| 1332 | int rc;
|
| 1333 |
|
| 1334 | rc = kstrtoull(buf, 0, &offset);
|
| 1335 | if (rc)
|
| 1336 | return rc;
|
| 1337 | swsusp_resume_block = offset;
|
| 1338 |
|
| 1339 | return n;
|
| 1340 | }
|
| 1341 |
|
| 1342 | power_attr(resume_offset);
|
| 1343 |
|
| 1344 | static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1345 | char *buf)
|
| 1346 | {
|
| 1347 | return sysfs_emit(buf, "%lu\n", image_size);
|
| 1348 | }
|
| 1349 |
|
| 1350 | static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *attr,
|
| 1351 | const char *buf, size_t n)
|
| 1352 | {
|
| 1353 | unsigned long size;
|
| 1354 |
|
| 1355 | if (sscanf(buf, "%lu", &size) == 1) {
|
| 1356 | image_size = size;
|
| 1357 | return n;
|
| 1358 | }
|
| 1359 |
|
| 1360 | return -EINVAL;
|
| 1361 | }
|
| 1362 |
|
| 1363 | power_attr(image_size);
|
| 1364 |
|
| 1365 | static ssize_t reserved_size_show(struct kobject *kobj,
|
| 1366 | struct kobj_attribute *attr, char *buf)
|
| 1367 | {
|
| 1368 | return sysfs_emit(buf, "%lu\n", reserved_size);
|
| 1369 | }
|
| 1370 |
|
| 1371 | static ssize_t reserved_size_store(struct kobject *kobj,
|
| 1372 | struct kobj_attribute *attr,
|
| 1373 | const char *buf, size_t n)
|
| 1374 | {
|
| 1375 | unsigned long size;
|
| 1376 |
|
| 1377 | if (sscanf(buf, "%lu", &size) == 1) {
|
| 1378 | reserved_size = size;
|
| 1379 | return n;
|
| 1380 | }
|
| 1381 |
|
| 1382 | return -EINVAL;
|
| 1383 | }
|
| 1384 |
|
| 1385 | power_attr(reserved_size);
|
| 1386 |
|
| 1387 | static struct attribute *g[] = {
|
| 1388 | &disk_attr.attr,
|
| 1389 | &resume_offset_attr.attr,
|
| 1390 | &resume_attr.attr,
|
| 1391 | &image_size_attr.attr,
|
| 1392 | &reserved_size_attr.attr,
|
| 1393 | NULL,
|
| 1394 | };
|
| 1395 |
|
| 1396 |
|
| 1397 | static const struct attribute_group attr_group = {
|
| 1398 | .attrs = g,
|
| 1399 | };
|
| 1400 |
|
| 1401 |
|
| 1402 | static int __init pm_disk_init(void)
|
| 1403 | {
|
| 1404 | return sysfs_create_group(power_kobj, &attr_group);
|
| 1405 | }
|
| 1406 |
|
| 1407 | core_initcall(pm_disk_init);
|
| 1408 |
|
| 1409 |
|
| 1410 | static int __init resume_setup(char *str)
|
| 1411 | {
|
| 1412 | if (noresume)
|
| 1413 | return 1;
|
| 1414 |
|
| 1415 | strscpy(resume_file, str);
|
| 1416 | return 1;
|
| 1417 | }
|
| 1418 |
|
| 1419 | static int __init resume_offset_setup(char *str)
|
| 1420 | {
|
| 1421 | unsigned long long offset;
|
| 1422 |
|
| 1423 | if (noresume)
|
| 1424 | return 1;
|
| 1425 |
|
| 1426 | if (sscanf(str, "%llu", &offset) == 1)
|
| 1427 | swsusp_resume_block = offset;
|
| 1428 |
|
| 1429 | return 1;
|
| 1430 | }
|
| 1431 |
|
| 1432 | static int __init hibernate_setup(char *str)
|
| 1433 | {
|
| 1434 | if (!strncmp(str, "noresume", 8)) {
|
| 1435 | noresume = 1;
|
| 1436 | } else if (!strncmp(str, "nocompress", 10)) {
|
| 1437 | nocompress = 1;
|
| 1438 | } else if (!strncmp(str, "no", 2)) {
|
| 1439 | noresume = 1;
|
| 1440 | nohibernate = 1;
|
| 1441 | } else if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)
|
| 1442 | && !strncmp(str, "protect_image", 13)) {
|
| 1443 | enable_restore_image_protection();
|
| 1444 | }
|
| 1445 | return 1;
|
| 1446 | }
|
| 1447 |
|
| 1448 | static int __init noresume_setup(char *str)
|
| 1449 | {
|
| 1450 | noresume = 1;
|
| 1451 | return 1;
|
| 1452 | }
|
| 1453 |
|
| 1454 | static int __init resumewait_setup(char *str)
|
| 1455 | {
|
| 1456 | resume_wait = 1;
|
| 1457 | return 1;
|
| 1458 | }
|
| 1459 |
|
| 1460 | static int __init resumedelay_setup(char *str)
|
| 1461 | {
|
| 1462 | int rc = kstrtouint(str, 0, &resume_delay);
|
| 1463 |
|
| 1464 | if (rc)
|
| 1465 | pr_warn("resumedelay: bad option string '%s'\n", str);
|
| 1466 | return 1;
|
| 1467 | }
|
| 1468 |
|
| 1469 | static int __init nohibernate_setup(char *str)
|
| 1470 | {
|
| 1471 | noresume = 1;
|
| 1472 | nohibernate = 1;
|
| 1473 | return 1;
|
| 1474 | }
|
| 1475 |
|
| 1476 | static const char * const comp_alg_enabled[] = {
|
| 1477 | #if IS_ENABLED(CONFIG_CRYPTO_LZO)
|
| 1478 | COMPRESSION_ALGO_LZO,
|
| 1479 | #endif
|
| 1480 | #if IS_ENABLED(CONFIG_CRYPTO_LZ4)
|
| 1481 | COMPRESSION_ALGO_LZ4,
|
| 1482 | #endif
|
| 1483 | };
|
| 1484 |
|
| 1485 | static int hibernate_compressor_param_set(const char *compressor,
|
| 1486 | const struct kernel_param *kp)
|
| 1487 | {
|
| 1488 | int index, ret;
|
| 1489 |
|
| 1490 | if (!mutex_trylock(&system_transition_mutex))
|
| 1491 | return -EBUSY;
|
| 1492 |
|
| 1493 | index = sysfs_match_string(comp_alg_enabled, compressor);
|
| 1494 | if (index >= 0) {
|
| 1495 | ret = param_set_copystring(comp_alg_enabled[index], kp);
|
| 1496 | if (!ret)
|
| 1497 | strscpy(hib_comp_algo, comp_alg_enabled[index]);
|
| 1498 | } else {
|
| 1499 | ret = index;
|
| 1500 | }
|
| 1501 |
|
| 1502 | mutex_unlock(&system_transition_mutex);
|
| 1503 |
|
| 1504 | if (ret)
|
| 1505 | pr_debug("Cannot set specified compressor %s\n",
|
| 1506 | compressor);
|
| 1507 |
|
| 1508 | return ret;
|
| 1509 | }
|
| 1510 |
|
| 1511 | static const struct kernel_param_ops hibernate_compressor_param_ops = {
|
| 1512 | .set = hibernate_compressor_param_set,
|
| 1513 | .get = param_get_string,
|
| 1514 | };
|
| 1515 |
|
| 1516 | static struct kparam_string hibernate_compressor_param_string = {
|
| 1517 | .maxlen = sizeof(hibernate_compressor),
|
| 1518 | .string = hibernate_compressor,
|
| 1519 | };
|
| 1520 |
|
| 1521 | module_param_cb(compressor, &hibernate_compressor_param_ops,
|
| 1522 | &hibernate_compressor_param_string, 0644);
|
| 1523 | MODULE_PARM_DESC(compressor,
|
| 1524 | "Compression algorithm to be used with hibernation");
|
| 1525 |
|
| 1526 | __setup("noresume", noresume_setup);
|
| 1527 | __setup("resume_offset=", resume_offset_setup);
|
| 1528 | __setup("resume=", resume_setup);
|
| 1529 | __setup("hibernate=", hibernate_setup);
|
| 1530 | __setup("resumewait", resumewait_setup);
|
| 1531 | __setup("resumedelay=", resumedelay_setup);
|
| 1532 | __setup("nohibernate", nohibernate_setup);
|