Fixes for hybrid sleep
Subsystems (4)
v3 cover Fixes for hybrid sleep
From: Mario Limonciello <[email protected]>
Ionut Nechita reported recently a hibernate failure, but in debugging the issue it's actually not a hibernate failure; but a hybrid sleep failure.
Multiple changes related to the change of when swap is disabled in the suspend sequence contribute to the failure. See the individual patches for details.
As it touches two subsystems it either needs to go through linux-pm or drm. Patch 3 has an Ack from Alex, this should merge through linux-pm.
---
v3:
* Push all calls for gfp mask changes into power_down()
Mario Limonciello (AMD) (3):
PM: hibernate: Fix hybrid-sleep
PM: hibernate: Add pm_hibernation_mode_is_suspend() drm/amd: Fix hybrid sleep
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- include/linux/suspend.h | 2 ++ kernel/power/hibernate.c | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-)
Signature · 1 line
2.51.0
PATCH v3 1/3 PM: hibernate: Fix hybrid-sleep
Hybrid sleep will hibernate the system followed by running through the suspend routine. Since both the hibernate and the suspend routine will call pm_restrict_gfp_mask(), pm_restore_gfp_mask() must be called before starting the suspend sequence.
Add an explicit call to pm_restore_gfp_mask() to power_down() before the suspend sequence starts. Add an extra call for pm_restrict_gfp_mask() when exiting suspend so that the pm_restore_gfp_mask() call in hibernate() is balanced.
--- kernel/power/hibernate.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/power/hibernate.c +3 -0
@@ -695,12 +695,15 @@ static void power_down(void)#ifdef CONFIG_SUSPEND if (hibernation_mode ==HIBERNATION_SUSPEND ) { +pm_restore_gfp_mask (); error =suspend_devices_and_enter (mem_sleep_current);if (error) { hibernation_mode = hibernation_ops ?HIBERNATION_PLATFORM :HIBERNATION_SHUTDOWN ; }else { +pm_restrict_gfp_mask (); +/* Restore swap signature. */ error =swsusp_unmark ();if (error)
Signature · 1 line
2.51.0
PATCH v3 2/3 PM: hibernate: Add pm_hibernation_mode_is_suspend()
In reply to Mario Limonciello (AMD)Some drivers have different flows for hibernation and suspend. If the driver opportunistically will skip thaw() then it needs a hint to know what is happening after the hibernate.
Introduce a new symbol pm_hibernation_mode_is_suspend() that drivers can call to determine if suspending the system for this purpose.
--- include/linux/suspend.h | 2 ++ kernel/power/hibernate.c | 11 +++++++++++ 2 files changed, 13 insertions(+)
include/linux/suspend.h +2 -0
@@ -276,6 +276,7 @@ extern void arch_suspend_enable_irqs(void);extern int pm_suspend (suspend_state_t state);extern bool sync_on_suspend_enabled; +bool pm_hibernation_mode_is_suspend (void );#else /* !CONFIG_SUSPEND */ #define suspend_valid_only_mem NULL
@@ -288,6 +289,7 @@ static inline bool pm_suspend_via_firmware(void) { return false; }static inline bool pm_resume_via_firmware (void ) {return false; }static inline bool pm_suspend_no_platform (void ) {return false; }static inline bool pm_suspend_default_s2idle (void ) {return false; } +static inline bool pm_hibernation_mode_is_suspend (void ) {return false; }static inline void suspend_set_ops (const struct platform_suspend_ops *ops) {}static inline int pm_suspend (suspend_state_t state) {return -ENOSYS ; }
kernel/power/hibernate.c +11 -0
@@ -80,6 +80,17 @@ 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.51.0
PATCH v3 3/3 drm/amd: Fix hybrid sleep
In reply to Mario Limonciello (AMD)[Why]
commit 530694f54dd5e ("drm/amdgpu: do not resume device in thaw for normal hibernation") optimized the flow for systems that are going into S4 where the power would be turned off. Basically the thaw() callback wouldn't resume the device if the hibernation image was successfully created since the system would be powered off.
This however isn't the correct flow for a system entering into s0i3 after the hibernation image is created. Some of the amdgpu callbacks have different behavior depending upon the intended state of the suspend.
[How]
Use pm_hibernation_mode_is_suspend() as an input to decide whether to run resume during thaw() callback.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +1 -1
@@ -2665,7 +2665,7 @@ 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 ()) +if (!pm_hibernate_is_recovering () && !pm_hibernation_mode_is_suspend ())return 0 ;return amdgpu_device_resume (drm_dev, true);
Signature · 1 line
2.51.0
Rafael J. Wysocki
maintainerQuoted 24 lines · Mario Limonciello (AMD)
From: Mario Limonciello <[email protected]>
Ionut Nechita reported recently a hibernate failure, but in debugging the issue it's actually not a hibernate failure; but a hybrid sleep failure.
Multiple changes related to the change of when swap is disabled in the suspend sequence contribute to the failure. See the individual patches for details.
As it touches two subsystems it either needs to go through linux-pm or drm. Patch 3 has an Ack from Alex, this should merge through linux-pm.
---
v3:
* Push all calls for gfp mask changes intopower_down()
Mario Limonciello (AMD) (3):
PM: hibernate: Fix hybrid-sleep
PM: hibernate: Addpm_hibernation_mode_is_suspend()drm/amd: Fix hybrid sleep
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- include/linux/suspend.h | 2 ++ kernel/power/hibernate.c | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-)--
All applied as 6.18 material, thanks!