From: Alex Hung <[email protected]>
[WHAT]
Add KUnit tests for amdgpu_dm_dce110_register_irq_handlers() covering
the SOC15 DCE client used from Vega on, the amdgpu_irq_add_id()
rejections for the CRTC, VUPDATE and HPD sources, and the
invalid-source guards in the VBLANK, VUPDATE and PFLIP loops.
[HOW]
Add three fake IRQ services that map only a prefix of the source IDs so
each loop reaches its guard in turn. Clearing a single amdgpu_irq_src's
funcs makes only that source's add_id() fail.
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 | 196 ++++++++++++++++++
1 file changed, 196 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 933a33a360fbe..a354fa25998f7 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
@@ -276,6 +276,55 @@ static const struct irq_service_funcs dm_test_irq_service_funcs_dce110 = {
.to_dal_irq_source = dm_test_to_dal_irq_source_dce110
};
+/* Maps nothing, so the first (VBLANK) register loop sees an invalid source. */
+static enum dc_irq_source dm_test_to_dal_irq_source_unmapped(
+ struct irq_service *irq_service,
+ uint32_t src_id,
+ uint32_t ext_id)
+{
+ return DC_IRQ_SOURCE_INVALID;
+}
+
+static const struct irq_service_funcs dm_test_irq_service_funcs_unmapped = {
+ .to_dal_irq_source = dm_test_to_dal_irq_source_unmapped
+};
+
+/* Maps VBLANK only, so the VUPDATE register loop sees an invalid source. */
+static enum dc_irq_source dm_test_to_dal_irq_source_vblank_only(
+ struct irq_service *irq_service,
+ uint32_t src_id,
+ uint32_t ext_id)
+{
+ if (src_id == VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0)
+ return DC_IRQ_SOURCE_VBLANK1;
+
+ return DC_IRQ_SOURCE_INVALID;
+}
+
+static const struct irq_service_funcs dm_test_irq_service_funcs_vblank_only = {
+ .to_dal_irq_source = dm_test_to_dal_irq_source_vblank_only
+};
+
+/* Maps everything but PFLIP, so the PFLIP register loop sees an invalid source. */
+static enum dc_irq_source dm_test_to_dal_irq_source_no_pflip(
+ struct irq_service *irq_service,
+ uint32_t src_id,
+ uint32_t ext_id)
+{
+ switch (src_id) {
+ case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
+ return DC_IRQ_SOURCE_VBLANK1;
+ case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
+ return DC_IRQ_SOURCE_VUPDATE1;
+ default:
+ return DC_IRQ_SOURCE_INVALID;
+ }
+}
+
+static const struct irq_service_funcs dm_test_irq_service_funcs_no_pflip = {
+ .to_dal_irq_source = dm_test_to_dal_irq_source_no_pflip
+};
+
static enum dc_irq_source dm_test_to_dal_irq_source_dcn10(
struct irq_service *irq_service,
uint32_t src_id,
@@ -4266,6 +4315,146 @@ static void dm_test_dce110_register_irq_handlers_one_crtc(struct kunit *test)
amdgpu_dm_irq_fini(adev);
}
+/**
+ * dm_test_dce110_register_irq_handlers_soc15_client - Test DCE110 on AI+ ASICs
+ * @test: The KUnit test context
+ *
+ * From Vega on, the DCE interrupts are routed through the SOC15 DCE client
+ * rather than the legacy one, so the IRQ sources must be registered there.
+ */
+static void dm_test_dce110_register_irq_handlers_soc15_client(struct kunit *test)
+{
+ struct amdgpu_irq_src **soc15_sources;
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_dce110);
+ adev->family = AMDGPU_FAMILY_AI;
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), 0);
+
+ KUNIT_EXPECT_NULL(test, adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources);
+ soc15_sources = adev->irq.client[SOC15_IH_CLIENTID_DCE].sources;
+ KUNIT_ASSERT_NOT_NULL(test, soc15_sources);
+ KUNIT_EXPECT_PTR_EQ(test,
+ soc15_sources[VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0],
+ &adev->crtc_irq);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_crtc_add_id_fails - Test add-id failure
+ * @test: The KUnit test context
+ *
+ * amdgpu_irq_add_id() rejects a source with no funcs table, so registering the
+ * VBLANK interrupt before amdgpu_dm_set_irq_funcs() has run must fail.
+ */
+static void dm_test_dce110_register_irq_handlers_crtc_add_id_fails(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+ struct dc *dc;
+
+ adev = dm_kunit_alloc_adev(test);
+ dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dce110);
+ dc->ctx->dce_version = DCE_VERSION_11_0;
+ adev->dm.dc = dc;
+ adev->mode_info.num_crtc = 1;
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_bad_vblank_source - Test VBLANK guard
+ * @test: The KUnit test context
+ *
+ * A source ID that DC does not map to a VBLANK IRQ source must be rejected
+ * rather than used to index the vblank parameter array.
+ */
+static void dm_test_dce110_register_irq_handlers_bad_vblank_source(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_unmapped);
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_bad_vupdate_source - Test VUPDATE guard
+ * @test: The KUnit test context
+ *
+ * With VBLANK mapped but VUPDATE unmapped, registration must fail once the
+ * VUPDATE loop sees the invalid source.
+ */
+static void dm_test_dce110_register_irq_handlers_bad_vupdate_source(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_vblank_only);
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_bad_pflip_source - Test PFLIP guard
+ * @test: The KUnit test context
+ *
+ * With VBLANK and VUPDATE mapped but PFLIP unmapped, registration must fail
+ * once the pageflip loop sees the invalid source.
+ */
+static void dm_test_dce110_register_irq_handlers_bad_pflip_source(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_no_pflip);
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_vupdate_add_id_fails - Test add-id failure
+ * @test: The KUnit test context
+ *
+ * The VBLANK loop succeeds, then a VUPDATE source with no funcs table is
+ * rejected by amdgpu_irq_add_id().
+ */
+static void dm_test_dce110_register_irq_handlers_vupdate_add_id_fails(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_dce110);
+ adev->vupdate_irq.funcs = NULL;
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
+/**
+ * dm_test_dce110_register_irq_handlers_hpd_add_id_fails - Test HPD add-id failure
+ * @test: The KUnit test context
+ *
+ * All three per-CRTC loops succeed, then the HPD source with no funcs table is
+ * rejected by amdgpu_irq_add_id().
+ */
+static void dm_test_dce110_register_irq_handlers_hpd_add_id_fails(struct kunit *test)
+{
+ struct amdgpu_device *adev;
+
+ adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_dce110);
+ adev->hpd_irq.funcs = NULL;
+
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL);
+
+ amdgpu_dm_irq_fini(adev);
+}
+
/**
* dm_test_dcn10_register_irq_handlers_zero_crtc - Test DCN10 zero-CRTC registration
* @test: The KUnit test context
@@ -4673,6 +4862,13 @@ static struct kunit_case amdgpu_dm_irq_tests[] = {
/* IRQ handler registration helpers */
KUNIT_CASE(dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources),
KUNIT_CASE(dm_test_dce110_register_irq_handlers_one_crtc),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_soc15_client),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_crtc_add_id_fails),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_bad_vblank_source),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_bad_vupdate_source),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_bad_pflip_source),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_vupdate_add_id_fails),
+ KUNIT_CASE(dm_test_dce110_register_irq_handlers_hpd_add_id_fails),
KUNIT_CASE(dm_test_dcn10_register_irq_handlers_zero_crtc),
KUNIT_CASE(dm_test_dcn10_register_irq_handlers_one_crtc),
KUNIT_CASE(dm_test_register_outbox_irq_handlers_without_dmub),
--
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.