From: Bhawanpreet Lakha <[email protected]>

Add KUnit coverage for hdmi_cec_unset_edid(), create_eml_sink() and
handle_edid_mgmt(): unset edid with no notifier, eml sink with no
edid, and DP vs non-DP edid management link caps handling.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Wayne Lin <[email protected]>
---
 .../display/amdgpu_dm/amdgpu_dm_connector.c   |   9 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |   3 +
 .../tests/amdgpu_dm_connector_test.c          | 119 ++++++++++++++++++
 3 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index a4648acde71b..6d358cb84961 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -334,7 +334,7 @@ int amdgpu_dm_detect_mst_link_for_all_connectors(struct 
drm_device *dev)
 }
 EXPORT_IF_KUNIT(amdgpu_dm_detect_mst_link_for_all_connectors);
 
-static void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
+STATIC_IFN_KUNIT void hdmi_cec_unset_edid(struct amdgpu_dm_connector 
*aconnector)
 {
        struct cec_notifier *n = aconnector->notifier;
 
@@ -343,6 +343,7 @@ static void hdmi_cec_unset_edid(struct amdgpu_dm_connector 
*aconnector)
 
        cec_notifier_phys_addr_invalidate(n);
 }
+EXPORT_IF_KUNIT(hdmi_cec_unset_edid);
 
 void amdgpu_dm_hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector)
 {
@@ -1969,7 +1970,7 @@ static int get_modes(struct drm_connector *connector)
        return amdgpu_dm_connector_get_modes(connector);
 }
 
-static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
+STATIC_IFN_KUNIT void create_eml_sink(struct amdgpu_dm_connector *aconnector)
 {
        struct drm_connector *connector = &aconnector->base;
        struct dc_link *dc_link = aconnector->dc_link;
@@ -2014,8 +2015,9 @@ static void create_eml_sink(struct amdgpu_dm_connector 
*aconnector)
                        dc_sink_retain(aconnector->dc_sink);
        }
 }
+EXPORT_IF_KUNIT(create_eml_sink);
 
-static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
+STATIC_IFN_KUNIT void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
 {
        struct dc_link *link = (struct dc_link *)aconnector->dc_link;
 
@@ -2030,6 +2032,7 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector 
*aconnector)
 
        create_eml_sink(aconnector);
 }
+EXPORT_IF_KUNIT(handle_edid_mgmt);
 
 static enum dc_status dm_validate_stream_and_context(struct dc *dc,
                                                struct dc_stream_state *stream)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
index a5fff31b23bf..f7ec4b906e13 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
@@ -146,6 +146,9 @@ int amdgpu_dm_encoder_init(struct drm_device *dev,
                           uint32_t link_index);
 
 #if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector);
+void create_eml_sink(struct amdgpu_dm_connector *aconnector);
+void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector);
 void dm_encoder_helper_disable(struct drm_encoder *encoder);
 int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
                                   struct drm_crtc_state *crtc_state,
diff --git 
a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 441180d427c9..59f2f8235486 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -4267,6 +4267,118 @@ static void 
dm_test_atomic_check_non_mst_returns_zero(struct kunit *test)
                                               &ctx->dm_state->base), 0);
 }
 
+/* Tests for hdmi_cec_unset_edid() */
+
+/**
+ * dm_test_hdmi_cec_unset_edid_no_notifier - Test the no-notifier no-op path
+ * @test: The KUnit test context
+ *
+ * With aconnector->notifier NULL the function returns early and must not 
crash.
+ */
+static void dm_test_hdmi_cec_unset_edid_no_notifier(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconnector;
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+
+       hdmi_cec_unset_edid(aconnector);
+}
+
+/* Tests for create_eml_sink() and handle_edid_mgmt() */
+
+/*
+ * create_eml_sink() reads EDID off the connector's DDC. Forcing the connector
+ * DRM_FORCE_OFF makes drm_edid_read_ddc() return NULL before touching any i2c
+ * adapter, exercising the "no EDID" branch without real hardware. aux_mode is
+ * set so the embedded DP AUX ddc is selected (no i2c adapter pointer needed).
+ */
+struct dm_test_edid_ctx {
+       struct drm_device *drm;
+       struct amdgpu_dm_connector *aconnector;
+       struct dc_link *link;
+};
+
+static struct dm_test_edid_ctx *
+dm_test_edid_ctx_alloc(struct kunit *test, int connector_type)
+{
+       struct dm_test_edid_ctx *ctx;
+
+       ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+       ctx->drm = dm_test_alloc_drm(test);
+       ctx->aconnector = dm_test_add_connector(test, ctx->drm, connector_type);
+
+       ctx->link = kunit_kzalloc(test, sizeof(*ctx->link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, ctx->link);
+       ctx->link->aux_mode = true;
+       ctx->aconnector->dc_link = ctx->link;
+
+       ctx->aconnector->base.force = DRM_FORCE_OFF;
+
+       return ctx;
+}
+
+/**
+ * dm_test_create_eml_sink_no_edid - Test the no-EDID branch creates no sink
+ * @test: The KUnit test context
+ *
+ * When no EDID can be read the function logs an error and returns without
+ * allocating an emulated sink.
+ */
+static void dm_test_create_eml_sink_no_edid(struct kunit *test)
+{
+       struct dm_test_edid_ctx *ctx =
+               dm_test_edid_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort);
+
+       create_eml_sink(ctx->aconnector);
+
+       KUNIT_EXPECT_NULL(test, ctx->aconnector->dc_em_sink);
+}
+
+/**
+ * dm_test_handle_edid_mgmt_dp_sets_link_caps - Test DP seeds verified link 
caps
+ * @test: The KUnit test context
+ *
+ * For a DisplayPort link the function primes verified_link_cap before reading
+ * EDID so a headless force-on connector can still modeset.
+ */
+static void dm_test_handle_edid_mgmt_dp_sets_link_caps(struct kunit *test)
+{
+       struct dm_test_edid_ctx *ctx =
+               dm_test_edid_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort);
+
+       ctx->link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
+
+       handle_edid_mgmt(ctx->aconnector);
+
+       KUNIT_EXPECT_EQ(test, (int)ctx->link->verified_link_cap.lane_count,
+                       (int)LANE_COUNT_FOUR);
+       KUNIT_EXPECT_EQ(test, (int)ctx->link->verified_link_cap.link_rate,
+                       (int)LINK_RATE_HIGH2);
+       KUNIT_EXPECT_NULL(test, ctx->aconnector->dc_em_sink);
+}
+
+/**
+ * dm_test_handle_edid_mgmt_non_dp_leaves_caps - Test non-DP links keep zeroed 
caps
+ * @test: The KUnit test context
+ *
+ * A non-DisplayPort link skips the verified_link_cap seeding entirely.
+ */
+static void dm_test_handle_edid_mgmt_non_dp_leaves_caps(struct kunit *test)
+{
+       struct dm_test_edid_ctx *ctx =
+               dm_test_edid_ctx_alloc(test, DRM_MODE_CONNECTOR_HDMIA);
+
+       ctx->link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
+
+       handle_edid_mgmt(ctx->aconnector);
+
+       KUNIT_EXPECT_EQ(test, (int)ctx->link->verified_link_cap.lane_count, 0);
+       KUNIT_EXPECT_EQ(test, (int)ctx->link->verified_link_cap.link_rate, 0);
+}
+
 static struct kunit_case amdgpu_dm_connector_tests[] = {
        /* get_subconnector_type */
        KUNIT_CASE(dm_test_subconnector_type_none),
@@ -4489,6 +4601,13 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
        KUNIT_CASE(dm_test_atomic_check_edp_native_keeps_scaling),
        KUNIT_CASE(dm_test_atomic_check_lvds_non_native_enables_scaling),
        KUNIT_CASE(dm_test_atomic_check_non_mst_returns_zero),
+       /* hdmi_cec_unset_edid */
+       KUNIT_CASE(dm_test_hdmi_cec_unset_edid_no_notifier),
+       /* create_eml_sink */
+       KUNIT_CASE(dm_test_create_eml_sink_no_edid),
+       /* handle_edid_mgmt */
+       KUNIT_CASE(dm_test_handle_edid_mgmt_dp_sets_link_caps),
+       KUNIT_CASE(dm_test_handle_edid_mgmt_non_dp_leaves_caps),
        {}
 };
 
-- 
2.43.0

Reply via email to