From: Alex Hung <[email protected]> [Why] Add KUnit tests for an empty amdgpu_dm_atomic_check(), an unchanged CRTC update, and a detached plane update.
[How] Use standard DRM KUnit objects and existing state fixtures so each helper reaches its software-only early return without DC hardware programming. Assisted-by: Copilot:Claude-Opus-5 GPT-5.6 Sol Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Ray Wu <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 40 +++++----- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 17 +++++ .../display/amdgpu_dm/tests/amdgpu_dm_test.c | 76 +++++++++++++++++++ 3 files changed, 116 insertions(+), 17 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 d94d18e884ef..9f64bea15ea1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -145,8 +145,10 @@ STATIC_IFN_KUNIT int amdgpu_dm_atomic_setup_commit(struct drm_atomic_commit *sta static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state); STATIC_IFN_KUNIT void dm_enable_per_frame_crtc_master_sync(struct dc_state *context); +#if !IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST) static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state); +#endif static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc) { @@ -5428,13 +5430,13 @@ STATIC_IFN_KUNIT int do_aquire_global_lock(struct drm_device *dev, } EXPORT_IF_KUNIT(do_aquire_global_lock); -static int dm_update_crtc_state(struct amdgpu_display_manager *dm, - struct drm_atomic_commit *state, - struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state, - struct drm_crtc_state *new_crtc_state, - bool enable, - bool *lock_and_validation_needed) +STATIC_IFN_KUNIT int dm_update_crtc_state(struct amdgpu_display_manager *dm, + struct drm_atomic_commit *state, + struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state, + struct drm_crtc_state *new_crtc_state, + bool enable, + bool *lock_and_validation_needed) { struct dm_atomic_state *dm_state = NULL; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; @@ -5703,6 +5705,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, dc_stream_release(new_stream); return ret; } +EXPORT_IF_KUNIT(dm_update_crtc_state); STATIC_IFN_KUNIT bool should_reset_plane(struct drm_atomic_commit *state, struct drm_plane *plane, @@ -5869,14 +5872,15 @@ STATIC_IFN_KUNIT bool should_reset_plane(struct drm_atomic_commit *state, } EXPORT_IF_KUNIT(should_reset_plane); -static int dm_update_plane_state(struct dc *dc, - struct drm_atomic_commit *state, - struct drm_plane *plane, - struct drm_plane_state *old_plane_state, - struct drm_plane_state *new_plane_state, - bool enable, - bool *lock_and_validation_needed, - bool *is_top_most_overlay) +STATIC_IFN_KUNIT int +dm_update_plane_state(struct dc *dc, + struct drm_atomic_commit *state, + struct drm_plane *plane, + struct drm_plane_state *old_plane_state, + struct drm_plane_state *new_plane_state, + bool enable, + bool *lock_and_validation_needed, + bool *is_top_most_overlay) { struct dm_atomic_state *dm_state = NULL; @@ -6040,6 +6044,7 @@ static int dm_update_plane_state(struct dc *dc, return ret; } +EXPORT_IF_KUNIT(dm_update_plane_state); /* * The normalized_zpos value cannot be used by this iterator directly. It's only @@ -6166,8 +6171,8 @@ EXPORT_IF_KUNIT(amdgpu_dm_crtc_mem_type_changed); * * Return: -Error code if validation failed. */ -static int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_commit *state) +STATIC_IFN_KUNIT int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_commit *state) { struct amdgpu_device *adev = drm_to_adev(dev); struct dm_atomic_state *dm_state = NULL; @@ -6678,6 +6683,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } +EXPORT_IF_KUNIT(amdgpu_dm_atomic_check); void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { 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 3c63dfcc2343..c99a84bb040e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1208,6 +1208,23 @@ void amdgpu_dm_update_hdcp(struct drm_atomic_commit *state); int amdgpu_dm_atomic_setup_commit(struct drm_atomic_commit *state); int do_aquire_global_lock(struct drm_device *dev, struct drm_atomic_commit *state); +int dm_update_crtc_state(struct amdgpu_display_manager *dm, + struct drm_atomic_commit *state, + struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state, + struct drm_crtc_state *new_crtc_state, + bool enable, + bool *lock_and_validation_needed); +int dm_update_plane_state(struct dc *dc, + struct drm_atomic_commit *state, + struct drm_plane *plane, + struct drm_plane_state *old_plane_state, + struct drm_plane_state *new_plane_state, + bool enable, + bool *lock_and_validation_needed, + bool *is_top_most_overlay); +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_commit *state); void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, struct amdgpu_display_manager *dm); void amdgpu_dm_mod_power_setup_streams(struct drm_atomic_commit *state, 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 3209608a41b8..6335fc23e977 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 @@ -2990,6 +2990,21 @@ static void dm_test_atomic_setup_commit_empty(struct kunit *test) 0); } +/** + * dm_test_atomic_check_empty - Test an empty atomic commit needs no DC validation + * @test: The KUnit test context + */ +static void dm_test_atomic_check_empty(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct drm_atomic_commit *state = dm_test_alloc_commit(test, adev); + + adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test); + + KUNIT_EXPECT_EQ(test, amdgpu_dm_atomic_check(&adev->ddev, state), 0); + KUNIT_EXPECT_EQ(test, state->num_private_objs, 0U); +} + /* * A commit with one connector of @type bound to a CRTC that keeps its stream. * The content protection state is unchanged, so amdgpu_dm_update_hdcp() walks @@ -3172,6 +3187,64 @@ static void dm_test_aquire_global_lock_waits_commit(struct kunit *test) KUNIT_EXPECT_EQ(test, ret, 0); } +/** + * dm_test_update_crtc_state_unchanged - Test unchanged state needs no validation + * @test: The KUnit test context + */ +static void dm_test_update_crtc_state_unchanged(struct kunit *test) +{ + struct dm_test_reset_plane_ctx *ctx = dm_test_reset_plane_ctx_alloc(test); + bool lock_and_validation_needed = false; + + ctx->adev->dm.adev = ctx->adev; + KUNIT_EXPECT_EQ(test, + dm_update_crtc_state(&ctx->adev->dm, ctx->state, ctx->crtc, + &ctx->old_crtc_state->base, + &ctx->new_crtc_state->base, true, + &lock_and_validation_needed), + 0); + KUNIT_EXPECT_FALSE(test, lock_and_validation_needed); + KUNIT_EXPECT_NULL(test, ctx->new_crtc_state->stream); +} + +/** + * dm_test_update_plane_state_detached - Test a detached plane needs no DC update + * @test: The KUnit test context + */ +static void dm_test_update_plane_state_detached(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct dm_plane_state *old_plane_state; + struct dm_plane_state *new_plane_state; + struct drm_plane *plane; + bool lock_and_validation_needed = false; + bool is_top_most_overlay = true; + + old_plane_state = kunit_kzalloc(test, sizeof(*old_plane_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, old_plane_state); + new_plane_state = kunit_kzalloc(test, sizeof(*new_plane_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, new_plane_state); + plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, plane); + adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, adev->reset_domain); + + adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 2, 0); + plane->dev = &adev->ddev; + plane->type = DRM_PLANE_TYPE_PRIMARY; + + KUNIT_EXPECT_EQ(test, + dm_update_plane_state(NULL, dm_test_alloc_commit(test, adev), plane, + &old_plane_state->base, + &new_plane_state->base, false, + &lock_and_validation_needed, + &is_top_most_overlay), + 0); + KUNIT_EXPECT_FALSE(test, lock_and_validation_needed); + KUNIT_EXPECT_TRUE(test, is_top_most_overlay); + KUNIT_EXPECT_NULL(test, new_plane_state->dc_state); +} + /** * dm_test_mod_power_update_streams_empty - Test an empty commit updates no streams * @test: The KUnit test context @@ -5251,9 +5324,12 @@ static struct kunit_case amdgpu_dm_tests[] = { KUNIT_CASE(dm_test_atomic_setup_commit_color_mgmt), KUNIT_CASE(dm_test_atomic_setup_commit_modeset), KUNIT_CASE(dm_test_atomic_setup_commit_bad_lut), + KUNIT_CASE(dm_test_atomic_check_empty), KUNIT_CASE(dm_test_aquire_global_lock_no_crtc), KUNIT_CASE(dm_test_aquire_global_lock_no_commit), KUNIT_CASE(dm_test_aquire_global_lock_waits_commit), + KUNIT_CASE(dm_test_update_crtc_state_unchanged), + KUNIT_CASE(dm_test_update_plane_state_detached), KUNIT_CASE(dm_test_mod_power_update_streams_empty), KUNIT_CASE(dm_test_mod_power_update_streams_no_modeset), KUNIT_CASE(dm_test_mod_power_update_streams_enable), -- 2.43.0
