summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlex Hung <alex.hung@amd.com>2026-09-04 00:00:59 -0600
committerAlex Deucher <alexander.deucher@amd.com>2026-09-23 13:27:36 -0400
commiteaf681630590c2fb609bb0a06993cdf6af28a758 (patch)
tree3b5fddc3a7d2e73cf33ad864e5547eb179eb9d53 /drivers
parented32f69ac516f0f1ce0a01e5dd7608dbb1b85da8 (diff)
downloadlinux-next-eaf681630590c2fb609bb0a06993cdf6af28a758.tar.gz
linux-next-eaf681630590c2fb609bb0a06993cdf6af28a758.zip
drm/amd/display: Test HPD handler HDCP and detect
[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 <bhawanpreet.lakha@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Signed-off-by: George Zhang <george.zhang@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c119
1 files changed, 119 insertions, 0 deletions
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 dbbb7ed377b8..ae68aa34818a 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() */
/**
@@ -3207,6 +3241,88 @@ static void dm_test_handle_hpd_irq_helper_detect_type_fails(struct kunit *test)
}
/**
+ * 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),