From: Bhawanpreet Lakha <[email protected]>

Add KUnit coverage for connector mode validation and HDMI CEC:
mode_valid rejects interlaced and doublescan modes, set_edid with no
notifier, and the S3 suspend/resume CEC handlers.

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   |   3 +
 .../tests/amdgpu_dm_connector_test.c          | 105 ++++++++++++++++++
 2 files changed, 108 insertions(+)

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 72c12484d218..3fa2392549eb 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
@@ -356,6 +356,7 @@ void amdgpu_dm_hdmi_cec_set_edid(struct amdgpu_dm_connector 
*aconnector)
        cec_notifier_set_phys_addr(n,
                                   
connector->display_info.source_physical_address);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_hdmi_cec_set_edid);
 
 void amdgpu_dm_s3_handle_hdmi_cec(struct drm_device *ddev, bool suspend)
 {
@@ -376,6 +377,7 @@ void amdgpu_dm_s3_handle_hdmi_cec(struct drm_device *ddev, 
bool suspend)
        }
        drm_connector_list_iter_end(&conn_iter);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_s3_handle_hdmi_cec);
 
 
 struct drm_connector *
@@ -2254,6 +2256,7 @@ enum drm_mode_status 
amdgpu_dm_connector_mode_valid(struct drm_connector *connec
        /* TODO: error handling*/
        return result;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_connector_mode_valid);
 
 int amdgpu_dm_fill_hdr_info_packet(const struct drm_connector_state *state,
                                struct dc_info_packet *out)
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 f60ce381683e..cfb114d5b879 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
@@ -4900,6 +4900,103 @@ static void 
dm_test_parse_displayid_vrr_sets_range(struct kunit *test)
        KUNIT_EXPECT_EQ(test, connector->display_info.monitor_range.max_vfreq, 
144);
 }
 
+/**
+ * dm_test_mode_valid_interlace_rejected - Test interlaced modes are rejected
+ * @test: The KUnit test context
+ *
+ * Interlaced modes are rejected up front with MODE_ERROR before any sink or
+ * stream validation is attempted.
+ */
+static void dm_test_mode_valid_interlace_rejected(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconnector;
+       struct drm_display_mode *mode;
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+       mode = kunit_kzalloc(test, sizeof(*mode), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, mode);
+
+       mode->flags = DRM_MODE_FLAG_INTERLACE;
+
+       KUNIT_EXPECT_EQ(test,
+                       amdgpu_dm_connector_mode_valid(&aconnector->base, mode),
+                       MODE_ERROR);
+}
+
+/**
+ * dm_test_mode_valid_dblscan_rejected - Test doublescan modes are rejected
+ * @test: The KUnit test context
+ *
+ * Doublescan modes are rejected up front with MODE_ERROR.
+ */
+static void dm_test_mode_valid_dblscan_rejected(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconnector;
+       struct drm_display_mode *mode;
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+       mode = kunit_kzalloc(test, sizeof(*mode), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, mode);
+
+       mode->flags = DRM_MODE_FLAG_DBLSCAN;
+
+       KUNIT_EXPECT_EQ(test,
+                       amdgpu_dm_connector_mode_valid(&aconnector->base, mode),
+                       MODE_ERROR);
+}
+
+/**
+ * dm_test_hdmi_cec_set_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_set_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);
+
+       amdgpu_dm_hdmi_cec_set_edid(aconnector);
+}
+
+/**
+ * dm_test_s3_handle_hdmi_cec_suspend - Test the suspend pass over connectors
+ * @test: The KUnit test context
+ *
+ * Suspend iterates all connectors, skipping writeback ones and calling the
+ * unset path on the rest; with NULL notifiers this is a crash-free no-op.
+ */
+static void dm_test_s3_handle_hdmi_cec_suspend(struct kunit *test)
+{
+       struct drm_device *drm = dm_test_alloc_drm(test);
+
+       dm_test_add_connector(test, drm, DRM_MODE_CONNECTOR_WRITEBACK);
+       dm_test_add_connector(test, drm, DRM_MODE_CONNECTOR_HDMIA);
+
+       amdgpu_dm_s3_handle_hdmi_cec(drm, true);
+}
+
+/**
+ * dm_test_s3_handle_hdmi_cec_resume - Test the resume pass over connectors
+ * @test: The KUnit test context
+ *
+ * Resume iterates all connectors, skipping writeback ones and calling the set
+ * path on the rest; with NULL notifiers this is a crash-free no-op.
+ */
+static void dm_test_s3_handle_hdmi_cec_resume(struct kunit *test)
+{
+       struct drm_device *drm = dm_test_alloc_drm(test);
+
+       dm_test_add_connector(test, drm, DRM_MODE_CONNECTOR_WRITEBACK);
+       dm_test_add_connector(test, drm, DRM_MODE_CONNECTOR_HDMIA);
+
+       amdgpu_dm_s3_handle_hdmi_cec(drm, false);
+}
+
 static struct kunit_case amdgpu_dm_connector_tests[] = {
        /* get_subconnector_type */
        KUNIT_CASE(dm_test_subconnector_type_none),
@@ -5166,6 +5263,14 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
        KUNIT_CASE(dm_test_parse_displayid_vrr_null_edid),
        KUNIT_CASE(dm_test_parse_displayid_vrr_no_displayid),
        KUNIT_CASE(dm_test_parse_displayid_vrr_sets_range),
+       /* amdgpu_dm_connector_mode_valid */
+       KUNIT_CASE(dm_test_mode_valid_interlace_rejected),
+       KUNIT_CASE(dm_test_mode_valid_dblscan_rejected),
+       /* amdgpu_dm_hdmi_cec_set_edid */
+       KUNIT_CASE(dm_test_hdmi_cec_set_edid_no_notifier),
+       /* amdgpu_dm_s3_handle_hdmi_cec */
+       KUNIT_CASE(dm_test_s3_handle_hdmi_cec_suspend),
+       KUNIT_CASE(dm_test_s3_handle_hdmi_cec_resume),
        {}
 };
 
-- 
2.43.0

Reply via email to