[PATCH 48/59] drm/amd/display: Test DMCU firmware load

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for load_dmcu_fw(), covering the ASICs and DCN IP
versions without a DMCU, an unsupported IP version, the three Raven
revisions, and a missing firmware image.

[HOW]
No firmware is installed in the test environment, so
amdgpu_ucode_request() reports -ENODEV and the missing image is treated
as non-fatal.

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  | 101 ++++++++++++++++++
 3 files changed, 104 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 3d2a9e014797..128b12a945fc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -967,7 +967,7 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 	mutex_destroy(&adev->dm.dpia_aux_lock);
 }
 
-static int load_dmcu_fw(struct amdgpu_device *adev)
+STATIC_IFN_KUNIT int load_dmcu_fw(struct amdgpu_device *adev)
 {
 	const char *fw_name_dmcu = NULL;
 	int r;
@@ -1077,6 +1077,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
 
 	return 0;
 }
+EXPORT_IF_KUNIT(load_dmcu_fw);
 
 static int dm_sw_init(struct amdgpu_ip_block *ip_block)
 {
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 5e9d0b203a0f..858fe967046b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1253,6 +1253,7 @@ struct dc_phy_addr_space_config;
 void mmhub_read_system_context(struct amdgpu_device *adev,
 			       struct dc_phy_addr_space_config *pa_config);
 int amdgpu_dm_init_power_module(struct amdgpu_display_manager *dm);
+int load_dmcu_fw(struct amdgpu_device *adev);
 #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 d1a25b3e68c5..f0cd2de97faf 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 "dal_asic_id.h"
 #include "dm_services_types.h"
 #include "dmub/dmub_srv.h"
 #include "inc/core_types.h"
@@ -3559,6 +3560,100 @@ static void dm_test_init_power_module_alloc_failure(struct kunit *test)
 	KUNIT_EXPECT_NULL(test, adev->dm.power_module);
 }
 
+/* Tests for load_dmcu_fw() */
+
+/**
+ * dm_test_load_dmcu_fw_no_dmcu - Test ASICs and IP versions without a DMCU
+ * @test: The KUnit test context
+ */
+static void dm_test_load_dmcu_fw_no_dmcu(struct kunit *test)
+{
+	static const enum amd_asic_type cases[] = {
+		CHIP_BONAIRE, CHIP_HAWAII, CHIP_KAVERI, CHIP_KABINI, CHIP_MULLINS,
+		CHIP_TONGA, CHIP_FIJI, CHIP_CARRIZO, CHIP_STONEY, CHIP_POLARIS11,
+		CHIP_POLARIS10, CHIP_POLARIS12, CHIP_VEGAM, CHIP_VEGA10,
+		CHIP_VEGA12, CHIP_VEGA20,
+	};
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cases); i++) {
+		adev->asic_type = cases[i];
+
+		KUNIT_EXPECT_EQ_MSG(test, load_dmcu_fw(adev), 0, "asic_type %d",
+				    cases[i]);
+		KUNIT_EXPECT_NULL(test, adev->dm.fw_dmcu);
+	}
+}
+
+/**
+ * dm_test_load_dmcu_fw_dcn - Test DCN IP versions report no DMCU firmware
+ * @test: The KUnit test context
+ */
+static void dm_test_load_dmcu_fw_dcn(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	adev->asic_type = CHIP_IP_DISCOVERY;
+	adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 5, 0);
+
+	KUNIT_EXPECT_EQ(test, load_dmcu_fw(adev), 0);
+	KUNIT_EXPECT_NULL(test, adev->dm.fw_dmcu);
+}
+
+/**
+ * dm_test_load_dmcu_fw_unsupported - Test an unknown IP version is rejected
+ * @test: The KUnit test context
+ */
+static void dm_test_load_dmcu_fw_unsupported(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	adev->asic_type = CHIP_IP_DISCOVERY;
+	adev->ip_versions[DCE_HWIP][0] = IP_VERSION(9, 9, 9);
+
+	KUNIT_EXPECT_EQ(test, load_dmcu_fw(adev), -EINVAL);
+}
+
+/**
+ * dm_test_load_dmcu_fw_raven - Test the Raven revision selects a DMCU
+ * @test: The KUnit test context
+ */
+static void dm_test_load_dmcu_fw_raven(struct kunit *test)
+{
+	static const u32 cases[] = { PICASSO_A0, RAVEN2_A0, 0 };
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	unsigned int i;
+
+	adev->asic_type = CHIP_RAVEN;
+	adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
+
+	/* Picasso and Raven2 name a DMCU; a bare Raven has none. */
+	for (i = 0; i < ARRAY_SIZE(cases); i++) {
+		adev->external_rev_id = cases[i];
+
+		KUNIT_EXPECT_EQ_MSG(test, load_dmcu_fw(adev), 0, "rev 0x%x",
+				    cases[i]);
+	}
+}
+
+/**
+ * dm_test_load_dmcu_fw_missing_firmware - Test a missing DMCU image is not fatal
+ * @test: The KUnit test context
+ */
+static void dm_test_load_dmcu_fw_missing_firmware(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	adev->dev = adev->ddev.dev;
+	adev->asic_type = CHIP_NAVI12;
+	adev->firmware.load_type = AMDGPU_FW_LOAD_PSP;
+
+	/* No firmware is installed in the test environment. */
+	KUNIT_EXPECT_EQ(test, load_dmcu_fw(adev), 0);
+	KUNIT_EXPECT_NULL(test, adev->dm.fw_dmcu);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -3739,6 +3834,12 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	/* amdgpu_dm_init_power_module */
 	KUNIT_CASE(dm_test_init_power_module_no_edp),
 	KUNIT_CASE(dm_test_init_power_module_alloc_failure),
+	/* load_dmcu_fw */
+	KUNIT_CASE(dm_test_load_dmcu_fw_no_dmcu),
+	KUNIT_CASE(dm_test_load_dmcu_fw_dcn),
+	KUNIT_CASE(dm_test_load_dmcu_fw_unsupported),
+	KUNIT_CASE(dm_test_load_dmcu_fw_raven),
+	KUNIT_CASE(dm_test_load_dmcu_fw_missing_firmware),
 	{}
 };
 
-- 
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.