]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Sep 2025 11:56:52 +0000 (13:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Sep 2025 11:56:52 +0000 (13:56 +0200)
added patches:
drm-amd-display-destroy-cached-state-in-complete-callback.patch
drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch

queue-6.16/drm-amd-display-destroy-cached-state-in-complete-callback.patch [new file with mode: 0644]
queue-6.16/drm-amd-display-drop-dm_prepare_suspend-and-dm_complete.patch [new file with mode: 0644]
queue-6.16/series

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 (file)
index 0000000..7818fc7
--- /dev/null
@@ -0,0 +1,166 @@
+From stable+bounces-179564-greg=kroah.com@vger.kernel.org Sun Sep 14 13:48:28 2025
+From: Sasha Levin <sashal@kernel.org>
+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 <mario.limonciello@amd.com>, Alex Hung <alex.hung@amd.com>, Alex Deucher <alexander.deucher@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20250914114818.12813-1-sashal@kernel.org>
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ 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 <alex.hung@amd.com>
+Link: https://lore.kernel.org/r/20250602014432.3538345-4-superm1@kernel.org
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 60f71f0db7b1 ("drm/amd/display: Drop dm_prepare_suspend() and dm_complete()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0dafc18
--- /dev/null
@@ -0,0 +1,87 @@
+From stable+bounces-179565-greg=kroah.com@vger.kernel.org Sun Sep 14 13:48:29 2025
+From: Sasha Levin <sashal@kernel.org>
+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)" <mario.limonciello@amd.com>, "Harry Wentland" <harry.wentland@amd.com>, "Przemysław Kopa" <prz.kopa@gmail.com>, Kalvin <hikaph+oss@gmail.com>, "Alex Deucher" <alexander.deucher@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20250914114818.12813-2-sashal@kernel.org>
+
+From: "Mario Limonciello (AMD)" <mario.limonciello@amd.com>
+
+[ 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 <harry.wentland@amd.com>
+Reported-by: Przemysław Kopa <prz.kopa@gmail.com>
+Closes: https://lore.kernel.org/amd-gfx/1cea0d56-7739-4ad9-bf8e-c9330faea2bb@kernel.org/T/#m383d9c08397043a271b36c32b64bb80e524e4b0f
+Reported-by: Kalvin <hikaph+oss@gmail.com>
+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 <mario.limonciello@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 2fd653b9bb5aacec5d4c421ab290905898fe85a2)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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,
index 350ff0aa3682a1b8aeb76a5021fdcf7cf9fcd9f5..5b359145b4f93a609b141199df744a87f449f803 100644 (file)
@@ -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