From: Alex Hung <[email protected]>

[WHAT]
handle_hpd_irq_helper() never ran its HDCP reset, its forced
connector branch or its successful re-detect branch.

[HOW]
Add a minimal HDCP work queue fixture and three tests: an HPD on
a driver that carries an HDCP work queue, which must reset the display
and flag the connector state; a connector forced on that reports no
connection and is emulated instead of detected; and a successful
re-detect that notifies userspace.

Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../amdgpu_dm/tests/amdgpu_dm_irq_test.c      | 119 ++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
index 04cc5dd5812b..5f877c50b120 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
@@ -21,6 +21,7 @@
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
+#include "amdgpu_dm_hdcp.h"
 #include "amdgpu_dm_irq.h"
 #include "amdgpu_dm_kunit_test_helpers.h"
 #include "dc_dmub_srv.h"
@@ -547,6 +548,39 @@ static void dm_test_register_drm_dev(struct kunit *test, 
struct amdgpu_device *a
                                                        &adev->ddev), 0);
 }
 
+static void dm_test_hdcp_dummy_work(struct work_struct *work)
+{
+}
+
+/*
+ * Allocate the minimal hdcp_workqueue that hdcp_reset_display() and
+ * hdcp_handle_cpirq() touch: the per-link mutex, the delayed works
+ * process_output() re-arms, and the CP IRQ work item.
+ */
+static struct hdcp_workqueue *dm_test_alloc_hdcp_workqueue(struct kunit *test)
+{
+       struct hdcp_workqueue *hdcp_work;
+
+       hdcp_work = kunit_kzalloc(test, sizeof(*hdcp_work), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdcp_work);
+
+       mutex_init(&hdcp_work->mutex);
+       INIT_WORK(&hdcp_work->cpirq_work, dm_test_hdcp_dummy_work);
+       INIT_DELAYED_WORK(&hdcp_work->callback_dwork, dm_test_hdcp_dummy_work);
+       INIT_DELAYED_WORK(&hdcp_work->watchdog_timer_dwork, 
dm_test_hdcp_dummy_work);
+       INIT_DELAYED_WORK(&hdcp_work->property_validate_dwork, 
dm_test_hdcp_dummy_work);
+
+       return hdcp_work;
+}
+
+static void dm_test_flush_hdcp_workqueue(struct hdcp_workqueue *hdcp_work)
+{
+       flush_work(&hdcp_work->cpirq_work);
+       cancel_delayed_work_sync(&hdcp_work->callback_dwork);
+       cancel_delayed_work_sync(&hdcp_work->watchdog_timer_dwork);
+       cancel_delayed_work_sync(&hdcp_work->property_validate_dwork);
+}
+
 /* Tests for amdgpu_dm_hpd_to_dal_irq_source() */
 
 /**
@@ -3206,6 +3240,88 @@ static void 
dm_test_handle_hpd_irq_helper_detect_type_fails(struct kunit *test)
        KUNIT_EXPECT_FALSE(test, aconn->fake_enable);
 }
 
+/**
+ * dm_test_handle_hpd_irq_helper_hdcp_reset - Test the HDCP reset branch
+ * @test: The KUnit test context
+ *
+ * An HPD invalidates the link's HDCP authentication, so a driver carrying an
+ * HDCP work queue must reset the display and flag the connector state for a
+ * property update.
+ */
+static void dm_test_handle_hpd_irq_helper_hdcp_reset(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconn;
+       struct hdcp_workqueue *hdcp_work;
+       struct link_service *link_srv;
+
+       aconn = dm_test_setup_hpd_irq_helper(test, &link_srv);
+       link_srv->detect_link = dm_test_detect_link_false;
+
+       hdcp_work = dm_test_alloc_hdcp_workqueue(test);
+       drm_to_adev(aconn->base.dev)->dm.hdcp_workqueue = hdcp_work;
+
+       handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
+
+       KUNIT_EXPECT_TRUE(test, 
to_dm_connector_state(aconn->base.state)->update_hdcp);
+
+       dm_test_flush_hdcp_workqueue(hdcp_work);
+}
+
+/**
+ * dm_test_handle_hpd_irq_helper_forced_detect - Test the forced-connector 
branch
+ * @test: The KUnit test context
+ *
+ * A connector forced on but reporting no connection is emulated rather than
+ * detected, and an HPD RX always notifies userspace. An unset connector signal
+ * keeps amdgpu_dm_emulated_link_detect() to its unsupported-signal early
+ * return.
+ */
+static void dm_test_handle_hpd_irq_helper_forced_detect(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconn;
+       struct link_service *link_srv;
+
+       dm_test_detect_link_count = 0;
+
+       aconn = dm_test_setup_hpd_irq_helper(test, &link_srv);
+       dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev));
+
+       link_srv->detect_link = dm_test_detect_link_false_count;
+       aconn->base.force = DRM_FORCE_ON;
+       aconn->dc_link->ctx->driver_context = drm_to_adev(aconn->base.dev);
+
+       handle_hpd_irq_helper(aconn, DETECT_REASON_HPDRX);
+
+       /* The emulated path replaces detection entirely. */
+       KUNIT_EXPECT_EQ(test, dm_test_detect_link_count, 0);
+}
+
+/**
+ * dm_test_handle_hpd_irq_helper_detect_true - Test the connected detect branch
+ * @test: The KUnit test context
+ *
+ * A successful re-detect refreshes the connector state and notifies userspace.
+ * An MST-state connector keeps amdgpu_dm_update_connector_after_detect() to 
its
+ * early return.
+ */
+static void dm_test_handle_hpd_irq_helper_detect_true(struct kunit *test)
+{
+       struct amdgpu_dm_connector *aconn;
+       struct link_service *link_srv;
+
+       aconn = dm_test_setup_hpd_irq_helper(test, &link_srv);
+       dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev));
+
+       link_srv->detect_connection_type = dm_test_detect_connection_single;
+       link_srv->detect_link = dm_test_detect_link_true;
+       aconn->mst_mgr.mst_state = true;
+       aconn->fake_enable = true;
+
+       handle_hpd_irq_helper(aconn, DETECT_REASON_HPD);
+
+       KUNIT_EXPECT_FALSE(test, aconn->fake_enable);
+}
+
 /**
  * dm_test_handle_hpd_irq_helper_debounce_pending - Test pending-debounce exit
  * @test: The KUnit test context
@@ -5419,6 +5535,9 @@ static struct kunit_case amdgpu_dm_irq_tests[] = {
        KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_false),
        KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_type_fails),
        KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_pending),
+       KUNIT_CASE(dm_test_handle_hpd_irq_helper_hdcp_reset),
+       KUNIT_CASE(dm_test_handle_hpd_irq_helper_forced_detect),
+       KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_true),
        /* handle_hpd_rx_irq/schedule_hpd_rx_offload_work */
        KUNIT_CASE(dm_test_handle_hpd_rx_irq_disabled),
        KUNIT_CASE(dm_test_handle_hpd_rx_irq_no_left_work),
-- 
2.55.0

Reply via email to