Skip to contentSkip to conversation

drm/amdgpu: skip the noirq suspend reset for a switcheroo-parked GPU

PATCH Applied Theo Andersen Carton 2 participants 2 messages Sep 17 – Sep 21

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/amdgpu: skip the noirq suspend reset for a switcheroo-parked GPU

amdgpu_pmops_suspend_noirq() resets the ASIC unconditionally. When the GPU has been parked by vga_switcheroo it has neither power nor a PCIe link, so the reset cannot reach it: pci_set_power_state() reports the device as inaccessible and amdgpu_asic_reset() returns -EINVAL. A failure there aborts the entire noirq suspend phase, and with it the system suspend, so the machine cannot sleep at all while the GPU is switched off.

amdgpu_device_prepare(), amdgpu_device_suspend() and amdgpu_device_resume() all bail out early on DRM_SWITCH_POWER_OFF. This callback was added later, for an unrelated reason, and did not inherit the check. nouveau guards every one of its PM callbacks the same way.

Bail out the same way here. On a single-GPU system switch_power_state is never DRM_SWITCH_POWER_OFF, so this is a no-op there.

Found on a MacBookPro11,5, where the Radeon is powered down through apple-gmux so that the internal panel can be driven by the iGPU instead. Every suspend failed in amdgpu_pmops_suspend_noirq() while the card was off; with this check a full S3 cycle completes.

Fixes 9e051720f9d3 ("drm/amdgpu: Ensure HDA function is suspended before ASIC reset")
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +8 -0
index 5c33c19fd9bc..d9d794a7db96 100644
@@ -2664,6 +2664,14 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev)
 	struct amdgpu_device *adev = drm_to_adev(drm_dev);
 	int r;
 
+	/*
+	 * A GPU parked by vga_switcheroo has no power and no PCIe link, so the
+	 * ASIC reset below would fail and abort the whole noirq suspend phase.
+	 * Bail out like amdgpu_device_prepare/suspend/resume() already do.
+	 */
+	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+		return 0;
+
 	if (amdgpu_acpi_should_gpu_reset(adev)) {
 		amdgpu_device_lock_reset_domain(adev->reset_domain);
 		r = amdgpu_asic_reset(adev);

base-commit: 50d05c7c76c96b90462f24debacca971d2e86713

Signature · 1 line
2.55.0
maintainer Applied
#1 lore raw

Public

Applied. Thanks!

Quoted 67 lines

-----Original Message-----
From: Theo Andersen Carton <[email protected]>
Sent: Thursday, September 17, 2026 3:15 PM
To: Deucher, Alexander <[email protected]>; Koenig, Christian <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; amd- [email protected]; [email protected]; linux- [email protected]; Theo Andersen Carton <[email protected]>; [email protected]
Subject: [PATCH] drm/amdgpu: skip the noirq suspend reset for a switcheroo- parked GPU

amdgpu_pmops_suspend_noirq() resets the ASIC unconditionally. When the GPU has been parked by vga_switcheroo it has neither power nor a PCIe link, so the reset cannot reach it: pci_set_power_state() reports the device as inaccessible and amdgpu_asic_reset() returns -EINVAL. A failure there aborts the entire noirq suspend phase, and with it the system suspend, so the machine cannot sleep at all while the GPU is switched off.

amdgpu_device_prepare(), amdgpu_device_suspend() and amdgpu_device_resume() all bail out early on DRM_SWITCH_POWER_OFF. This callback was added later, for an unrelated reason, and did not inherit the check. nouveau guards every one of its PM callbacks the same way.

Bail out the same way here. On a single-GPU system switch_power_state is never DRM_SWITCH_POWER_OFF, so this is a no-op there.

Found on a MacBookPro11,5, where the Radeon is powered down through apple-gmux so that the internal panel can be driven by the iGPU instead. Every suspend failed in amdgpu_pmops_suspend_noirq() while the card was off; with this check a full S3 cycle completes.

Fixes 9e051720f9d3 ("drm/amdgpu: Ensure HDA function is suspended

before ASIC reset")

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2 -0
index 5c33c19fd9bc..d9d794a7db96 100644
@@ -2664,6 +2664,14 @@ static int amdgpu_pmops_suspend_noirq(struct
 device *dev)
      struct amdgpu_device *adev = drm_to_adev(drm_dev);
      int r;
 
+     /*
+      * A GPU parked by vga_switcheroo has no power and no PCIe link, so

the
+ * ASIC reset below would fail and abort the whole noirq suspend
phase.

drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +5 -0
+      * Bail out like amdgpu_device_prepare/suspend/resume() already do.
+      */
+     if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+             return 0;
+
      if (amdgpu_acpi_should_gpu_reset(adev)) {
              amdgpu_device_lock_reset_domain(adev->reset_domain);
              r = amdgpu_asic_reset(adev);

base-commit: 50d05c7c76c96b90462f24debacca971d2e86713 --
2.55.0