From: Greg Kroah-Hartman Date: Sun, 14 Sep 2025 11:56:52 +0000 (+0200) Subject: 6.16-stable patches X-Git-Tag: v6.1.153~45 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cb112c7d4a91be7e342ad6b79afc93c6cad47722;p=thirdparty%2Fkernel%2Fstable-queue.git 6.16-stable patches added patches: drm-amd-display-destroy-cached-state-in-complete-callback.patch drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch --- diff --git a/queue-6.16/drm-amd-display-destroy-cached-state-in-complete-callback.patch b/queue-6.16/drm-amd-display-destroy-cached-state-in-complete-callback.patch new file mode 100644 index 0000000000..7818fc7fb1 --- /dev/null +++ b/queue-6.16/drm-amd-display-destroy-cached-state-in-complete-callback.patch @@ -0,0 +1,166 @@ +From stable+bounces-179564-greg=kroah.com@vger.kernel.org Sun Sep 14 13:48:28 2025 +From: Sasha Levin +Date: Sun, 14 Sep 2025 07:48:17 -0400 +Subject: drm/amd/display: Destroy cached state in complete() callback +To: stable@vger.kernel.org +Cc: Mario Limonciello , Alex Hung , Alex Deucher , Sasha Levin +Message-ID: <20250914114818.12813-1-sashal@kernel.org> + +From: Mario Limonciello + +[ Upstream commit 45cc102f8e6520ac07637c7e09f61dcc3772e125 ] + +[Why] +When the suspend sequence has been aborted after prepare() but +before suspend() the resume() callback never gets called. The PM core +will call complete() when this happens. As the state has been cached +in prepare() it needs to be destroyed in complete() if it's still around. + +[How] +Create a helper for destroying cached state and call it both in resume() +and complete() callbacks. If resume has been called the state will be +destroyed and it's a no-op for complete(). If resume hasn't been called +(such as an aborted suspend) then destroy the state in complete(). + +Fixes: 50e0bae34fa6 ("drm/amd/display: Add and use new dm_prepare_suspend() callback") +Reviewed-by: Alex Hung +Link: https://lore.kernel.org/r/20250602014432.3538345-4-superm1@kernel.org +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +Stable-dep-of: 60f71f0db7b1 ("drm/amd/display: Drop dm_prepare_suspend() and dm_complete()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 100 +++++++++++++--------- + 1 file changed, 60 insertions(+), 40 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -3084,6 +3084,64 @@ static int dm_cache_state(struct amdgpu_ + return adev->dm.cached_state ? 0 : r; + } + ++static void dm_destroy_cached_state(struct amdgpu_device *adev) ++{ ++ struct amdgpu_display_manager *dm = &adev->dm; ++ struct drm_device *ddev = adev_to_drm(adev); ++ struct dm_plane_state *dm_new_plane_state; ++ struct drm_plane_state *new_plane_state; ++ struct dm_crtc_state *dm_new_crtc_state; ++ struct drm_crtc_state *new_crtc_state; ++ struct drm_plane *plane; ++ struct drm_crtc *crtc; ++ int i; ++ ++ if (!dm->cached_state) ++ return; ++ ++ /* Force mode set in atomic commit */ ++ for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { ++ new_crtc_state->active_changed = true; ++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); ++ reset_freesync_config_for_crtc(dm_new_crtc_state); ++ } ++ ++ /* ++ * atomic_check is expected to create the dc states. We need to release ++ * them here, since they were duplicated as part of the suspend ++ * procedure. ++ */ ++ for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { ++ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); ++ if (dm_new_crtc_state->stream) { ++ WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1); ++ dc_stream_release(dm_new_crtc_state->stream); ++ dm_new_crtc_state->stream = NULL; ++ } ++ dm_new_crtc_state->base.color_mgmt_changed = true; ++ } ++ ++ for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { ++ dm_new_plane_state = to_dm_plane_state(new_plane_state); ++ if (dm_new_plane_state->dc_state) { ++ WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1); ++ dc_plane_state_release(dm_new_plane_state->dc_state); ++ dm_new_plane_state->dc_state = NULL; ++ } ++ } ++ ++ drm_atomic_helper_resume(ddev, dm->cached_state); ++ ++ dm->cached_state = NULL; ++} ++ ++static void dm_complete(struct amdgpu_ip_block *ip_block) ++{ ++ struct amdgpu_device *adev = ip_block->adev; ++ ++ dm_destroy_cached_state(adev); ++} ++ + static int dm_prepare_suspend(struct amdgpu_ip_block *ip_block) + { + struct amdgpu_device *adev = ip_block->adev; +@@ -3317,12 +3375,6 @@ static int dm_resume(struct amdgpu_ip_bl + struct amdgpu_dm_connector *aconnector; + struct drm_connector *connector; + struct drm_connector_list_iter iter; +- struct drm_crtc *crtc; +- struct drm_crtc_state *new_crtc_state; +- struct dm_crtc_state *dm_new_crtc_state; +- struct drm_plane *plane; +- struct drm_plane_state *new_plane_state; +- struct dm_plane_state *dm_new_plane_state; + struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state); + enum dc_connection_type new_connection_type = dc_connection_none; + struct dc_state *dc_state; +@@ -3481,40 +3533,7 @@ static int dm_resume(struct amdgpu_ip_bl + } + drm_connector_list_iter_end(&iter); + +- /* Force mode set in atomic commit */ +- for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { +- new_crtc_state->active_changed = true; +- dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); +- reset_freesync_config_for_crtc(dm_new_crtc_state); +- } +- +- /* +- * atomic_check is expected to create the dc states. We need to release +- * them here, since they were duplicated as part of the suspend +- * procedure. +- */ +- for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { +- dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); +- if (dm_new_crtc_state->stream) { +- WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1); +- dc_stream_release(dm_new_crtc_state->stream); +- dm_new_crtc_state->stream = NULL; +- } +- dm_new_crtc_state->base.color_mgmt_changed = true; +- } +- +- for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { +- dm_new_plane_state = to_dm_plane_state(new_plane_state); +- if (dm_new_plane_state->dc_state) { +- WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1); +- dc_plane_state_release(dm_new_plane_state->dc_state); +- dm_new_plane_state->dc_state = NULL; +- } +- } +- +- drm_atomic_helper_resume(ddev, dm->cached_state); +- +- dm->cached_state = NULL; ++ dm_destroy_cached_state(adev); + + /* Do mst topology probing after resuming cached state*/ + drm_connector_list_iter_begin(ddev, &iter); +@@ -3563,6 +3582,7 @@ static const struct amd_ip_funcs amdgpu_ + .prepare_suspend = dm_prepare_suspend, + .suspend = dm_suspend, + .resume = dm_resume, ++ .complete = dm_complete, + .is_idle = dm_is_idle, + .wait_for_idle = dm_wait_for_idle, + .check_soft_reset = dm_check_soft_reset, diff --git a/queue-6.16/drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch b/queue-6.16/drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch new file mode 100644 index 0000000000..0dafc18245 --- /dev/null +++ b/queue-6.16/drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch @@ -0,0 +1,87 @@ +From stable+bounces-179565-greg=kroah.com@vger.kernel.org Sun Sep 14 13:48:29 2025 +From: Sasha Levin +Date: Sun, 14 Sep 2025 07:48:18 -0400 +Subject: drm/amd/display: Drop dm_prepare_suspend() and dm_complete() +To: stable@vger.kernel.org +Cc: "Mario Limonciello (AMD)" , "Harry Wentland" , "Przemysław Kopa" , Kalvin , "Alex Deucher" , "Sasha Levin" +Message-ID: <20250914114818.12813-2-sashal@kernel.org> + +From: "Mario Limonciello (AMD)" + +[ Upstream commit 60f71f0db7b12f303789ef59949e38ee5838ee8b ] + +[Why] +dm_prepare_suspend() was added in commit 50e0bae34fa6b +("drm/amd/display: Add and use new dm_prepare_suspend() callback") +to allow display to turn off earlier in the suspend sequence. + +This caused a regression that HDMI audio sometimes didn't work +properly after resume unless audio was playing during suspend. + +[How] +Drop dm_prepare_suspend() callback. All code in it will still run +during dm_suspend(). Also drop unnecessary dm_complete() callback. +dm_complete() was used for failed prepare and also for any case +of successful resume. The code in it already runs in dm_resume(). + +This change will introduce more time that the display is turned on +during suspend sequence. The compositor can turn it off sooner if +desired. + +Cc: Harry Wentland +Reported-by: Przemysław Kopa +Closes: https://lore.kernel.org/amd-gfx/1cea0d56-7739-4ad9-bf8e-c9330faea2bb@kernel.org/T/#m383d9c08397043a271b36c32b64bb80e524e4b0f +Reported-by: Kalvin +Closes: https://github.com/alsa-project/alsa-lib/issues/465 +Closes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4809 +Fixes: 50e0bae34fa6b ("drm/amd/display: Add and use new dm_prepare_suspend() callback") +Signed-off-by: Mario Limonciello +Acked-by: Alex Deucher +Signed-off-by: Alex Deucher +(cherry picked from commit 2fd653b9bb5aacec5d4c421ab290905898fe85a2) +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 --------------------- + 1 file changed, 21 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -3135,25 +3135,6 @@ static void dm_destroy_cached_state(stru + dm->cached_state = NULL; + } + +-static void dm_complete(struct amdgpu_ip_block *ip_block) +-{ +- struct amdgpu_device *adev = ip_block->adev; +- +- dm_destroy_cached_state(adev); +-} +- +-static int dm_prepare_suspend(struct amdgpu_ip_block *ip_block) +-{ +- struct amdgpu_device *adev = ip_block->adev; +- +- if (amdgpu_in_reset(adev)) +- return 0; +- +- WARN_ON(adev->dm.cached_state); +- +- return dm_cache_state(adev); +-} +- + static int dm_suspend(struct amdgpu_ip_block *ip_block) + { + struct amdgpu_device *adev = ip_block->adev; +@@ -3579,10 +3560,8 @@ static const struct amd_ip_funcs amdgpu_ + .early_fini = amdgpu_dm_early_fini, + .hw_init = dm_hw_init, + .hw_fini = dm_hw_fini, +- .prepare_suspend = dm_prepare_suspend, + .suspend = dm_suspend, + .resume = dm_resume, +- .complete = dm_complete, + .is_idle = dm_is_idle, + .wait_for_idle = dm_wait_for_idle, + .check_soft_reset = dm_check_soft_reset, diff --git a/queue-6.16/series b/queue-6.16/series index 350ff0aa36..5b359145b4 100644 --- a/queue-6.16/series +++ b/queue-6.16/series @@ -107,3 +107,5 @@ mtd-spinand-winbond-enable-high-speed-modes-on-w25n0xjw.patch mtd-spinand-winbond-fix-oob_layout-for-w25n01jw.patch mm-damon-sysfs-fix-use-after-free-in-state_show.patch mm-damon-reclaim-avoid-divide-by-zero-in-damon_reclaim_apply_parameters.patch +drm-amd-display-destroy-cached-state-in-complete-callback.patch +drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch