[PATCH 31/70] drm/amd/display: add KUnit tests for DM CRTC vblank/scanout

Wayne Lin <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Alex Hung <[email protected]>

[WHAT]
Add KUnit tests for the DM CRTC helpers: the no-writeback and
non-pending writeback paths of amdgpu_dm_crtc_complete_writeback, the
out-of-range and no-stream paths of dm_vblank_get_counter, and the
invalid-CRTC and no-stream paths of dm_crtc_get_scanoutpos.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Wayne Lin <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   9 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   3 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 112 ++++++++++++++++++
 3 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 80778d7e7337..4b60d7343dec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -169,7 +169,7 @@ static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
  * @return
  * Counter for vertical blanks
  */
-static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
+STATIC_IFN_KUNIT u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 {
 	struct amdgpu_crtc *acrtc = NULL;
 
@@ -186,9 +186,10 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 
 	return dc_stream_get_vblank_counter(acrtc->dm_irq_params.stream);
 }
+EXPORT_IF_KUNIT(dm_vblank_get_counter);
 
-static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
-				  u32 *vbl, u32 *position)
+STATIC_IFN_KUNIT int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+					    u32 *vbl, u32 *position)
 {
 	u32 v_blank_start = 0, v_blank_end = 0, h_position = 0, v_position = 0;
 	struct amdgpu_crtc *acrtc = NULL;
@@ -223,6 +224,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
 
 	return 0;
 }
+EXPORT_IF_KUNIT(dm_crtc_get_scanoutpos);
 
 STATIC_IFN_KUNIT bool dm_is_idle(struct amdgpu_ip_block *ip_block)
 {
@@ -4686,6 +4688,7 @@ bool amdgpu_dm_crtc_complete_writeback(struct amdgpu_crtc *acrtc)
 
 	return true;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_complete_writeback);
 
 static void dm_clear_writeback(struct amdgpu_display_manager *dm,
 			      struct amdgpu_crtc *acrtc,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 7bb552d1ddba..cbe95fb3c0d6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1149,6 +1149,9 @@ int dm_set_clockgating_state(struct amdgpu_ip_block *ip_block,
 int dm_set_powergating_state(struct amdgpu_ip_block *ip_block,
 			     enum amd_powergating_state state);
 void dm_bandwidth_update(struct amdgpu_device *adev);
+u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc);
+int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+			   u32 *vbl, u32 *position);
 int dm_plane_layer_index_cmp(const void *a, const void *b);
 int fill_plane_color_attributes(const struct drm_plane_state *plane_state,
 				const enum surface_pixel_format format,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index d4e37580316f..7b92078d95bc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -77,6 +77,112 @@ static void dm_test_bandwidth_update(struct kunit *test)
 	dm_bandwidth_update(NULL);
 }
 
+/**
+ * dm_test_crtc_complete_writeback_no_connector - Test no writeback connector returns false
+ * @test: The KUnit test context
+ */
+static void dm_test_crtc_complete_writeback_no_connector(struct kunit *test)
+{
+	struct amdgpu_crtc *acrtc;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acrtc);
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_complete_writeback(acrtc));
+}
+
+/**
+ * dm_test_crtc_complete_writeback_not_pending - Test non-pending writeback returns false
+ * @test: The KUnit test context
+ */
+static void dm_test_crtc_complete_writeback_not_pending(struct kunit *test)
+{
+	struct amdgpu_crtc *acrtc;
+	struct drm_writeback_connector *wb_conn;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acrtc);
+	wb_conn = kunit_kzalloc(test, sizeof(*wb_conn), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, wb_conn);
+
+	spin_lock_init(&wb_conn->job_lock);
+	acrtc->wb_conn = wb_conn;
+	acrtc->wb_pending = false;
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_complete_writeback(acrtc));
+}
+
+/**
+ * dm_test_vblank_get_counter_out_of_range - Test out-of-range CRTC returns zero
+ * @test: The KUnit test context
+ */
+static void dm_test_vblank_get_counter_out_of_range(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	adev->mode_info.num_crtc = 1;
+
+	KUNIT_EXPECT_EQ(test, dm_vblank_get_counter(adev, 1), 0U);
+}
+
+/**
+ * dm_test_vblank_get_counter_no_stream - Test missing stream returns zero
+ * @test: The KUnit test context
+ */
+static void dm_test_vblank_get_counter_no_stream(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct amdgpu_crtc *acrtc;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acrtc);
+
+	adev->mode_info.num_crtc = 1;
+	adev->mode_info.crtcs[0] = acrtc;
+
+	KUNIT_EXPECT_EQ(test, dm_vblank_get_counter(adev, 0), 0U);
+}
+
+/**
+ * dm_test_crtc_get_scanoutpos_invalid_crtc - Test invalid CRTC returns -EINVAL
+ * @test: The KUnit test context
+ */
+static void dm_test_crtc_get_scanoutpos_invalid_crtc(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	u32 vbl = 0;
+	u32 position = 0;
+
+	adev->mode_info.num_crtc = 1;
+
+	KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, -1, &vbl, &position),
+			-EINVAL);
+	KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 1, &vbl, &position),
+			-EINVAL);
+}
+
+/**
+ * dm_test_crtc_get_scanoutpos_no_stream - Test missing stream returns zero
+ * @test: The KUnit test context
+ */
+static void dm_test_crtc_get_scanoutpos_no_stream(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct amdgpu_crtc *acrtc;
+	u32 vbl = 0;
+	u32 position = 0;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, acrtc);
+
+	adev->mode_info.num_crtc = 1;
+	adev->mode_info.crtcs[0] = acrtc;
+
+	KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0, &vbl, &position), 0);
+	KUNIT_EXPECT_EQ(test, vbl, 0U);
+	KUNIT_EXPECT_EQ(test, position, 0U);
+}
+
 /* Tests for dm_plane_layer_index_cmp() */
 
 /**
@@ -957,6 +1063,12 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_set_clockgating_state),
 	KUNIT_CASE(dm_test_set_powergating_state),
 	KUNIT_CASE(dm_test_bandwidth_update),
+	KUNIT_CASE(dm_test_crtc_complete_writeback_no_connector),
+	KUNIT_CASE(dm_test_crtc_complete_writeback_not_pending),
+	KUNIT_CASE(dm_test_vblank_get_counter_out_of_range),
+	KUNIT_CASE(dm_test_vblank_get_counter_no_stream),
+	KUNIT_CASE(dm_test_crtc_get_scanoutpos_invalid_crtc),
+	KUNIT_CASE(dm_test_crtc_get_scanoutpos_no_stream),
 	/* dm_plane_layer_index_cmp */
 	KUNIT_CASE(dm_test_plane_layer_index_cmp_equal),
 	KUNIT_CASE(dm_test_plane_layer_index_cmp_descending),
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.