[PATCH 35/59] drm/amd/display: Test CRTC memory domain change detection

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for amdgpu_dm_crtc_mem_type_changed() covering an empty
plane mask, a plane missing one of its states, framebuffers in the same
memory domain, and a framebuffer migrated between domains.

[HOW]
Back the framebuffers with fake buffer objects carrying a TTM resource, so
get_mem_type() resolves a memory domain without a live TTM device.

Assisted-by: Copilot:Claude-Opus-5 GPT-5.6-Sol
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   7 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   3 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 138 ++++++++++++++++++
 3 files changed, 145 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 4650b5f09c08..70f50fa17366 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6044,9 +6044,9 @@ STATIC_IFN_KUNIT int add_affected_mst_dsc_crtcs(struct drm_atomic_commit *state,
 }
 EXPORT_IF_KUNIT(add_affected_mst_dsc_crtcs);
 
-static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
-					    struct drm_atomic_commit *state,
-					    struct drm_crtc_state *crtc_state)
+STATIC_IFN_KUNIT bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
+						      struct drm_atomic_commit *state,
+						      struct drm_crtc_state *crtc_state)
 {
 	struct drm_plane *plane;
 	struct drm_plane_state *new_plane_state, *old_plane_state;
@@ -6065,6 +6065,7 @@ static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
 
 	return false;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_mem_type_changed);
 
 /**
  * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
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 c22266f534e3..ca19977cf788 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1186,6 +1186,9 @@ void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
 					 bool pflip_update, bool cursor_update);
 int add_affected_mst_dsc_crtcs(struct drm_atomic_commit *state,
 			       struct drm_crtc *crtc);
+bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
+				     struct drm_atomic_commit *state,
+				     struct drm_crtc_state *crtc_state);
 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 845638fed223..0c57b3cc47fe 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
@@ -1804,6 +1804,139 @@ static void dm_test_update_pflip_irq_state_dce(struct kunit *test)
 			(int)AMDGPU_IRQ_STATE_DISABLE);
 }
 
+/* Tests for amdgpu_dm_crtc_mem_type_changed() */
+
+struct dm_test_mem_type_ctx {
+	struct amdgpu_device *adev;
+	struct drm_atomic_commit *state;
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state;
+	struct drm_plane_state *new_plane_state;
+};
+
+/*
+ * Register a single plane on the CRTC's plane mask. get_mem_type() walks
+ * fb->obj[0] back to an amdgpu_bo, so the framebuffers are backed by fake
+ * buffer objects with a TTM resource instead of a live TTM device.
+ */
+static struct drm_framebuffer *dm_test_alloc_fb(struct kunit *test,
+						u32 mem_type)
+{
+	struct drm_framebuffer *fb;
+	struct ttm_resource *res;
+	struct amdgpu_bo *abo;
+
+	fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, fb);
+	abo = kunit_kzalloc(test, sizeof(*abo), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, abo);
+	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, res);
+
+	res->mem_type = mem_type;
+	abo->tbo.resource = res;
+	fb->obj[0] = &abo->tbo.base;
+
+	return fb;
+}
+
+static struct dm_test_mem_type_ctx *dm_test_mem_type_ctx_alloc(struct kunit *test)
+{
+	struct dm_test_mem_type_ctx *ctx;
+
+	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+	ctx->adev = dm_kunit_alloc_adev(test);
+	ctx->state = dm_test_alloc_commit(test, ctx->adev);
+	ctx->crtc_state = kunit_kzalloc(test, sizeof(*ctx->crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->crtc_state);
+	ctx->plane = drm_kunit_helper_create_primary_plane(test, &ctx->adev->ddev,
+							   NULL, NULL, NULL, 0, NULL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->plane);
+	ctx->old_plane_state = kunit_kzalloc(test, sizeof(*ctx->old_plane_state),
+					     GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->old_plane_state);
+	ctx->new_plane_state = kunit_kzalloc(test, sizeof(*ctx->new_plane_state),
+					     GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->new_plane_state);
+	ctx->state->planes = kunit_kcalloc(test, ctx->plane->index + 1,
+					   sizeof(*ctx->state->planes), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->state->planes);
+
+	ctx->crtc_state->plane_mask = drm_plane_mask(ctx->plane);
+	ctx->state->planes[ctx->plane->index].ptr = ctx->plane;
+
+	return ctx;
+}
+
+/**
+ * dm_test_mem_type_changed_no_planes - Test an empty plane mask reports no change
+ * @test: The KUnit test context
+ */
+static void dm_test_mem_type_changed_no_planes(struct kunit *test)
+{
+	struct dm_test_mem_type_ctx *ctx = dm_test_mem_type_ctx_alloc(test);
+
+	ctx->crtc_state->plane_mask = 0;
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_mem_type_changed(&ctx->adev->ddev,
+								ctx->state,
+								ctx->crtc_state));
+}
+
+/**
+ * dm_test_mem_type_changed_missing_state - Test a plane without both states is skipped
+ * @test: The KUnit test context
+ */
+static void dm_test_mem_type_changed_missing_state(struct kunit *test)
+{
+	struct dm_test_mem_type_ctx *ctx = dm_test_mem_type_ctx_alloc(test);
+
+	ctx->state->planes[ctx->plane->index].new_state = ctx->new_plane_state;
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_mem_type_changed(&ctx->adev->ddev,
+								ctx->state,
+								ctx->crtc_state));
+}
+
+/**
+ * dm_test_mem_type_changed_same_domain - Test identical memory domains report no change
+ * @test: The KUnit test context
+ */
+static void dm_test_mem_type_changed_same_domain(struct kunit *test)
+{
+	struct dm_test_mem_type_ctx *ctx = dm_test_mem_type_ctx_alloc(test);
+
+	ctx->old_plane_state->fb = dm_test_alloc_fb(test, TTM_PL_VRAM);
+	ctx->new_plane_state->fb = dm_test_alloc_fb(test, TTM_PL_VRAM);
+	ctx->state->planes[ctx->plane->index].old_state = ctx->old_plane_state;
+	ctx->state->planes[ctx->plane->index].new_state = ctx->new_plane_state;
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_mem_type_changed(&ctx->adev->ddev,
+								ctx->state,
+								ctx->crtc_state));
+}
+
+/**
+ * dm_test_mem_type_changed_different_domain - Test a domain migration is detected
+ * @test: The KUnit test context
+ */
+static void dm_test_mem_type_changed_different_domain(struct kunit *test)
+{
+	struct dm_test_mem_type_ctx *ctx = dm_test_mem_type_ctx_alloc(test);
+
+	ctx->old_plane_state->fb = dm_test_alloc_fb(test, TTM_PL_TT);
+	ctx->new_plane_state->fb = dm_test_alloc_fb(test, TTM_PL_VRAM);
+	ctx->state->planes[ctx->plane->index].old_state = ctx->old_plane_state;
+	ctx->state->planes[ctx->plane->index].new_state = ctx->new_plane_state;
+
+	KUNIT_EXPECT_TRUE(test, amdgpu_dm_crtc_mem_type_changed(&ctx->adev->ddev,
+							       ctx->state,
+							       ctx->crtc_state));
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -1900,6 +2033,11 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	/* dm_update_pflip_irq_state */
 	KUNIT_CASE(dm_test_update_pflip_irq_state_dcn),
 	KUNIT_CASE(dm_test_update_pflip_irq_state_dce),
+	/* amdgpu_dm_crtc_mem_type_changed */
+	KUNIT_CASE(dm_test_mem_type_changed_no_planes),
+	KUNIT_CASE(dm_test_mem_type_changed_missing_state),
+	KUNIT_CASE(dm_test_mem_type_changed_same_domain),
+	KUNIT_CASE(dm_test_mem_type_changed_different_domain),
 	{}
 };
 
-- 
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.