From: Alex Hung <[email protected]>
[WHAT]
Add KUnit tests for schedule_dc_vmin_vmax(), which had no coverage. Both
callers are exercised: dm_crtc_high_irq() on an AI+ family and the DCE
path of dm_vupdate_high_irq() on a pre-DCE12 family.
[HOW]
Add a dm_test_setup_vmin_vmax_crtc() fixture building a CRTC with an
active VRR stream and a vmin/vmax work queue. Each test flushes the
queue and checks the worker applied the adjust and dropped its stream
reference.
Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
.../amdgpu_dm/tests/amdgpu_dm_irq_test.c | 114 ++++++++++++++++++
1 file changed, 114 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
index 4cb52093987f3..b398be878c932 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
@@ -3450,6 +3450,83 @@ static void dm_test_vupdate_high_irq_dcn_no_active_planes(struct kunit *test)
KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE);
}
+/*
+ * Build a CRTC with an active VRR stream on a device whose vmin/vmax updates
+ * are offloaded to adev->dm.vmin_vmax_wq, seeded with the given timing adjust.
+ * Caller sets adev->family to select the DCE or DCN path, then invokes the
+ * handler and flushes the queue.
+ */
+static struct amdgpu_crtc *dm_test_setup_vmin_vmax_crtc(struct kunit *test,
+ unsigned int v_total_min,
+ unsigned int v_total_max)
+{
+ struct dc_stream_state *stream;
+ struct amdgpu_device *adev;
+ struct amdgpu_crtc *acrtc;
+ struct dc_link *link;
+ struct dc *dc;
+
+ adev = dm_kunit_alloc_adev(test);
+ mutex_init(&adev->dm.dc_lock);
+ KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+ KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
+
+ dc = dm_kunit_alloc_dc_with_ctx(test);
+ dc->current_state = kunit_kzalloc(test, sizeof(*dc->current_state),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc->current_state);
+ adev->dm.dc = dc;
+
+ link = dm_kunit_alloc_link(test);
+ stream = dm_kunit_alloc_stream(test, link);
+
+ acrtc = dm_test_add_crtc(test, adev);
+ /* VRR active so the !vrr_active vblank handler is skipped. */
+ acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+ acrtc->dm_irq_params.stream = stream;
+ acrtc->dm_irq_params.vrr_params.adjust.v_total_min = v_total_min;
+ acrtc->dm_irq_params.vrr_params.adjust.v_total_max = v_total_max;
+
+ return acrtc;
+}
+
+/**
+ * dm_test_vupdate_high_irq_dce_vrr_btr - Test DCE vupdate BTR handling
+ * @test: The KUnit test context
+ *
+ * On DCE (zero DCE IP version) with VRR active and a pre-DCE12 family, vupdate
+ * runs the below-the-range section: it handles the vblank and offloads the
+ * vmin/vmax update, which the worker then applies to the stream.
+ */
+static void dm_test_vupdate_high_irq_dce_vrr_btr(struct kunit *test)
+{
+ struct common_irq_params params = { 0 };
+ struct dc_stream_state *stream;
+ struct amdgpu_device *adev;
+ struct amdgpu_crtc *acrtc;
+
+ acrtc = dm_test_setup_vmin_vmax_crtc(test, 2000, 2200);
+ adev = drm_to_adev(acrtc->base.dev);
+ stream = acrtc->dm_irq_params.stream;
+ /* Pre-AI family so the BTR block inside the DCE path runs. */
+ adev->family = AMDGPU_FAMILY_SI;
+
+ adev->ddev.vblank[0].time = ktime_get();
+
+ params.adev = adev;
+ params.irq_src = (enum dc_irq_source)IRQ_TYPE_VUPDATE;
+
+ dm_vupdate_high_irq(¶ms);
+
+ /* The offloaded worker applies the adjust and drops its stream ref. */
+ flush_workqueue(adev->dm.vmin_vmax_wq);
+ KUNIT_EXPECT_EQ(test, stream->adjust.v_total_min, 2000);
+ KUNIT_EXPECT_EQ(test, stream->adjust.v_total_max, 2200);
+ KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
/**
* dm_test_crtc_high_irq_no_crtc - Test crtc high IRQ with no CRTC
* @test: The KUnit test context
@@ -3619,6 +3696,41 @@ static void dm_test_crtc_high_irq_writeback_completes(struct kunit *test)
KUNIT_EXPECT_FALSE(test, acrtc->wb_frame_done);
}
+/**
+ * dm_test_crtc_high_irq_schedules_vmin_vmax - Test the freesync BTR update
+ * @test: The KUnit test context
+ *
+ * On an AI+ family with an active VRR stream, the handler must run the freesync
+ * v-update and offload the vmin/vmax programming, which the worker then applies
+ * to the stream.
+ */
+static void dm_test_crtc_high_irq_schedules_vmin_vmax(struct kunit *test)
+{
+ struct common_irq_params params = { 0 };
+ struct dc_stream_state *stream;
+ struct amdgpu_device *adev;
+ struct amdgpu_crtc *acrtc;
+
+ acrtc = dm_test_setup_vmin_vmax_crtc(test, 1000, 1100);
+ adev = drm_to_adev(acrtc->base.dev);
+ stream = acrtc->dm_irq_params.stream;
+ adev->family = AMDGPU_FAMILY_AI;
+ acrtc->dm_irq_params.vrr_params.supported = true;
+
+ params.adev = adev;
+ params.irq_src = (enum dc_irq_source)IRQ_TYPE_VBLANK;
+
+ dm_crtc_high_irq(¶ms);
+
+ /* The offloaded worker applies the adjust and drops its stream ref. */
+ flush_workqueue(adev->dm.vmin_vmax_wq);
+ KUNIT_EXPECT_EQ(test, stream->adjust.v_total_min, 1000);
+ KUNIT_EXPECT_EQ(test, stream->adjust.v_total_max, 1100);
+ KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
/* Tests for dm_handle_hpd_work() */
/**
@@ -4246,11 +4358,13 @@ static struct kunit_case amdgpu_dm_irq_tests[] = {
KUNIT_CASE(dm_test_vupdate_high_irq_no_crtc),
KUNIT_CASE(dm_test_vupdate_high_irq_dcn_completes_flip),
KUNIT_CASE(dm_test_vupdate_high_irq_dcn_no_active_planes),
+ KUNIT_CASE(dm_test_vupdate_high_irq_dce_vrr_btr),
KUNIT_CASE(dm_test_crtc_high_irq_no_crtc),
KUNIT_CASE(dm_test_crtc_high_irq_vrr_pre_ai),
KUNIT_CASE(dm_test_crtc_high_irq_vrr_ai_no_stream),
KUNIT_CASE(dm_test_crtc_high_irq_writeback_disables),
KUNIT_CASE(dm_test_crtc_high_irq_writeback_completes),
+ KUNIT_CASE(dm_test_crtc_high_irq_schedules_vmin_vmax),
/* dm_handle_hpd_work */
KUNIT_CASE(dm_test_handle_hpd_work_out_of_range),
/* dm_dmub_outbox1_low_irq */
--
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.