[PATCH 50/59] drm/amd/display: Test DM late init

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for dm_late_init(), covering a DC without a DMCU, and
the boot time CRC init with and without a DMUB service.

[HOW]
An empty resource pool leaves the DMCU NULL and an empty link list
leaves no eDP, so the ABM configuration is skipped and only the MST
detection sweep runs. A stub reports the boot time CRC as disabled.

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 |  3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 87 +++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)

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 8b4d01d97ea4..0393ec122f26 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1183,7 +1183,7 @@ static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev)
 	}
 }
 
-static int dm_late_init(struct amdgpu_ip_block *ip_block)
+STATIC_IFN_KUNIT int dm_late_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
 
@@ -1233,6 +1233,7 @@ static int dm_late_init(struct amdgpu_ip_block *ip_block)
 
 	return amdgpu_dm_detect_mst_link_for_all_connectors(adev_to_drm(adev));
 }
+EXPORT_IF_KUNIT(dm_late_init);
 
 static void resume_mst_branch_status(struct drm_dp_mst_topology_mgr *mgr)
 {
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 80da5a378d73..c662c39416d8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1255,6 +1255,7 @@ void mmhub_read_system_context(struct amdgpu_device *adev,
 int amdgpu_dm_init_power_module(struct amdgpu_display_manager *dm);
 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);
 #endif
 
 #endif /* __AMDGPU_DM_H__ */
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 8ad6cf0eaa6c..432e4cd2803d 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
@@ -21,6 +21,7 @@
 #include <drm/drm_writeback.h>
 
 #include "dc.h"
+#include "dc/dc_dmub_srv.h"
 #include "dal_asic_id.h"
 #include "dm_services_types.h"
 #include "dmub/dmub_srv.h"
@@ -3702,6 +3703,88 @@ static void dm_test_sw_fini_releases_bounding_box(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, list_empty(&adev->dm.da_list));
 }
 
+/* Tests for dm_late_init() */
+
+/*
+ * A DC without a DMCU and with an empty link list, so the ABM configuration is
+ * skipped and only the MST detection sweep runs.
+ */
+static struct amdgpu_device *dm_test_late_init_adev(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct dc *dc = dm_kunit_alloc_dc_with_ctx(test);
+
+	dc->res_pool = kunit_kzalloc(test, sizeof(*dc->res_pool), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, dc->res_pool);
+	adev->dm.dc = dc;
+
+	return adev;
+}
+
+static int dm_test_run_late_init(struct amdgpu_device *adev)
+{
+	struct amdgpu_ip_block ip_block = { .adev = adev };
+
+	return dm_late_init(&ip_block);
+}
+
+/**
+ * dm_test_late_init_no_dmcu - Test a DC without a DMCU or DMUB
+ * @test: The KUnit test context
+ */
+static void dm_test_late_init_no_dmcu(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_test_late_init_adev(test);
+
+	KUNIT_EXPECT_EQ(test, dm_test_run_late_init(adev), 0);
+}
+
+/**
+ * dm_test_late_init_boot_crc_no_dmub - Test boot time CRC needs a DMUB service
+ * @test: The KUnit test context
+ */
+static void dm_test_late_init_boot_crc_no_dmub(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_test_late_init_adev(test);
+
+	adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 6, 0);
+
+	KUNIT_EXPECT_EQ(test, dm_test_run_late_init(adev), 0);
+	KUNIT_EXPECT_NULL(test, adev->dm.boot_time_crc_info.bo_ptr);
+}
+
+static union dmub_fw_boot_options dm_test_fw_boot_options;
+
+static union dmub_fw_boot_options dm_test_get_fw_boot_option(struct dmub_srv *dmub)
+{
+	return dm_test_fw_boot_options;
+}
+
+/**
+ * dm_test_late_init_boot_crc_disabled - Test a disabled boot time CRC allocates nothing
+ * @test: The KUnit test context
+ */
+static void dm_test_late_init_boot_crc_disabled(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_test_late_init_adev(test);
+	struct dc_dmub_srv *dmub_srv;
+	struct dmub_srv *dmub;
+
+	dmub_srv = kunit_kzalloc(test, sizeof(*dmub_srv), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, dmub_srv);
+	dmub = kunit_kzalloc(test, sizeof(*dmub), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, dmub);
+
+	dm_test_fw_boot_options.bits.bootcrc_en_at_S0i3 = 0;
+	dmub->hw_funcs.get_fw_boot_option = dm_test_get_fw_boot_option;
+	dmub_srv->dmub = dmub;
+	adev->dm.dc->ctx->dmub_srv = dmub_srv;
+	adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 6, 0);
+
+	KUNIT_EXPECT_EQ(test, dm_test_run_late_init(adev), 0);
+	KUNIT_EXPECT_NULL(test, adev->dm.boot_time_crc_info.bo_ptr);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -3891,6 +3974,10 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	/* dm_sw_init / dm_sw_fini */
 	KUNIT_CASE(dm_test_sw_init_no_dmub),
 	KUNIT_CASE(dm_test_sw_fini_releases_bounding_box),
+	/* dm_late_init */
+	KUNIT_CASE(dm_test_late_init_no_dmcu),
+	KUNIT_CASE(dm_test_late_init_boot_crc_no_dmub),
+	KUNIT_CASE(dm_test_late_init_boot_crc_disabled),
 	{}
 };
 
-- 
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.