On Mon, Oct 13, 2025 at 7:48 PM Mario Limonciello (AMD)
<[email protected]> wrote:
>
> From: Mario Limonciello <[email protected]>
>
> After the hibernation snapshot is created all devices will have
> their thaw() callback called before the next stage.  For the most
> common scenarios of hibernation this is not necessary because the
> device will be powered off anyway.

And how exactly is the image going to be saved?

It is only in memory when the "thaw" callbacks are invoked.

> If the hibernation snapshot was successfully created skip thawing
> devices until it's needed for userspace created hibernation image
> or hybrid sleep. To accomplish this use PMSG_INVALID in
> hibernation_snapshot() and set the dpm functions to skip running.
>
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
>  drivers/base/power/main.c |  6 ++++++
>  kernel/power/hibernate.c  | 13 ++++++++++---
>  kernel/power/user.c       |  3 +++
>  3 files changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
> index 8179fd53171dc..58f5270a173e8 100644
> --- a/drivers/base/power/main.c
> +++ b/drivers/base/power/main.c
> @@ -1143,6 +1143,9 @@ void dpm_resume(pm_message_t state)
>         struct device *dev;
>         ktime_t starttime = ktime_get();
>
> +       if (state.event == PM_EVENT_INVALID)
> +               return;
> +
>         trace_suspend_resume(TPS("dpm_resume"), state.event, true);
>
>         pm_transition = state;
> @@ -1245,6 +1248,9 @@ void dpm_complete(pm_message_t state)
>  {
>         struct list_head list;
>
> +       if (state.event == PM_EVENT_INVALID)
> +               return;
> +
>         trace_suspend_resume(TPS("dpm_complete"), state.event, true);
>
>         INIT_LIST_HEAD(&list);
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index aadf82f57e868..7af2e392c574a 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -480,13 +480,14 @@ int hibernation_snapshot(int platform_mode)
>         if (error || !in_suspend)
>                 swsusp_free();
>
> -       msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE;
> +       msg = in_suspend ? (error ? PMSG_RECOVER : PMSG_INVALID) : 
> PMSG_RESTORE;
>         dpm_resume(msg);
>
> -       if (error || !in_suspend)
> +       if (error || !in_suspend) {
>                 pm_restore_gfp_mask();
> +               console_resume_all();
> +       }
>
> -       console_resume_all();
>         dpm_complete(msg);
>
>   Close:
> @@ -707,7 +708,13 @@ static void power_down(void)
>
>  #ifdef CONFIG_SUSPEND
>         if (hibernation_mode == HIBERNATION_SUSPEND) {
> +               /* recover from hibernation_snapshot() */
> +               dpm_resume(PMSG_THAW);
> +               console_resume_all();
> +               dpm_complete(PMSG_THAW);
>                 pm_restore_gfp_mask();
> +
> +               /* run suspend sequence */
>                 error = suspend_devices_and_enter(mem_sleep_current);
>                 if (!error)
>                         goto exit;
> diff --git a/kernel/power/user.c b/kernel/power/user.c
> index 3f9e3efb9f6e7..d70c963b1ba88 100644
> --- a/kernel/power/user.c
> +++ b/kernel/power/user.c
> @@ -310,6 +310,9 @@ static long snapshot_ioctl(struct file *filp, unsigned 
> int cmd,
>                 pm_restore_gfp_mask();
>                 error = hibernation_snapshot(data->platform_support);
>                 if (!error) {
> +                       dpm_resume(PMSG_THAW);
> +                       console_resume_all();
> +                       dpm_complete(PMSG_THAW);
>                         error = put_user(in_suspend, (int __user *)arg);
>                         data->ready = !freezer_test_done && !error;
>                         freezer_test_done = false;
> --
> 2.43.0
>

Reply via email to