diff options
author | 2020-10-15 20:37:01 +0200 | |
---|---|---|
committer | 2020-10-15 20:37:01 +0200 | |
commit | 62b31a045757eac81fed94b19df47418a0818528 (patch) | |
tree | 285fda56df8304dff6ba929bad65ddfb4e4fd726 /kernel/power/hibernate.c | |
parent | Merge branch 'for-5.10/apple' into for-linus (diff) | |
parent | HID: hid-debug: fix nonblocking read semantics wrt EIO/ERESTARTSYS (diff) | |
download | wireguard-linux-62b31a045757eac81fed94b19df47418a0818528.tar.xz wireguard-linux-62b31a045757eac81fed94b19df47418a0818528.zip |
Merge branch 'for-5.10/core' into for-linus
- nonblocking read semantics fix for hid-debug
Diffstat (limited to '')
-rw-r--r-- | kernel/power/hibernate.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 5714f51ba9f8..e7aa57fb2fdc 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -659,7 +659,7 @@ static void power_down(void) break; case HIBERNATION_PLATFORM: hibernation_platform_enter(); - /* Fall through */ + fallthrough; case HIBERNATION_SHUTDOWN: if (pm_power_off) kernel_power_off(); @@ -795,6 +795,103 @@ int hibernate(void) return error; } +/** + * hibernate_quiet_exec - Execute a function with all devices frozen. + * @func: Function to execute. + * @data: Data pointer to pass to @func. + * + * Return the @func return value or an error code if it cannot be executed. + */ +int hibernate_quiet_exec(int (*func)(void *data), void *data) +{ + int error, nr_calls = 0; + + lock_system_sleep(); + + if (!hibernate_acquire()) { + error = -EBUSY; + goto unlock; + } + + pm_prepare_console(); + + error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls); + if (error) { + nr_calls--; + goto exit; + } + + error = freeze_processes(); + if (error) + goto exit; + + lock_device_hotplug(); + + pm_suspend_clear_flags(); + + error = platform_begin(true); + if (error) + goto thaw; + + error = freeze_kernel_threads(); + if (error) + goto thaw; + + error = dpm_prepare(PMSG_FREEZE); + if (error) + goto dpm_complete; + + suspend_console(); + + error = dpm_suspend(PMSG_FREEZE); + if (error) + goto dpm_resume; + + error = dpm_suspend_end(PMSG_FREEZE); + if (error) + goto dpm_resume; + + error = platform_pre_snapshot(true); + if (error) + goto skip; + + error = func(data); + +skip: + platform_finish(true); + + dpm_resume_start(PMSG_THAW); + +dpm_resume: + dpm_resume(PMSG_THAW); + + resume_console(); + +dpm_complete: + dpm_complete(PMSG_THAW); + + thaw_kernel_threads(); + +thaw: + platform_end(true); + + unlock_device_hotplug(); + + thaw_processes(); + +exit: + __pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL); + + pm_restore_console(); + + hibernate_release(); + +unlock: + unlock_system_sleep(); + + return error; +} +EXPORT_SYMBOL_GPL(hibernate_quiet_exec); /** * software_resume - Resume from a saved hibernation image. |