/** * toi_end_atomic - post atomic copy/restore routines * @stage: What step to start at. * @suspend_time: Whether we're suspending or resuming. * @error: Whether we're recovering from an error. **/ void toi_end_atomic(int stage, int suspend_time, int error) { pm_message_t msg = suspend_time ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE; switch (stage) { case ATOMIC_ALL_STEPS: if (!suspend_time) { events_check_enabled = false; platform_leave(1); } case ATOMIC_STEP_SYSCORE_RESUME: syscore_resume(); case ATOMIC_STEP_IRQS: local_irq_enable(); case ATOMIC_STEP_CPU_HOTPLUG: if (test_action_state(TOI_LATE_CPU_HOTPLUG)) enable_nonboot_cpus(); case ATOMIC_STEP_PLATFORM_FINISH: if (!suspend_time && error & 2) platform_restore_cleanup(1); else platform_finish(1); dpm_resume_start(msg); case ATOMIC_STEP_DEVICE_RESUME: if (suspend_time && (error & 2)) platform_recover(1); dpm_resume(msg); if (error || !toi_in_suspend()) pm_restore_gfp_mask(); ftrace_start(); resume_console(); case ATOMIC_STEP_DPM_COMPLETE: dpm_complete(msg); case ATOMIC_STEP_PLATFORM_END: platform_end(1); toi_prepare_status(DONT_CLEAR_BAR, "Post atomic."); } }
int hibernation_restore(int platform_mode) { int error; pm_prepare_console(); suspend_console(); error = device_suspend(PMSG_QUIESCE); if (error) goto Finish; error = platform_pre_restore(platform_mode); if (!error) { error = disable_nonboot_cpus(); if (!error) error = resume_target_kernel(); enable_nonboot_cpus(); } platform_restore_cleanup(platform_mode); device_resume(PMSG_RECOVER); Finish: resume_console(); pm_restore_console(); return error; }
int hibernation_restore(int platform_mode) { int error; pm_prepare_console(); suspend_console(); error = device_suspend(PMSG_PRETHAW); if (error) goto Finish; error = platform_pre_restore(platform_mode); if (!error) { error = disable_nonboot_cpus(); if (!error) error = swsusp_resume(); enable_nonboot_cpus(); } platform_restore_cleanup(platform_mode); device_resume(); Finish: resume_console(); pm_restore_console(); return error; }
/** * resume_target_kernel - Restore system state from a hibernation image. * @platform_mode: Whether or not to use the platform driver. * * Execute device drivers' "noirq" and "late" freeze callbacks, restore the * contents of highmem that have not been restored yet from the image and run * the low-level code that will restore the remaining contents of memory and * switch to the just restored target kernel. */ static int resume_target_kernel(bool platform_mode) { int error; error = dpm_suspend_end(PMSG_QUIESCE); if (error) { pr_err("Some devices failed to power down, aborting resume\n"); return error; } error = platform_pre_restore(platform_mode); if (error) goto Cleanup; error = hibernate_resume_nonboot_cpu_disable(); if (error) goto Enable_cpus; local_irq_disable(); error = syscore_suspend(); if (error) goto Enable_irqs; save_processor_state(); error = restore_highmem(); if (!error) { error = swsusp_arch_resume(); /* * The code below is only ever reached in case of a failure. * Otherwise, execution continues at the place where * swsusp_arch_suspend() was called. */ BUG_ON(!error); /* * This call to restore_highmem() reverts the changes made by * the previous one. */ restore_highmem(); } /* * The only reason why swsusp_arch_resume() can fail is memory being * very tight, so we have to free it as soon as we can to avoid * subsequent failures. */ swsusp_free(); restore_processor_state(); touch_softlockup_watchdog(); syscore_resume(); Enable_irqs: local_irq_enable(); Enable_cpus: enable_nonboot_cpus(); Cleanup: platform_restore_cleanup(platform_mode); dpm_resume_start(PMSG_RECOVER); return error; }
static int resume_target_kernel(bool platform_mode) { int error; error = dpm_suspend_noirq(PMSG_QUIESCE); if (error) { printk(KERN_ERR "PM: Some devices failed to power down, " "aborting resume\n"); return error; } error = platform_pre_restore(platform_mode); if (error) goto Cleanup; error = disable_nonboot_cpus(); if (error) goto Enable_cpus; local_irq_disable(); error = sysdev_suspend(PMSG_QUIESCE); if (error) goto Enable_irqs; /* We'll ignore saved state, but this gets preempt count (etc) right */ save_processor_state(); error = restore_highmem(); if (!error) { error = swsusp_arch_resume(); /* * The code below is only ever reached in case of a failure. * Otherwise execution continues at place where * swsusp_arch_suspend() was called */ BUG_ON(!error); /* This call to restore_highmem() undos the previous one */ restore_highmem(); } /* * The only reason why swsusp_arch_resume() can fail is memory being * very tight, so we have to free it as soon as we can to avoid * subsequent failures */ swsusp_free(); restore_processor_state(); touch_softlockup_watchdog(); sysdev_resume(); Enable_irqs: local_irq_enable(); Enable_cpus: enable_nonboot_cpus(); Cleanup: platform_restore_cleanup(platform_mode); dpm_resume_noirq(PMSG_RECOVER); return error; }