Christoph Rudorff
2025-Mar-26  14:02 UTC
[PATCH BACKPORT v3] drm/nouveau: fix hibernate on disabled GPU
Hibernate bricks the machine if a discrete GPU was disabled via
echo IGD > /sys/kernel/debug/vgaswitcheroo/switch
The freeze and thaw handler lacks checking the GPU power state,
as suspend and resume do.
This patch add the checks and fix this issue.
This is a backport and applies to v6.6 and below.
Signed-off-by: Christoph Rudorff <chris at rudorff.com>
---
I got an old MacBook having a defective nvidia GPU
So I put this in the initrd scripts to turn it off asap:
mount -t debugfs none /sys/kernel/debug
echo IGD > /sys/kernel/debug/vgaswitcheroo/switch
which powers down the nouveau.
Suspend and resume works,
but hibernate locks up the machine.
The handlers are not checking the GPU state.
This is a good candidate for backport.
This patch applies to v6.6 and below
---
Changes in v3:
- Backport for v6.6 and below
- Link to v2:
https://lore.kernel.org/r/20250325-nouveau-fix-hibernate-v2-1-2bd5c13fb953 at
rudorff.com
Changes in v2:
- EDITME: use my real name, my nick raised bugs
- Link to v1:
https://lore.kernel.org/r/20250304-nouveau-fix-hibernate-v1-1-ee4433546030 at
rudorff.com
---
 drivers/gpu/drm/nouveau/nouveau_drm.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c
b/drivers/gpu/drm/nouveau/nouveau_drm.c
index
ac15a662e06042e2c133da9c17fcd53000a98650..a05151b557dac6860e07fe7147aa81b7b15e6f4b
100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -1026,6 +1026,11 @@ nouveau_pmops_freeze(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF ||
+	    drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF)
+		return 0;
+
 	return nouveau_do_suspend(drm_dev, false);
 }
 
@@ -1034,6 +1039,11 @@ nouveau_pmops_thaw(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF ||
+	    drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF)
+		return 0;
+
 	return nouveau_do_resume(drm_dev, false);
 }
 
---
base-commit: 4b6a8fa777d29785c7ddb51dcbb2b5411deefaca
change-id: 20250304-nouveau-fix-hibernate-249826d427bb
Best regards,
-- 
Christoph Rudorff <chris at rudorff.com>