Skip thaw sequence for all devices, not just amdgpu
Subsystems (6)
cover Skip thaw sequence for all devices, not just amdgpu
As part of looking at the hibernate code recently again I was considering whether we really need the thaw stage at all when things are working well.
So I wanted to explore what breaks if we just skip it. This should speed up the S4 sequence since nothing needs to resume.
If we do this we can drop the special cases in amdgpu and the exported symbols too.
Mario Limonciello (3):
PM: hibernate: Nominally skip thaw sequence for all devices drm/amd: Drop special cases for thaw() callback
PM: Drop pm_hibernate_is_recovering() and
pm_hibernation_mode_is_suspend()
drivers/base/power/main.c | 20 ++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ---- include/linux/suspend.h | 8 -------- kernel/power/hibernate.c | 24 ++++++++++-------------- kernel/power/user.c | 3 +++ 5 files changed, 19 insertions(+), 40 deletions(-)
Signature · 1 line
2.43.0
RFC PATCH 1/3 PM: hibernate: Nominally skip thaw sequence for all devices
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.
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.
--- drivers/base/power/main.c | 6 ++++++ kernel/power/hibernate.c | 13 ++++++++++--- kernel/power/user.c | 3 +++ 3 files changed, 19 insertions(+), 3 deletions(-)
drivers/base/power/main.c +6 -0
@@ -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);
kernel/power/hibernate.c +10 -3
@@ -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;
kernel/power/user.c +3 -0
@@ -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;
Signature · 1 line
2.43.0
Rafael J. Wysocki
maintainerRe: [RFC PATCH 1/3] PM: hibernate: Nominally skip thaw sequence for all devices
Quoted 7 lines · Mario Limonciello (AMD)
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.
Quoted 89 lines
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_INVALIDinhibernation_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(-)drivers/base/power/main.c +6
-0@@ -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);kernel/power/hibernate.c +10
-3@@ -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;kernel/power/user.c +3
-1@@ -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
Re: [RFC PATCH 1/3] PM: hibernate: Nominally skip thaw sequence for all devices
Quoted 5 lines · Rafael J. Wysocki
Quoted 3 lines · Mario Limonciello (AMD)
From: Mario Limonciello <[email protected]>
Quoted 8 lines
Quoted 4 lines
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.
Ah; right.
I suppose one option would be to thaw "just" the backing device, but this could turn into a relatively complex mess because it would have relationships (parent/child or device link) to other devices that need to thaw too then.
Quoted 90 lines
Quoted 90 lines
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_INVALIDinhibernation_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(-)drivers/base/power/main.c +6
-0@@ -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);kernel/power/hibernate.c +10
-3@@ -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;kernel/power/user.c +3
-1@@ -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
Rafael J. Wysocki
maintainerRe: [RFC PATCH 1/3] PM: hibernate: Nominally skip thaw sequence for all devices
Quoted 14 lines · Mario Limonciello
Quoted 12 lines · Rafael J. Wysocki
Quoted 7 lines · Mario Limonciello (AMD)
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?
Quoted 8 lines
Quoted 1 line
It is only in memory when the "thaw" callbacks are invoked.
Ah; right.
I suppose one option would be to thaw "just" the backing device, but this could turn into a relatively complex mess because it would have relationships (parent/child or device link) to other devices that need to thaw too then.
Right and that's exactly why everything is thawed.
RFC PATCH 2/3 drm/amd: Drop special cases for thaw() callback
In reply to Mario Limonciello (AMD)From: Mario Limonciello <[email protected]>
The special cases to use pm_hibernate_is_recovering() and pm_hibernation_mode_is_suspend() were for an optimization to avoid turning the display on and moving memory around when the system was about to hibernate anyway.
As the hibernate core skips thaw() unless it's necessary drop them.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +0 -4
@@ -2671,10 +2671,6 @@ static int amdgpu_pmops_thaw(struct device *dev) {struct drm_device *drm_dev =dev_get_drvdata (dev); -/* do not resume device if it's normal hibernation */ -if (!pm_hibernate_is_recovering () && !pm_hibernation_mode_is_suspend ()) -return 0 ; -return amdgpu_device_resume (drm_dev, true); }
Signature · 1 line
2.43.0
RFC PATCH 3/3 PM: Drop pm_hibernate_is_recovering() and pm_hibernation_mode_is_suspend()
In reply to Mario Limonciello (AMD)From: Mario Limonciello <[email protected]>
All consumers in the kernel of pm_hibernate_is_recovering() and pm_hibernation_mode_is_suspend() have been dropped. Remove the symbols.
--- drivers/base/power/main.c | 14 -------------- include/linux/suspend.h | 8 -------- kernel/power/hibernate.c | 11 ----------- 3 files changed, 33 deletions(-)
drivers/base/power/main.c +0 -14
@@ -62,20 +62,6 @@ static pm_message_t pm_transition;static DEFINE_MUTEX (async_wip_mtx);static int async_error; -/** -* pm_hibernate_is_recovering - if recovering from hibernate due to error. -* -* Used to query if dev_pm_ops.thaw() is called for normal hibernation case or -* recovering from some error. -* -* Return: true for error case, false for normal case. -*/ -bool pm_hibernate_is_recovering (void ) -{ -return pm_transition.event ==PM_EVENT_RECOVER ; -} -EXPORT_SYMBOL_GPL (pm_hibernate_is_recovering); -static const char *pm_verb (int event) {switch (event) {
include/linux/suspend.h +0 -8
@@ -420,12 +420,6 @@ static inline int hibernate_quiet_exec(int (*func)(void *data), void *data) { }#endif /* CONFIG_HIBERNATION */ -#if defined(CONFIG_HIBERNATION ) && defined(CONFIG_SUSPEND ) -bool pm_hibernation_mode_is_suspend (void ); -#else -static inline bool pm_hibernation_mode_is_suspend (void ) {return false; } -#endif -int arch_resume_nosmt (void );#ifdef CONFIG_HIBERNATION_SNAPSHOT_DEV
@@ -486,7 +480,6 @@ extern unsigned int lock_system_sleep(void);extern void unlock_system_sleep (unsigned int );extern bool pm_sleep_transition_in_progress (void ); -bool pm_hibernate_is_recovering (void );#else /* !CONFIG_PM_SLEEP */
@@ -520,7 +513,6 @@ static inline unsigned int lock_system_sleep(void) { return 0; }static inline void unlock_system_sleep (unsigned int flags) {}static inline bool pm_sleep_transition_in_progress (void ) {return false; } -static inline bool pm_hibernate_is_recovering (void ) {return false; }#endif /* !CONFIG_PM_SLEEP */
kernel/power/hibernate.c +0 -11
@@ -80,17 +80,6 @@ static const struct platform_hibernation_ops *hibernation_ops;static atomic_t hibernate_atomic =ATOMIC_INIT (1 ); -#ifdef CONFIG_SUSPEND -/** -* pm_hibernation_mode_is_suspend - Check if hibernation has been set to suspend -*/ -bool pm_hibernation_mode_is_suspend (void ) -{ -return hibernation_mode ==HIBERNATION_SUSPEND ; -} -EXPORT_SYMBOL_GPL (pm_hibernation_mode_is_suspend); -#endif -bool hibernate_acquire (void ) {return atomic_add_unless (&hibernate_atomic,-1 ,0 );
Signature · 1 line
2.43.0