[PATCH 47/59] drm/amd/display: Test vline0 irq control

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
The vline0 interrupt handling in amdgpu_dm_crtc_set_vblank() sits
inside a CONFIG_DRM_AMD_SECURE_DISPLAY block. That symbol depends on
CONFIG_DRM_AMD_DC_FP, which cannot be enabled on UML because UML does
not select ARCH_HAS_KERNEL_FPU_SUPPORT, so the logic is never built by
the KUnit tests and stays uncovered.

[HOW]
Move the block into amdgpu_dm_crtc_set_vline0_irq() and build it
whenever CONFIG_DRM_AMD_SECURE_DISPLAY or the KUnit tests are enabled.
The DCN-only check becomes an early return. Behaviour of
amdgpu_dm_crtc_set_vblank() is unchanged.

Add tests for amdgpu_dm_crtc_set_vline0_irq() covering the DCE no-op
path, error propagation from amdgpu_irq_get() and the enable/disable
refcount round-trip.

Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  40 ++++---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |   1 +
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 101 ++++++++++++++++++
 3 files changed, 129 insertions(+), 13 deletions(-)

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 2de758aceda5..4b8530d734e5 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
@@ -249,6 +249,30 @@ STATIC_IFN_KUNIT void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *w
 }
 EXPORT_IF_KUNIT(amdgpu_dm_crtc_vblank_control_worker);
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) || IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+STATIC_IFN_KUNIT int amdgpu_dm_crtc_set_vline0_irq(struct drm_crtc *crtc, int irq_type,
+						   bool enable)
+{
+	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
+	int rc;
+
+	/* crtc vline0 interrupt, only available on DCN+ */
+	if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0)
+		return 0;
+
+	if (enable) {
+		rc = amdgpu_irq_get(adev, &adev->vline0_irq, irq_type);
+		drm_dbg_vbl(crtc->dev, "Get vline0_irq ret=%d\n", rc);
+	} else {
+		rc = amdgpu_irq_put(adev, &adev->vline0_irq, irq_type);
+		drm_dbg_vbl(crtc->dev, "Put vline0_irq ret=%d\n", rc);
+	}
+
+	return rc;
+}
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_set_vline0_irq);
+#endif
+
 static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
 {
 	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
@@ -358,19 +382,9 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
 	}
 
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-	/* crtc vline0 interrupt, only available on DCN+ */
-	if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
-		if (enable) {
-			rc = amdgpu_irq_get(adev, &adev->vline0_irq, irq_type);
-			drm_dbg_vbl(crtc->dev, "Get vline0_irq ret=%d\n", rc);
-		} else {
-			rc = amdgpu_irq_put(adev, &adev->vline0_irq, irq_type);
-			drm_dbg_vbl(crtc->dev, "Put vline0_irq ret=%d\n", rc);
-		}
-
-		if (rc)
-			return rc;
-	}
+	rc = amdgpu_dm_crtc_set_vline0_irq(crtc, irq_type, enable);
+	if (rc)
+		return rc;
 #endif
 
 	if (amdgpu_in_reset(adev))
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 7de79796a56d..91fdd262c2d2 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
@@ -56,6 +56,7 @@ void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 					      struct drm_crtc_state *new_crtc_state);
 void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work);
 void amdgpu_dm_idle_worker(struct work_struct *work);
+int amdgpu_dm_crtc_set_vline0_irq(struct drm_crtc *crtc, int irq_type, bool enable);
 int amdgpu_dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
 				       struct drm_atomic_commit *state);
 #ifdef CONFIG_DEBUG_FS
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 a88175d99092..544445fbc770 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
@@ -1226,6 +1226,103 @@ static void dm_test_crtc_enable_vblank_ips_restore_replay(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
 }
 
+/* Tests for amdgpu_dm_crtc_set_vline0_irq() */
+
+/*
+ * dm_test_crtc_setup_vline0 - Build an adev/CRTC for the vline0 IRQ helper.
+ * @test: The KUnit test context
+ * @adev_out: Receives the allocated device
+ * @ip_version: DCE IP version stamped on the device (0 selects the DCE path)
+ *
+ * Returns a bare CRTC attached to the device. The IRQ subsystem is left
+ * uninstalled for callers to arm.
+ */
+static struct drm_crtc *dm_test_crtc_setup_vline0(struct kunit *test,
+						  struct amdgpu_device **adev_out,
+						  uint32_t ip_version)
+{
+	struct amdgpu_device *adev;
+	struct drm_crtc *crtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
+	crtc->dev = &adev->ddev;
+
+	adev->ip_versions[DCE_HWIP][0] = ip_version;
+
+	*adev_out = adev;
+	return crtc;
+}
+
+/**
+ * dm_test_crtc_set_vline0_irq_dce_noop - Test vline0 irq is skipped on DCE
+ * @test: The KUnit test context
+ *
+ * VLINE0 only exists on DCN+. With no DCE IP version stamped the helper must
+ * return 0 without touching the IRQ source, even though the IRQ subsystem is
+ * uninstalled (which would otherwise make amdgpu_irq_get() fail).
+ */
+static void dm_test_crtc_set_vline0_irq_dce_noop(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct drm_crtc *crtc;
+
+	crtc = dm_test_crtc_setup_vline0(test, &adev, 0);
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vline0_irq(crtc, AMDGPU_CRTC_IRQ_VBLANK1, true), 0);
+}
+
+/**
+ * dm_test_crtc_set_vline0_irq_error - Test vline0 irq failure is propagated
+ * @test: The KUnit test context
+ *
+ * On DCN with the IRQ subsystem uninstalled, amdgpu_irq_get() returns -ENOENT
+ * and the helper must propagate it.
+ */
+static void dm_test_crtc_set_vline0_irq_error(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct drm_crtc *crtc;
+
+	crtc = dm_test_crtc_setup_vline0(test, &adev, IP_VERSION(3, 5, 0));
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vline0_irq(crtc, AMDGPU_CRTC_IRQ_VBLANK1, true),
+			-ENOENT);
+}
+
+/**
+ * dm_test_crtc_set_vline0_irq_enable_disable - Test vline0 irq refcounting
+ * @test: The KUnit test context
+ *
+ * On DCN with an armed IRQ source, enabling takes a vline0 reference and
+ * disabling drops it again.
+ */
+static void dm_test_crtc_set_vline0_irq_enable_disable(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct drm_crtc *crtc;
+	atomic_t *refcount;
+
+	crtc = dm_test_crtc_setup_vline0(test, &adev, IP_VERSION(3, 5, 0));
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->vline0_irq, 1);
+	refcount = &adev->vline0_irq.enabled_types[AMDGPU_CRTC_IRQ_VBLANK1];
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vline0_irq(crtc, AMDGPU_CRTC_IRQ_VBLANK1, true), 0);
+	KUNIT_EXPECT_EQ(test, atomic_read(refcount), 2);
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vline0_irq(crtc, AMDGPU_CRTC_IRQ_VBLANK1, false), 0);
+	KUNIT_EXPECT_EQ(test, atomic_read(refcount), 1);
+}
+
 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
 
 /**
@@ -2526,6 +2623,10 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_enable_vblank_queues_work),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore_replay),
+	/* amdgpu_dm_crtc_set_vline0_irq */
+	KUNIT_CASE(dm_test_crtc_set_vline0_irq_dce_noop),
+	KUNIT_CASE(dm_test_crtc_set_vline0_irq_error),
+	KUNIT_CASE(dm_test_crtc_set_vline0_irq_enable_disable),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
 	/* amdgpu_dm_crtc_count_crtc_active_planes */
-- 
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.