From: Ivan Lipski <[email protected]>

[Why & How]
amdgpu_dm_hpd_init() was changed to walk adev->dm.dc->links directly,
so the two tests that left adev->dm.dc NULL now panic on a NULL dc
dereference.

Give both tests a real DC via dm_test_alloc_dc_with_irq_service()
with a dc_link and dc->links[0] / link_count = 1.

Reviewed-by: Alex Hung <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
Signed-off-by: Ray Wu <[email protected]>
---
 .../amdgpu_dm/tests/amdgpu_dm_irq_test.c      | 48 ++++++++++++++++---
 1 file changed, 42 insertions(+), 6 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 a139890b7cd5..18a2409c5a69 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
@@ -2035,14 +2035,27 @@ static void dm_test_outbox_init_null_dc(struct kunit 
*test)
 static void dm_test_hpd_init_empty_connectors(struct kunit *test)
 {
        struct amdgpu_device *adev;
+       struct dc_link *link;
+       struct dc *dc;
 
        adev = dm_kunit_alloc_adev(test);
 
        /*
-        * With an empty connector list the per-connector loop is skipped and
-        * the initial clear loop relies on amdgpu_dm_irq_set() being a no-op
-        * for a NULL dc, so init must complete without touching the DC.
+        * The initial clear loop walks adev->dm.dc->links, so a DC with a
+        * populated irq service is required. With an empty connector list the
+        * per-connector loop is skipped, so init must complete after only the
+        * clear loop runs.
         */
+       dc = dm_test_alloc_dc_with_irq_service(test, 
&dm_test_irq_service_funcs_dcn10);
+       adev->dm.dc = dc;
+
+       link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link);
+       link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
+       link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX;
+       dc->links[0] = link;
+       dc->link_count = 1;
+
        amdgpu_dm_hpd_init(adev);
 }
 
@@ -2070,13 +2083,17 @@ static void 
dm_test_hpd_init_fini_with_connectors(struct kunit *test)
        struct drm_connector *wbconn;
        struct amdgpu_device *adev;
        struct dc_link *link;
+       struct dc *dc;
 
        adev = dm_kunit_alloc_adev(test);
 
+       /* The clear loop walks dc->links, so set up a DC with an irq service. 
*/
+       dc = dm_test_alloc_dc_with_irq_service(test, 
&dm_test_irq_service_funcs_dcn10);
+       adev->dm.dc = dc;
+
        /*
         * num_hpd = 0 forces irq_type >= num_hpd so the loop takes the HW
-        * fallback (amdgpu_dm_irq_set()) instead of amdgpu_irq_get(); with a
-        * NULL dc that fallback is a safe no-op.
+        * fallback (amdgpu_dm_irq_set()) instead of amdgpu_irq_get().
         */
        adev->mode_info.num_hpd = 0;
 
@@ -2102,8 +2119,10 @@ static void dm_test_hpd_init_fini_with_connectors(struct 
kunit *test)
        link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
        link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX;
        aconn->dc_link = link;
+       dc->links[0] = link;
+       dc->link_count = 1;
 
-       /* DC is absent (NULL), so the HW writes are NULL-safe no-ops. */
+       /* The irq service stubs accept the HW writes without register access. 
*/
        amdgpu_dm_hpd_init(adev);
        amdgpu_dm_hpd_fini(adev);
 }
@@ -2117,10 +2136,15 @@ static void 
dm_test_hpd_init_fini_analog_connector(struct kunit *test)
        struct amdgpu_dm_connector *aconn;
        struct amdgpu_device *adev;
        struct dc_link *link;
+       struct dc *dc;
 
        adev = dm_kunit_alloc_adev(test);
        adev->mode_info.num_hpd = 0;
 
+       /* The clear loop walks dc->links, so set up a DC with an irq service. 
*/
+       dc = dm_test_alloc_dc_with_irq_service(test, 
&dm_test_irq_service_funcs_dcn10);
+       adev->dm.dc = dc;
+
        aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
        KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
@@ -2136,6 +2160,8 @@ static void dm_test_hpd_init_fini_analog_connector(struct 
kunit *test)
        /* An analog connector id makes the loop request polling. */
        link->link_id.id = CONNECTOR_ID_VGA;
        aconn->dc_link = link;
+       dc->links[0] = link;
+       dc->link_count = 1;
 
        /* use_polling becomes true, so init must enable KMS polling. */
        amdgpu_dm_hpd_init(adev);
@@ -2155,9 +2181,14 @@ static void dm_test_hpd_init_fini_irq_ref(struct kunit 
*test)
        struct amdgpu_dm_connector *aconn;
        struct amdgpu_device *adev;
        struct dc_link *link;
+       struct dc *dc;
 
        adev = dm_kunit_alloc_adev(test);
 
+       /* The clear loop walks dc->links, so set up a DC with an irq service. 
*/
+       dc = dm_test_alloc_dc_with_irq_service(test, 
&dm_test_irq_service_funcs_dcn10);
+       adev->dm.dc = dc;
+
        /*
         * num_hpd >= 1 makes irq_type (0) < num_hpd, so the loop takes the
         * amdgpu_irq_get()/amdgpu_irq_put() branch instead of the
@@ -2180,6 +2211,8 @@ static void dm_test_hpd_init_fini_irq_ref(struct kunit 
*test)
        link->irq_source_hpd = DC_IRQ_SOURCE_HPD1;
        link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
        aconn->dc_link = link;
+       dc->links[0] = link;
+       dc->link_count = 1;
 
        amdgpu_dm_hpd_init(adev);
        amdgpu_dm_hpd_fini(adev);
@@ -2200,6 +2233,9 @@ static void 
dm_test_hpd_init_skips_connector_without_link(struct kunit *test)
        adev = dm_kunit_alloc_adev(test);
        adev->mode_info.num_hpd = 0;
 
+       /* The clear loop walks dc->links, so set up a DC with an irq service. 
*/
+       adev->dm.dc = dm_test_alloc_dc_with_irq_service(test, 
&dm_test_irq_service_funcs_dcn10);
+
        aconn = kunit_kzalloc(test, sizeof(*aconn), GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn);
        KUNIT_ASSERT_EQ(test, drm_connector_init(&adev->ddev, &aconn->base,
-- 
2.43.0

Reply via email to