From: Alex Hung <[email protected]>

[WHAT]
Add KUnit tests for is_synaptics_cascaded_panamera() covering a
matching cascaded hub, a non Synaptics branch, a non Panamera device
ID, an unsupported branch firmware revision and a port without a
parent branch.

[HOW]
Allocate an MST topology manager with a branch and a port, and drive a
table driven test that fills in the branch OUI, device ID and firmware
revision for each case before checking the returned verdict.

Assisted-by: Copilot:Claude-Opus-5
Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Chenyu Chen <[email protected]>
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  3 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  1 +
 .../tests/amdgpu_dm_mst_types_test.c          | 81 +++++++++++++++++++
 3 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index e8f4ca7e1f2a..c584906c8bb0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -279,7 +279,7 @@ bool needs_dsc_aux_workaround(struct dc_link *link)
 EXPORT_IF_KUNIT(needs_dsc_aux_workaround);
 
 #if defined(CONFIG_DRM_AMD_DC_FP) || IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
-static bool is_synaptics_cascaded_panamera(struct dc_link *link, struct 
drm_dp_mst_port *port)
+STATIC_IFN_KUNIT bool is_synaptics_cascaded_panamera(struct dc_link *link, 
struct drm_dp_mst_port *port)
 {
        u8 branch_vendor_data[4] = { 0 }; // Vendor data 0x50C ~ 0x50F
 
@@ -293,6 +293,7 @@ static bool is_synaptics_cascaded_panamera(struct dc_link 
*link, struct drm_dp_m
 
        return false;
 }
+EXPORT_IF_KUNIT(is_synaptics_cascaded_panamera);
 
 static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector 
*aconnector)
 {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index 4af3aac31223..f2e36807f0da 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -105,6 +105,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 
 #if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
 void amdgpu_dm_mst_reset_mst_connector_setting(struct amdgpu_dm_connector 
*aconnector);
+bool is_synaptics_cascaded_panamera(struct dc_link *link, struct 
drm_dp_mst_port *port);
 bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *cur_link_bw);
 bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnector);
 bool retrieve_branch_specific_data(struct amdgpu_dm_connector *aconnector);
diff --git 
a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
index 58a4bbb31e79..2e562c545c30 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c
@@ -2394,6 +2394,85 @@ static void dm_mst_test_link_current_set_bw(struct kunit 
*test)
        KUNIT_EXPECT_EQ(test, cur_link_bw, param->cur_link_bw);
 }
 
+/* Tests for is_synaptics_cascaded_panamera */
+
+/*
+ * A Panamera hub is identified by its branch device ID plus the high nibble of
+ * the fifth branch device name byte; the cascaded variant additionally reports
+ * SYNAPTICS_CASCADED_HUB_ID at DPCD 0x50e.
+ */
+static void dm_mst_test_set_panamera_ids(struct dc_link *link, u32 
branch_dev_id,
+                                        u8 dev_name_4, u8 cascaded_id)
+{
+       link->dpcd_caps.branch_dev_id = branch_dev_id;
+       link->dpcd_caps.branch_dev_name[4] = dev_name_4;
+       dm_mst_test_dsc_dpcd[DP_BRANCH_VENDOR_SPECIFIC_START + 2] = cascaded_id;
+}
+
+static struct drm_dp_mst_port *dm_mst_test_alloc_mgr_port(struct kunit *test)
+{
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_port *port;
+
+       mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);
+       port = kunit_kzalloc(test, sizeof(*port), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_NULL(test, mgr);
+       KUNIT_ASSERT_NOT_NULL(test, port);
+
+       mutex_init(&mgr->lock);
+       mgr->aux = dm_mst_test_alloc_dsc_aux(test, "dm_mst_test_mgr_aux");
+       port->mgr = mgr;
+
+       return port;
+}
+
+struct dm_mst_panamera_param {
+       const char *name;
+       u32 branch_dev_id;
+       u8 dev_name_4;
+       u8 cascaded_id;
+       bool aux_fails;
+       bool cascaded;
+};
+
+static const struct dm_mst_panamera_param dm_mst_panamera_params[] = {
+       { "cascaded_hub", DP_BRANCH_DEVICE_ID_90CC24, 0x50,
+         SYNAPTICS_CASCADED_HUB_ID, false, true },
+       { "wrong_dev_id", 0x001122, 0x50, SYNAPTICS_CASCADED_HUB_ID, false, 
false },
+       { "not_panamera", DP_BRANCH_DEVICE_ID_90CC24, 0x40,
+         SYNAPTICS_CASCADED_HUB_ID, false, false },
+       { "not_cascaded", DP_BRANCH_DEVICE_ID_90CC24, 0x50, 0, false, false },
+       { "dpcd_read_error", DP_BRANCH_DEVICE_ID_90CC24, 0x50,
+         SYNAPTICS_CASCADED_HUB_ID, true, false },
+};
+
+KUNIT_ARRAY_PARAM_DESC(dm_mst_panamera, dm_mst_panamera_params, name);
+
+/**
+ * dm_mst_test_synaptics_cascaded - only a cascaded Panamera hub is detected
+ * @test: KUnit test context
+ *
+ * All three conditions must hold: the Synaptics branch device ID, a Panamera
+ * device name and the cascaded hub ID in the branch vendor data. A failed
+ * vendor read leaves the hub undetected.
+ */
+static void dm_mst_test_synaptics_cascaded(struct kunit *test)
+{
+       const struct dm_mst_panamera_param *param = test->param_value;
+       struct drm_dp_mst_port *port;
+       struct dc_link *link;
+
+       dm_mst_test_reset_dsc_dpcd();
+       port = dm_mst_test_alloc_mgr_port(test);
+       link = dm_kunit_alloc_link(test);
+       dm_mst_test_set_panamera_ids(link, param->branch_dev_id, 
param->dev_name_4,
+                                    param->cascaded_id);
+       if (param->aux_fails)
+               dm_mst_test_dsc_aux_fail = port->mgr->aux;
+
+       KUNIT_EXPECT_EQ(test, is_synaptics_cascaded_panamera(link, port), 
param->cascaded);
+}
+
 static struct kunit_case dm_mst_types_test_cases[] = {
        /* needs_dsc_aux_workaround tests */
        KUNIT_CASE(dm_mst_test_needs_dsc_aux_workaround_match),
@@ -2480,6 +2559,8 @@ static struct kunit_case dm_mst_types_test_cases[] = {
        KUNIT_CASE(dm_mst_test_connector_destroy_releases_sink),
        /* dp_get_link_current_set_bw tests */
        KUNIT_CASE_PARAM(dm_mst_test_link_current_set_bw, 
dm_mst_link_bw_gen_params),
+       /* is_synaptics_cascaded_panamera tests */
+       KUNIT_CASE_PARAM(dm_mst_test_synaptics_cascaded, 
dm_mst_panamera_gen_params),
        {}
 };
 
-- 
2.43.0

Reply via email to