[PATCH 29/41] drm/amd/display: Cover crtc destroy_state stream release

<[email protected]> Fri, 31 Jul 2026 17:12:50 -0400
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Bhawanpreet Lakha <[email protected]>

Add dm_test_crtc_destroy_state_releases_stream to cover the cur->stream
branch of amdgpu_dm_crtc_destroy_state(), complementing the existing
no-stream test.

The test attaches a DC stream to the CRTC state and takes an extra stream
reference so the destroy path drops back to the KUnit-managed reference
instead of freeing the stream, then verifies exactly one reference was
released.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Roman Li <[email protected]>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 805c171564c8..4dacddd23878 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -1451,6 +1451,40 @@ static void dm_test_crtc_destroy_state_no_stream(struct kunit *test)
 	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
 }
 
+/**
+ * dm_test_crtc_destroy_state_releases_stream - Test destroy releases the stream
+ * @test: The KUnit test context
+ *
+ * When the CRTC state carries a DC stream, destroying the state must release a
+ * stream reference. An extra reference is taken up front so the release leaves
+ * the KUnit-managed reference intact rather than freeing the stream here.
+ */
+static void dm_test_crtc_destroy_state_releases_stream(struct kunit *test)
+{
+	struct dc_stream_state *stream;
+	struct dm_crtc_state *dm_state;
+	struct dc_link *link;
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	/*
+	 * Take an extra reference so amdgpu_dm_crtc_destroy_state() drops back to
+	 * the KUnit-managed reference instead of freeing the stream.
+	 */
+	kref_get(&stream->refcount);
+
+	/* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */
+	dm_state = kzalloc_obj(*dm_state, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+	dm_state->stream = stream;
+
+	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
+
+	/* One reference was dropped, leaving the KUnit-managed one. */
+	KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
+}
+
 /**
  * dm_test_crtc_handle_vblank_no_event - Test vblank handling with no pending event
  * @test: The KUnit test context
@@ -1877,6 +1911,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_reset_state_allocates_state),
 	/* amdgpu_dm_crtc_destroy_state */
 	KUNIT_CASE(dm_test_crtc_destroy_state_no_stream),
+	KUNIT_CASE(dm_test_crtc_destroy_state_releases_stream),
 	/* amdgpu_dm_crtc_handle_vblank */
 	KUNIT_CASE(dm_test_crtc_handle_vblank_no_event),
 	KUNIT_CASE(dm_test_crtc_handle_vblank_skips_when_flip_submitted),
-- 
2.34.1