From: Alex Hung <[email protected]>

[Why]
Add KUnit tests for manage_dm_interrupts(), covering the off delay
derived from the stream timing, the 30ms fallback, the DCN3.5 APU
instant off, and the vblank disable path.

[How]
The IRQ subsystem is not installed, so amdgpu_irq_get() and
amdgpu_irq_put() only report the missing source; the point is that the
affected DCN versions request it at all.

Assisted-by: Copilot:Claude-Opus-5 GPT-5.6 Sol
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Ray Wu <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   7 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   2 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 116 ++++++++++++++++++
 3 files changed, 122 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 f49cc198fb0d..e793dd0426b1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3374,9 +3374,9 @@ STATIC_IFN_KUNIT int 
dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_commit *
 }
 EXPORT_IF_KUNIT(dm_update_mst_vcpi_slots_for_dsc);
 
-static void manage_dm_interrupts(struct amdgpu_device *adev,
-                                struct amdgpu_crtc *acrtc,
-                                struct dm_crtc_state *acrtc_state)
+STATIC_IFN_KUNIT void manage_dm_interrupts(struct amdgpu_device *adev,
+                                          struct amdgpu_crtc *acrtc,
+                                          struct dm_crtc_state *acrtc_state)
 {      /*
         * We cannot be sure that the frontend index maps to the same
         * backend index - some even map to more than one.
@@ -3455,6 +3455,7 @@ static void manage_dm_interrupts(struct amdgpu_device 
*adev,
                drm_crtc_vblank_off(&acrtc->base);
        }
 }
+EXPORT_IF_KUNIT(manage_dm_interrupts);
 
 STATIC_IFN_KUNIT void dm_update_pflip_irq_state(struct amdgpu_device *adev,
                                                struct amdgpu_crtc *acrtc)
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 089741ba0619..ad72dc182e93 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1264,6 +1264,8 @@ int fill_dc_plane_info_and_addr(struct amdgpu_device 
*adev,
                                struct dc_plane_address *address, bool 
tmz_surface);
 int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_commit *state, struct 
dc_state *dc_state,
                                     struct dsc_mst_fairness_vars *vars);
+void manage_dm_interrupts(struct amdgpu_device *adev, struct amdgpu_crtc 
*acrtc,
+                         struct dm_crtc_state *acrtc_state);
 int load_dmcu_fw(struct amdgpu_device *adev);
 int dm_sw_init(struct amdgpu_ip_block *ip_block);
 int dm_late_init(struct amdgpu_ip_block *ip_block);
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 a67774e6db36..4daa187fbd0a 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
@@ -3803,6 +3803,117 @@ static void 
dm_test_plane_info_layer_and_blending(struct kunit *test)
        KUNIT_EXPECT_EQ(test, ctx->plane_info.global_alpha_value, 0x7f);
 }
 
+/* Tests for manage_dm_interrupts() */
+
+struct dm_test_irq_mgmt_ctx {
+       struct amdgpu_device *adev;
+       struct amdgpu_crtc *acrtc;
+       struct dm_crtc_state *acrtc_state;
+};
+
+/*
+ * A CRTC with a single initialised vblank and a 1080p60 stream timing, which
+ * is what the vblank off-delay estimate is derived from.
+ */
+static struct dm_test_irq_mgmt_ctx *dm_test_irq_mgmt_ctx_alloc(struct kunit 
*test)
+{
+       struct dm_test_irq_mgmt_ctx *ctx;
+       struct dc_crtc_timing *timing;
+
+       ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       ctx->adev = dm_kunit_alloc_adev(test);
+       KUNIT_ASSERT_EQ(test, drm_vblank_init(&ctx->adev->ddev, 1), 0);
+
+       ctx->acrtc = kunit_kzalloc(test, sizeof(*ctx->acrtc), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc);
+       ctx->acrtc_state = kunit_kzalloc(test, sizeof(*ctx->acrtc_state), 
GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc_state);
+
+       ctx->adev->mode_info.num_crtc = 1;
+       ctx->acrtc->base.dev = &ctx->adev->ddev;
+       ctx->acrtc->crtc_id = 0;
+
+       ctx->acrtc_state->stream = dm_kunit_alloc_stream(test, NULL);
+       timing = &ctx->acrtc_state->stream->timing;
+       timing->h_total = 2200;
+       timing->v_total = 1125;
+       timing->pix_clk_100hz = 1485000;
+
+       return ctx;
+}
+
+/**
+ * dm_test_manage_interrupts_offdelay - Test the off delay is derived from 
timing
+ * @test: The KUnit test context
+ *
+ * DCN3.0 also takes the extra vupdate reference. The IRQ subsystem is not
+ * installed, so amdgpu_irq_get() only reports the missing source.
+ */
+static void dm_test_manage_interrupts_offdelay(struct kunit *test)
+{
+       struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test);
+
+       /* Pre-DCN3.5 keeps the two frame off delay. */
+       ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 0, 0);
+
+       manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state);
+
+       KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 34);
+       KUNIT_EXPECT_FALSE(test, 
ctx->adev->ddev.vblank[0].config.disable_immediate);
+}
+
+/**
+ * dm_test_manage_interrupts_offdelay_fallback - Test a zero delay falls back 
to 30ms
+ * @test: The KUnit test context
+ */
+static void dm_test_manage_interrupts_offdelay_fallback(struct kunit *test)
+{
+       struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test);
+
+       ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 1, 2);
+       /* A zero line count makes the computed delay round down to zero. */
+       ctx->acrtc_state->stream->timing.v_total = 0;
+
+       manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state);
+
+       KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 30);
+}
+
+/**
+ * dm_test_manage_interrupts_apu_instant_off - Test DCN3.5 APUs use instant off
+ * @test: The KUnit test context
+ */
+static void dm_test_manage_interrupts_apu_instant_off(struct kunit *test)
+{
+       struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test);
+
+       ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 5, 0);
+       ctx->adev->flags |= AMD_IS_APU;
+
+       manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state);
+
+       KUNIT_EXPECT_EQ(test, ctx->adev->ddev.vblank[0].config.offdelay_ms, 1);
+       KUNIT_EXPECT_TRUE(test, 
ctx->adev->ddev.vblank[0].config.disable_immediate);
+}
+
+/**
+ * dm_test_manage_interrupts_disable - Test a NULL CRTC state turns vblank off
+ * @test: The KUnit test context
+ */
+static void dm_test_manage_interrupts_disable(struct kunit *test)
+{
+       struct dm_test_irq_mgmt_ctx *ctx = dm_test_irq_mgmt_ctx_alloc(test);
+
+       ctx->adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 0, 0);
+       manage_dm_interrupts(ctx->adev, ctx->acrtc, ctx->acrtc_state);
+
+       manage_dm_interrupts(ctx->adev, ctx->acrtc, NULL);
+
+       KUNIT_EXPECT_FALSE(test, ctx->adev->ddev.vblank[0].enabled);
+}
+
 /* Tests for dm_early_init() */
 
 #define DM_TEST_ATOM_BIOS_SIZE 512
@@ -4725,6 +4836,11 @@ static struct kunit_case amdgpu_dm_tests[] = {
        KUNIT_CASE(dm_test_plane_info_bad_color_encoding),
        KUNIT_CASE(dm_test_plane_info_rotations),
        KUNIT_CASE(dm_test_plane_info_layer_and_blending),
+       /* manage_dm_interrupts */
+       KUNIT_CASE(dm_test_manage_interrupts_offdelay),
+       KUNIT_CASE(dm_test_manage_interrupts_offdelay_fallback),
+       KUNIT_CASE(dm_test_manage_interrupts_apu_instant_off),
+       KUNIT_CASE(dm_test_manage_interrupts_disable),
        /* dm_early_init */
        KUNIT_CASE(dm_test_early_init_no_object_header),
        KUNIT_CASE(dm_test_early_init_legacy_asics),
-- 
2.43.0

Reply via email to