From: Bhawanpreet Lakha <[email protected]>

Expand KUnit coverage for event_property_update() beyond the null
connector skip. Add cases for the disconnected, missing-state and
missing-device skip branches, plus the fully connected path where
hdcp_get_content_protection_from_status() maps HDCP_OFF to DESIRED and
HDCP1 TYPE0 encryption to ENABLED.

The connected-path tests use dm_kunit_alloc_adev() so the drm_device has
an initialised mode_config connection_mutex, and pre-set the connector
state to the expected content protection value so
drm_hdcp_update_content_protection() takes its no-change early return.

Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Fangzhi Zuo <[email protected]>
Tested-by: Dan Wheeler <[email protected]>
---
 .../amdgpu_dm/tests/amdgpu_dm_hdcp_test.c     | 174 +++++++++++++++++-
 1 file changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
index b359ba5d524b..cfdcc44581b1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_hdcp_test.c
@@ -473,7 +473,8 @@ static void 
dm_test_process_output_watchdog_stop_and_needed_requeues(struct kuni
  * @test: KUnit test context for managed allocation
  *
  * Allocates a minimal hdcp_workqueue with property_update_work initialised
- * so event_property_update() can resolve container_of() safely.
+ * so event_property_update() can resolve container_of() safely. The mutex is
+ * initialised as well because the connected path takes guard(mutex).
  */
 static struct hdcp_workqueue *alloc_test_workqueue_for_property_update(struct 
kunit *test)
 {
@@ -482,11 +483,41 @@ static struct hdcp_workqueue 
*alloc_test_workqueue_for_property_update(struct ku
        work = kunit_kzalloc(test, sizeof(*work), GFP_KERNEL);
        KUNIT_ASSERT_NOT_NULL(test, work);
 
+       mutex_init(&work->mutex);
        INIT_WORK(&work->property_update_work, dummy_work_fn);
 
        return work;
 }
 
+/**
+ * alloc_update_connector - connector for event_property_update() tests
+ * @test: KUnit test context for managed allocation
+ * @status: drm connector detection status to assign
+ * @conn_state: drm_connector_state to attach (may be NULL)
+ * @dev: drm_device to attach as connector->dev (may be NULL)
+ *
+ * Allocates an amdgpu_dm_connector wired for the traversal in
+ * event_property_update(). The caller supplies the state and device so the
+ * various skip branches (disconnected, no state, no device) and the fully
+ * connected path can all be exercised.
+ */
+static struct amdgpu_dm_connector *alloc_update_connector(struct kunit *test,
+                                                         enum 
drm_connector_status status,
+                                                         struct 
drm_connector_state *conn_state,
+                                                         struct drm_device 
*dev)
+{
+       struct amdgpu_dm_connector *aconnector;
+
+       aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, aconnector);
+
+       aconnector->base.status = status;
+       aconnector->base.state = conn_state;
+       aconnector->base.dev = dev;
+
+       return aconnector;
+}
+
 /**
  * dm_test_event_property_update_skips_null_connector - null connector is 
ignored
  * @test: KUnit test context
@@ -507,6 +538,142 @@ static void 
dm_test_event_property_update_skips_null_connector(struct kunit *tes
        KUNIT_EXPECT_EQ(test, work->encryption_status[0], before);
 }
 
+/**
+ * dm_test_event_property_update_skips_disconnected - disconnected is skipped
+ * @test: KUnit test context
+ *
+ * A connector whose status is not connector_status_connected must be skipped
+ * before any modeset lock is taken, leaving encryption_status untouched.
+ */
+static void dm_test_event_property_update_skips_disconnected(struct kunit 
*test)
+{
+       struct hdcp_workqueue *work = 
alloc_test_workqueue_for_property_update(test);
+       struct drm_connector_state *conn_state;
+
+       conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+       work->aconnector[1] = alloc_update_connector(test, 
connector_status_disconnected,
+                                                    conn_state, NULL);
+       work->encryption_status[1] = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
+
+       event_property_update(&work->property_update_work);
+
+       KUNIT_EXPECT_EQ(test, work->encryption_status[1],
+                       MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON);
+}
+
+/**
+ * dm_test_event_property_update_skips_null_state - missing state is skipped
+ * @test: KUnit test context
+ *
+ * A connected connector without a drm_connector_state must be skipped before
+ * the modeset lock, leaving encryption_status unchanged.
+ */
+static void dm_test_event_property_update_skips_null_state(struct kunit *test)
+{
+       struct hdcp_workqueue *work = 
alloc_test_workqueue_for_property_update(test);
+
+       work->aconnector[2] = alloc_update_connector(test, 
connector_status_connected,
+                                                    NULL, NULL);
+       work->encryption_status[2] = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
+
+       event_property_update(&work->property_update_work);
+
+       KUNIT_EXPECT_EQ(test, work->encryption_status[2],
+                       MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON);
+}
+
+/**
+ * dm_test_event_property_update_skips_null_dev - missing device is skipped
+ * @test: KUnit test context
+ *
+ * A connected connector with state but no drm_device must be skipped before
+ * the modeset lock, leaving encryption_status unchanged.
+ */
+static void dm_test_event_property_update_skips_null_dev(struct kunit *test)
+{
+       struct hdcp_workqueue *work = 
alloc_test_workqueue_for_property_update(test);
+       struct drm_connector_state *conn_state;
+
+       conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, conn_state);
+
+       work->aconnector[3] = alloc_update_connector(test, 
connector_status_connected,
+                                                    conn_state, NULL);
+       work->encryption_status[3] = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
+
+       event_property_update(&work->property_update_work);
+
+       KUNIT_EXPECT_EQ(test, work->encryption_status[3],
+                       MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON);
+}
+
+/**
+ * dm_test_event_property_update_desired_when_off - HDCP off maps to DESIRED
+ * @test: KUnit test context
+ *
+ * A fully connected display with HDCP_OFF encryption drives the connected
+ * path: the modeset lock is taken, hdcp_get_content_protection_from_status()
+ * reports DRM_MODE_CONTENT_PROTECTION_DESIRED and
+ * drm_hdcp_update_content_protection() is called. The connector state is
+ * pre-set to DESIRED so the value is unchanged (no sysfs event) and the deep
+ * path completes cleanly.
+ */
+static void dm_test_event_property_update_desired_when_off(struct kunit *test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct hdcp_workqueue *work = 
alloc_test_workqueue_for_property_update(test);
+       struct drm_connector_state *conn_state;
+
+       conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, conn_state);
+       conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+
+       work->aconnector[0] = alloc_update_connector(test, 
connector_status_connected,
+                                                    conn_state, &adev->ddev);
+       work->encryption_status[0] = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+
+       event_property_update(&work->property_update_work);
+
+       KUNIT_EXPECT_EQ(test, conn_state->content_protection,
+                       (unsigned int)DRM_MODE_CONTENT_PROTECTION_DESIRED);
+       KUNIT_EXPECT_EQ(test, work->encryption_status[0],
+                       MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF);
+}
+
+/**
+ * dm_test_event_property_update_enabled_when_encrypted - encrypted maps to 
ENABLED
+ * @test: KUnit test context
+ *
+ * A fully connected display with TYPE0 content and HDCP1 encryption drives
+ * the connected path where hdcp_get_content_protection_from_status() reports
+ * DRM_MODE_CONTENT_PROTECTION_ENABLED. The connector state is pre-set to
+ * ENABLED so drm_hdcp_update_content_protection() leaves it unchanged.
+ */
+static void dm_test_event_property_update_enabled_when_encrypted(struct kunit 
*test)
+{
+       struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+       struct hdcp_workqueue *work = 
alloc_test_workqueue_for_property_update(test);
+       struct drm_connector_state *conn_state;
+
+       conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, conn_state);
+       conn_state->hdcp_content_type = DRM_MODE_HDCP_CONTENT_TYPE0;
+       conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+
+       work->aconnector[0] = alloc_update_connector(test, 
connector_status_connected,
+                                                    conn_state, &adev->ddev);
+       work->encryption_status[0] = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON;
+
+       event_property_update(&work->property_update_work);
+
+       KUNIT_EXPECT_EQ(test, conn_state->content_protection,
+                       (unsigned int)DRM_MODE_CONTENT_PROTECTION_ENABLED);
+       KUNIT_EXPECT_EQ(test, work->encryption_status[0],
+                       MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON);
+}
+
 /* End of tests for event_property_update() */
 
 /* Tests for event_callback() */
@@ -2367,6 +2534,11 @@ static struct kunit_case dm_hdcp_test_cases[] = {
        KUNIT_CASE(dm_test_process_output_watchdog_stop_and_needed_requeues),
        /* event_property_update() */
        KUNIT_CASE(dm_test_event_property_update_skips_null_connector),
+       KUNIT_CASE(dm_test_event_property_update_skips_disconnected),
+       KUNIT_CASE(dm_test_event_property_update_skips_null_state),
+       KUNIT_CASE(dm_test_event_property_update_skips_null_dev),
+       KUNIT_CASE(dm_test_event_property_update_desired_when_off),
+       KUNIT_CASE(dm_test_event_property_update_enabled_when_encrypted),
        /* event_callback() */
        KUNIT_CASE(dm_test_event_callback_cancels_callback_dwork),
        KUNIT_CASE(dm_test_event_callback_schedules_property_validate),
-- 
2.53.0

Reply via email to