All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] drm/amd/pm: Fix SMU messages after system resume for smu 11.0.x
@ 2026-08-18  4:20 Yang Wang
  2026-08-18  7:41 ` Feng, Kenneth
  0 siblings, 1 reply; 2+ messages in thread
From: Yang Wang @ 2026-08-18  4:20 UTC (permalink / raw)
  To: amd-gfx; +Cc: alexander.deucher, hawking.zhang, kenneth.feng

SMU 11.0.x can retain an unfinished command across system
suspend, causing SMU messages such as RunDcBtc to fail during resume.

The original failure path is:

amdgpu_pmops_resume()
`-- amdgpu_device_resume()
    `-- amdgpu_device_ip_resume()
        `-- smu_resume()
            `-- smu_smc_hw_setup()
                `-- smu_run_btc()
                    `-- RunDcBtc fails

v1:
- Prepare MP1 for unload for an active system suspend.
- Restore PMFW context after the normal PSP resume load. The initial
  centralized load preserves PMFW-before-TMR ordering; a successful MP1
  unload additionally requires the post-TMR context reload.

v2:
- Snapshot the runtime PM state at system-suspend entry.
- Exclude runtime-suspended BACO entries from the MP1 unload and PMFW
  recovery transaction.
- Mark the successful MP1 unload in PSP to order the post-TMR reload.

Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5620
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h       |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   | 11 ++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c   | 11 +++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h   |  2 ++
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 40 ++++++++++++++++++++---
 5 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 070986b03fb8..71606dd2d6fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -860,6 +860,8 @@ struct amdgpu_device {
 
 	/* s3/s4 mask */
 	bool                            in_suspend;
+	/* runtime PM state snapshot at system-suspend entry */
+	bool				in_runpm_at_suspend;
 	bool				in_s3;
 	bool				in_s4;
 	bool				in_s0ix;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 845160d2c516..8c7df6b4e168 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2803,10 +2803,15 @@ static int amdgpu_pmops_prepare(struct device *dev)
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 	struct amdgpu_device *adev = drm_to_adev(drm_dev);
 
+	adev->in_runpm_at_suspend = false;
+
 	/* device maybe not resumed here, return immediately in this case */
 	if (adev->in_s4 && adev->in_suspend)
 		return 0;
 
+	/* System PM can change runtime PM state after this callback. */
+	adev->in_runpm_at_suspend = pm_runtime_suspended(dev);
+
 	/* Return a positive number here so
 	 * DPM_FLAG_SMART_SUSPEND works properly
 	 */
@@ -2825,7 +2830,11 @@ static int amdgpu_pmops_prepare(struct device *dev)
 
 static void amdgpu_pmops_complete(struct device *dev)
 {
-	amdgpu_device_complete(dev_get_drvdata(dev));
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	struct amdgpu_device *adev = drm_to_adev(drm_dev);
+
+	amdgpu_device_complete(drm_dev);
+	adev->in_runpm_at_suspend = false;
 }
 
 static int amdgpu_pmops_suspend(struct device *dev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 04f6ebf31cca..e252733a6f3b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -3512,11 +3512,18 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
 	struct amdgpu_firmware_info *ucode;
 	struct amdgpu_device *adev = psp->adev;
 
-	if (psp->autoload_supported &&
-	    !psp->pmfw_centralized_cstate_management) {
+	/*
+	 * NOTE: The centralized PMFW load in psp_hw_start() must precede
+	 * TMR setup. A successful MP1 unload also requires PMFW context
+	 * recovery after TMR, so reload it for this transaction here.
+	 */
+	if (psp->smu_fw_post_tmr_reload ||
+	    (psp->autoload_supported &&
+	     !psp->pmfw_centralized_cstate_management)) {
 		ret = psp_load_smu_fw(psp);
 		if (ret)
 			return ret;
+		psp->smu_fw_post_tmr_reload = false;
 	}
 
 	/* Load P2S table first if it's available */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index d80c85793e3b..540077b9f070 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -443,6 +443,8 @@ struct psp_context {
 	bool				boot_time_tmr;
 	/* flag to mark whether df cstate management centralized to PMFW */
 	bool				pmfw_centralized_cstate_management;
+	/* SMC firmware reload required after TMR during system resume */
+	bool				smu_fw_post_tmr_reload;
 
 	/* xgmi ta firmware and buffer */
 	const struct firmware		*ta_fw;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 559afdc5815d..8ff1cb1efc5b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -2182,12 +2182,38 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
 static int smu_reset_mp1_state(struct smu_context *smu)
 {
 	struct amdgpu_device *adev = smu->adev;
-	int ret = 0;
+	u32 mp1_version = amdgpu_ip_version(adev, MP1_HWIP, 0);
+	bool needs_mp1_unload;
+	int ret;
 
-	if ((!adev->in_runpm) && (!adev->in_suspend) &&
-		(!amdgpu_in_reset(adev)) && !smu->is_apu &&
-			amdgpu_ip_version(adev, MP1_HWIP, 0) >= IP_VERSION(13, 0, 0))
-		ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD);
+	if (adev->in_runpm || amdgpu_in_reset(adev) || smu->is_apu)
+		return 0;
+
+	switch (mp1_version) {
+	case IP_VERSION(11, 0, 7):
+	case IP_VERSION(11, 0, 11):
+	case IP_VERSION(11, 0, 12):
+	case IP_VERSION(11, 0, 13):
+		/*
+		 * Prepare MP1 only for an active system-suspend entry.
+		 * BACO retains the SMU firmware across runtime suspend.
+		 */
+		needs_mp1_unload = adev->in_suspend &&
+			!adev->in_runpm_at_suspend &&
+			adev->mp1_state != PP_MP1_STATE_UNLOAD;
+		break;
+	default:
+		needs_mp1_unload = !adev->in_suspend &&
+			mp1_version >= IP_VERSION(13, 0, 0);
+		break;
+	}
+
+	if (!needs_mp1_unload)
+		return 0;
+
+	ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD);
+	if (!ret && adev->in_suspend)
+		adev->psp.smu_fw_post_tmr_reload = true;
 
 	return ret;
 }
@@ -2279,6 +2305,10 @@ static int smu_suspend(struct amdgpu_ip_block *ip_block)
 	if (ret)
 		return ret;
 
+	ret = smu_reset_mp1_state(smu);
+	if (ret)
+		return ret;
+
 	smu->watermarks_bitmap &= ~(WATERMARKS_LOADED);
 
 	smu_set_gfx_cgpg(smu, false);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-18  7:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18  4:20 [PATCH v2] drm/amd/pm: Fix SMU messages after system resume for smu 11.0.x Yang Wang
2026-08-18  7:41 ` Feng, Kenneth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.