[PATCH 05/34] drm/amd/display: Cover crtc destroy callback
Tom Chung <[email protected]> Wed, 5 Aug 2026 14:36:17 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Bhawanpreet Lakha <[email protected]> [why] The amdgpu_dm_crtc_destroy() .destroy callback, which runs drm_crtc_cleanup() and frees the CRTC, was not exercised by the KUnit suite. [how] Exposed amdgpu_dm_crtc_destroy() via STATIC_IFN_KUNIT/EXPORT_IF_KUNIT and a KUnit-only declaration, and added dm_test_crtc_destroy_cleans_up_and_frees which initializes a CRTC with a primary plane and verifies mode_config.num_crtc drops from 1 to 0 after destroy. Registered the case in amdgpu_dm_crtc_tests. Reviewed-by: Alex Hung <[email protected]> Signed-off-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Tom Chung <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 3 +- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h | 1 + .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c | 43 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 82a30097072e..470abe9cc8f1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -459,7 +459,7 @@ STATIC_IFN_KUNIT struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct dr } EXPORT_IF_KUNIT(amdgpu_dm_crtc_duplicate_state); -static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +STATIC_IFN_KUNIT void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) { /* * amdgpu_dm_ism_fini() is intentionally called in amdgpu_dm_fini(). @@ -470,6 +470,7 @@ static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) drm_crtc_cleanup(crtc); kfree(crtc); } +EXPORT_IF_KUNIT(amdgpu_dm_crtc_destroy); STATIC_IFN_KUNIT void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h index 93c6d0d8d7fd..06bb22d4c3b7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h @@ -49,6 +49,7 @@ bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc); +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc); int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state); void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc, 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 a23281a33422..1af819113168 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 @@ -1463,6 +1463,47 @@ static void dm_test_crtc_duplicate_state_null_state_returns_null(struct kunit *t KUNIT_EXPECT_NULL(test, amdgpu_dm_crtc_duplicate_state(crtc)); } +/* Tests for amdgpu_dm_crtc_destroy() */ + +/** + * dm_test_crtc_destroy_cleans_up_and_frees - Test destroy tears down the CRTC + * @test: The KUnit test context + * + * amdgpu_dm_crtc_destroy() is the drm_crtc .destroy callback: it must run + * drm_crtc_cleanup() and free the CRTC. Initialise a CRTC with a primary plane + * so it is registered on the device (num_crtc == 1), then destroy it and verify + * the CRTC was unregistered (num_crtc back to 0). The CRTC is a plain (unmanaged) + * allocation because amdgpu_dm_crtc_destroy() kfree()s it. + */ +static void dm_test_crtc_destroy_cleans_up_and_frees(struct kunit *test) +{ + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + struct drm_plane *plane; + int ret; + + adev = dm_kunit_alloc_adev(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); + + plane = drm_kunit_helper_create_primary_plane(test, &adev->ddev, + NULL, NULL, NULL, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); + + /* amdgpu_dm_crtc_destroy() kfree()s the CRTC, so use a plain alloc. */ + acrtc = kzalloc_obj(*acrtc, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + ret = drm_crtc_init_with_planes(&adev->ddev, &acrtc->base, plane, + NULL, &dm_test_crtc_funcs, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, adev->ddev.mode_config.num_crtc, 1); + + amdgpu_dm_crtc_destroy(&acrtc->base); + + /* drm_crtc_cleanup() ran: the CRTC was unregistered from the device. */ + KUNIT_EXPECT_EQ(test, adev->ddev.mode_config.num_crtc, 0); +} + /* Tests for amdgpu_dm_crtc_reset_state() */ /** @@ -1968,6 +2009,8 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = { KUNIT_CASE(dm_test_crtc_duplicate_state_copies_fields), KUNIT_CASE(dm_test_crtc_duplicate_state_retains_stream), KUNIT_CASE(dm_test_crtc_duplicate_state_null_state_returns_null), + /* amdgpu_dm_crtc_destroy */ + KUNIT_CASE(dm_test_crtc_destroy_cleans_up_and_frees), /* amdgpu_dm_crtc_reset_state */ KUNIT_CASE(dm_test_crtc_reset_state_allocates_state), /* amdgpu_dm_crtc_destroy_state */ -- 2.43.0