diff options
| author | Alex Hung <alex.hung@amd.com> | 2026-08-11 17:08:06 -0600 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-08-25 18:32:57 -0400 |
| commit | 3dcd57191e07a916618dca02e85643348f0165de (patch) | |
| tree | 1f1ccf1dca559ff83c4eb07cd0d9d5bc3426870a /drivers | |
| parent | ba495959a529de04e921036ca0e54372943107dd (diff) | |
| download | linux-next-3dcd57191e07a916618dca02e85643348f0165de.tar.gz linux-next-3dcd57191e07a916618dca02e85643348f0165de.zip | |
drm/amd/display: Test plane state duplicate and destroy
[WHAT]
Add KUnit tests for amdgpu_dm_plane_drm_plane_duplicate_state() and
amdgpu_dm_plane_drm_plane_destroy_state() covering the resource paths.
Duplicating a state shares every color blob and takes an extra reference
on the DC plane state, and destroying one drops a reference on each.
Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c index ba97092c7bb8..17789b3845b7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c @@ -10,11 +10,14 @@ #include <drm/drm_blend.h> #include "link_enc_cfg.h" #include "amdgpu_dm_plane.h" +#include "amdgpu_dm_kunit_test_helpers.h" #include "amdgpu_rlc.h" #include "gc/gc_11_0_0_offset.h" #include "gc/gc_11_0_0_sh_mask.h" #include <drm/amdgpu_drm.h> +#include <drm/drm_mode_config.h> #include <drm/drm_plane.h> +#include <drm/drm_property.h> struct dm_test_dcc_cap_ctx { bool callback_ret; @@ -3001,6 +3004,78 @@ static void dm_test_plane_duplicate_state_copies_fields(struct kunit *test) kfree(dup_state); } +/* + * Attach a blob to every color property of @state. Each blob starts with a + * single reference that the tested function is expected to drop or share. + */ +static void dm_test_attach_color_blobs(struct kunit *test, struct drm_device *dev, + struct dm_plane_state *state) +{ + struct drm_property_blob **blobs[] = { + &state->degamma_lut, &state->ctm, &state->lut3d, + &state->shaper_lut, &state->blend_lut, + }; + u32 blob_data = 0; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(blobs); i++) { + *blobs[i] = drm_property_create_blob(dev, sizeof(blob_data), &blob_data); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, *blobs[i]); + } +} + +/** + * dm_test_plane_duplicate_state_copies_resources() - Verify blob and DC state sharing. + * @test: KUnit test context. + * + * Verify amdgpu_dm_plane_drm_plane_duplicate_state() shares the DC plane state + * and every color blob with the duplicate, taking an extra reference on each. + */ +static void dm_test_plane_duplicate_state_copies_resources(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct dm_plane_state *old_state; + struct drm_plane_state *dup_base; + struct dm_plane_state *dup_state; + struct dc_plane_state *dc_plane_state; + struct drm_plane *plane; + + KUNIT_ASSERT_EQ(test, drmm_mode_config_init(&adev->ddev), 0); + + plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); + old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL); + dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, plane); + KUNIT_ASSERT_NOT_NULL(test, old_state); + KUNIT_ASSERT_NOT_NULL(test, dc_plane_state); + + kref_init(&dc_plane_state->refcount); + old_state->dc_state = dc_plane_state; + dm_test_attach_color_blobs(test, &adev->ddev, old_state); + plane->state = &old_state->base; + + dup_base = amdgpu_dm_plane_drm_plane_duplicate_state(plane); + KUNIT_ASSERT_NOT_NULL(test, dup_base); + + dup_state = to_dm_plane_state(dup_base); + KUNIT_EXPECT_PTR_EQ(test, dup_state->dc_state, dc_plane_state); + KUNIT_EXPECT_EQ(test, kref_read(&dc_plane_state->refcount), 2U); + KUNIT_EXPECT_PTR_EQ(test, dup_state->degamma_lut, old_state->degamma_lut); + KUNIT_EXPECT_PTR_EQ(test, dup_state->ctm, old_state->ctm); + KUNIT_EXPECT_PTR_EQ(test, dup_state->shaper_lut, old_state->shaper_lut); + KUNIT_EXPECT_PTR_EQ(test, dup_state->lut3d, old_state->lut3d); + KUNIT_EXPECT_PTR_EQ(test, dup_state->blend_lut, old_state->blend_lut); + + /* Drops the duplicate's references; the originals are released below. */ + amdgpu_dm_plane_drm_plane_destroy_state(plane, dup_base); + + drm_property_blob_put(old_state->degamma_lut); + drm_property_blob_put(old_state->ctm); + drm_property_blob_put(old_state->lut3d); + drm_property_blob_put(old_state->shaper_lut); + drm_property_blob_put(old_state->blend_lut); +} + /** * dm_test_plane_destroy_state_minimal() - Verify destroy of a minimal state. * @test: KUnit test context. @@ -3024,6 +3099,42 @@ static void dm_test_plane_destroy_state_minimal(struct kunit *test) amdgpu_dm_plane_drm_plane_destroy_state(plane, &dm_plane_state->base); } +/** + * dm_test_plane_destroy_state_releases_resources() - Verify blob and DC state release. + * @test: KUnit test context. + * + * Verify amdgpu_dm_plane_drm_plane_destroy_state() drops a reference on every + * attached color blob and on the DC plane state. + */ +static void dm_test_plane_destroy_state_releases_resources(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct dm_plane_state *dm_plane_state; + struct dc_plane_state *dc_plane_state; + struct drm_plane *plane; + + KUNIT_ASSERT_EQ(test, drmm_mode_config_init(&adev->ddev), 0); + + plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); + dc_plane_state = kunit_kzalloc(test, sizeof(*dc_plane_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, plane); + KUNIT_ASSERT_NOT_NULL(test, dc_plane_state); + + /* destroy_state frees the state itself, so use a plain allocation. */ + dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, dm_plane_state); + + /* Hold an extra reference so the release does not free KUnit memory. */ + kref_init(&dc_plane_state->refcount); + kref_get(&dc_plane_state->refcount); + dm_plane_state->dc_state = dc_plane_state; + dm_test_attach_color_blobs(test, &adev->ddev, dm_plane_state); + + amdgpu_dm_plane_drm_plane_destroy_state(plane, &dm_plane_state->base); + + KUNIT_EXPECT_EQ(test, kref_read(&dc_plane_state->refcount), 1U); +} + static struct kunit_case amdgpu_dm_plane_test_cases[] = { /* amdgpu_dm_plane_is_video_format() */ KUNIT_CASE(dm_test_plane_is_video_format_known_video), @@ -3102,8 +3213,10 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = { KUNIT_CASE(dm_test_plane_reset_initializes_state), /* amdgpu_dm_plane_drm_plane_duplicate_state() */ KUNIT_CASE(dm_test_plane_duplicate_state_copies_fields), + KUNIT_CASE(dm_test_plane_duplicate_state_copies_resources), /* amdgpu_dm_plane_drm_plane_destroy_state() */ KUNIT_CASE(dm_test_plane_destroy_state_minimal), + KUNIT_CASE(dm_test_plane_destroy_state_releases_resources), /* amdgpu_dm_plane_add_modifier() */ KUNIT_CASE(dm_test_add_modifier_appends_value), KUNIT_CASE(dm_test_add_modifier_grows_capacity), |
