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
