[PATCH 34/59] drm/amd/display: Test page flip interrupt state update

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for dm_update_pflip_irq_state() covering DCN, where there
is nothing to reapply, and DCE, where the current interrupt state is
reapplied to the pageflip source.

[HOW]
Add a spy for the pageflip IRQ source. amdgpu_irq_update() always
dispatches through src->funcs->set(), which needs a registered IH ring on
real hardware, so the spy records the requested type and state instead.

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 |  5 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 78 +++++++++++++++++++
 3 files changed, 83 insertions(+), 2 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 1eb2f0973aac..4650b5f09c08 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3419,8 +3419,8 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
 	}
 }
 
-static void dm_update_pflip_irq_state(struct amdgpu_device *adev,
-				      struct amdgpu_crtc *acrtc)
+STATIC_IFN_KUNIT void dm_update_pflip_irq_state(struct amdgpu_device *adev,
+						struct amdgpu_crtc *acrtc)
 {
 	int irq_type =
 		amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);
@@ -3435,6 +3435,7 @@ static void dm_update_pflip_irq_state(struct amdgpu_device *adev,
 	 */
 	amdgpu_irq_update(adev, &adev->pageflip_irq, irq_type);
 }
+EXPORT_IF_KUNIT(dm_update_pflip_irq_state);
 
 STATIC_IFN_KUNIT bool
 is_scaling_state_different(const struct dm_connector_state *dm_state,
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 e4b67a0b98c3..c22266f534e3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1172,6 +1172,8 @@ struct dm_atomic_state *dm_atomic_get_new_state(struct drm_atomic_commit *state)
 struct drm_private_state *dm_atomic_duplicate_state(struct drm_private_obj *obj);
 void dm_atomic_destroy_state(struct drm_private_obj *obj,
 			     struct drm_private_state *state);
+void dm_update_pflip_irq_state(struct amdgpu_device *adev,
+			       struct amdgpu_crtc *acrtc);
 void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state);
 void amdgpu_dm_update_cursor(struct drm_plane *plane,
 			     struct drm_plane_state *old_plane_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 648db4a58509..845638fed223 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
@@ -1729,6 +1729,81 @@ static void dm_test_arm_vblank_event_cursor(struct kunit *test)
 			(int)AMDGPU_FLIP_NONE);
 }
 
+/**
+ * dm_test_update_pflip_irq_state_dcn - Test DCN skips the GRPH_PFLIP reapply
+ * @test: The KUnit test context
+ */
+static void dm_test_update_pflip_irq_state_dcn(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->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 2, 0);
+
+	dm_update_pflip_irq_state(adev, acrtc);
+}
+
+/*
+ * Spy for the pageflip IRQ source: amdgpu_irq_update() always dispatches
+ * through src->funcs->set(), which needs a registered IH ring on real
+ * hardware. Recording the requested state instead keeps the DCE reapply path
+ * reachable and observable.
+ */
+struct dm_test_irq_spy {
+	unsigned int set_count;
+	unsigned int last_type;
+	enum amdgpu_interrupt_state last_state;
+};
+
+static struct dm_test_irq_spy dm_test_irq_spy_data;
+
+static int dm_test_irq_set(struct amdgpu_device *adev,
+			   struct amdgpu_irq_src *src, unsigned int type,
+			   enum amdgpu_interrupt_state state)
+{
+	dm_test_irq_spy_data.set_count++;
+	dm_test_irq_spy_data.last_type = type;
+	dm_test_irq_spy_data.last_state = state;
+
+	return 0;
+}
+
+static const struct amdgpu_irq_src_funcs dm_test_irq_funcs = {
+	.set = dm_test_irq_set,
+};
+
+/**
+ * dm_test_update_pflip_irq_state_dce - Test DCE reapplies the GRPH_PFLIP state
+ * @test: The KUnit test context
+ */
+static void dm_test_update_pflip_irq_state_dce(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);
+
+	memset(&dm_test_irq_spy_data, 0, sizeof(dm_test_irq_spy_data));
+	adev->mode_info.num_crtc = 2;
+	adev->ip_versions[DCE_HWIP][0] = 0;
+	adev->pageflip_irq.funcs = &dm_test_irq_funcs;
+	acrtc->crtc_id = 1;
+	spin_lock_init(&adev->irq.lock);
+
+	dm_update_pflip_irq_state(adev, acrtc);
+
+	KUNIT_EXPECT_EQ(test, dm_test_irq_spy_data.set_count, 1U);
+	KUNIT_EXPECT_EQ(test, dm_test_irq_spy_data.last_type,
+			(unsigned int)AMDGPU_CRTC_IRQ_VBLANK2);
+	KUNIT_EXPECT_EQ(test, (int)dm_test_irq_spy_data.last_state,
+			(int)AMDGPU_IRQ_STATE_DISABLE);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -1822,6 +1897,9 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_event),
 	KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_planes),
 	KUNIT_CASE(dm_test_arm_vblank_pre_programming_update),
+	/* dm_update_pflip_irq_state */
+	KUNIT_CASE(dm_test_update_pflip_irq_state_dcn),
+	KUNIT_CASE(dm_test_update_pflip_irq_state_dce),
 	{}
 };
 
-- 
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.