From: Alex Hung <[email protected]> [WHAT] Several amdgpu_dm_irq tests were each open-coding the same setup. Share it through three functions: dm_test_add_crtc(), dm_test_setup_hpd_irq_helper() and dm_test_setup_irq_regs().
Assisted-by: Copilot:Claude-Opus-5 Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Ivan Lipski <[email protected]> --- .../amdgpu_dm/tests/amdgpu_dm_irq_test.c | 214 ++++++++---------- 1 file changed, 95 insertions(+), 119 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 28c36217f6a21..fbe37bb0a39d6 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 @@ -340,6 +340,38 @@ static void dm_test_crtc_list_del(void *data) list_del_init(&acrtc->base.head); } +/* + * The DRM vblank core looks CRTCs up by index on mode_config.crtc_list and + * dereferences crtc->funcs, so a listed CRTC must carry a funcs table even + * when it implements no callbacks. + */ +static const struct drm_crtc_funcs dm_test_crtc_funcs = { +}; + +/* + * Add an OTG instance 0 CRTC to the device so amdgpu_dm_get_crtc_by_otg_inst() + * finds it. The CRTC is removed from the list again on test teardown. + */ +static struct amdgpu_crtc *dm_test_add_crtc(struct kunit *test, + struct amdgpu_device *adev) +{ + struct amdgpu_crtc *acrtc; + + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + + INIT_LIST_HEAD(&acrtc->base.head); + acrtc->base.dev = &adev->ddev; + acrtc->base.funcs = &dm_test_crtc_funcs; + acrtc->otg_inst = 0; + + list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); + KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, + dm_test_crtc_list_del, acrtc), 0); + + return acrtc; +} + struct dm_test_hpd_rx_wq_ctx { struct hpd_rx_irq_offload_work_queue *wq; int count; @@ -2481,16 +2513,14 @@ static void dm_test_handle_hpd_irq_disabled(struct kunit *test) KUNIT_EXPECT_TRUE(test, aconn->fake_enable); } -/** - * dm_test_handle_hpd_irq_helper_debounce_schedule - Test HDMI debounce branch - * @test: The KUnit test context - * - * An HDMI link reporting a disconnect (connection type none) with a non-zero - * debounce delay and a cached local_sink must take the debounce branch: it - * caches local_sink in hdmi_prev_sink and schedules the delayed debounce work - * instead of detecting immediately. +/* + * Build an aconnector wired for handle_hpd_irq_helper(): an HPD lock, an armed + * debounce work item, an atomic state and a dc/link pair reporting no + * connection. Caller sets the link_srv stubs and any HDMI/debounce fields the + * branch under test needs. */ -static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test) +static struct amdgpu_dm_connector *dm_test_setup_hpd_irq_helper(struct kunit *test, + struct link_service **link_srv_out) { struct amdgpu_dm_connector *aconn; struct dm_connector_state *state; @@ -2501,6 +2531,7 @@ static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test) struct dc *dc; adev = dm_kunit_alloc_adev(test); + mutex_init(&adev->dm.dc_lock); aconn = dm_kunit_alloc_connector(test, adev, NULL); mutex_init(&aconn->hpd_lock); @@ -2528,6 +2559,29 @@ static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test) link->ctx = ctx; aconn->dc_link = link; + *link_srv_out = link_srv; + + return aconn; +} + +/** + * dm_test_handle_hpd_irq_helper_debounce_schedule - Test HDMI debounce branch + * @test: The KUnit test context + * + * An HDMI link reporting a disconnect (connection type none) with a non-zero + * debounce delay and a cached local_sink must take the debounce branch: it + * caches local_sink in hdmi_prev_sink and schedules the delayed debounce work + * instead of detecting immediately. + */ +static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + struct dc_link *link; + + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); + link = aconn->dc_link; + /* HDMI signal + debounce delay + cached sink -> debounce branch. */ aconn->hdmi_hpd_debounce_delay_ms = 100; link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; @@ -2555,40 +2609,11 @@ static void dm_test_handle_hpd_irq_helper_debounce_schedule(struct kunit *test) static void dm_test_handle_hpd_irq_helper_debounce_release_prev(struct kunit *test) { struct amdgpu_dm_connector *aconn; - struct dm_connector_state *state; struct link_service *link_srv; - struct amdgpu_device *adev; - struct dc_context *ctx; struct dc_link *link; - struct dc *dc; - - adev = dm_kunit_alloc_adev(test); - aconn = dm_kunit_alloc_connector(test, adev, NULL); - mutex_init(&aconn->hpd_lock); - INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work, - amdgpu_dm_hdmi_hpd_debounce_work); - - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); - aconn->base.state = &state->base; - - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); - - link_srv->detect_connection_type = dm_test_detect_connection_none; - dc->ctx = ctx; - dc->link_srv = link_srv; - ctx->dc = dc; - link->dc = dc; - link->ctx = ctx; - aconn->dc_link = link; + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); + link = aconn->dc_link; /* HDMI signal + debounce delay + cached sink -> debounce branch. */ aconn->hdmi_hpd_debounce_delay_ms = 100; @@ -2623,42 +2648,10 @@ static void dm_test_handle_hpd_irq_helper_debounce_release_prev(struct kunit *te static void dm_test_handle_hpd_irq_helper_detect_false(struct kunit *test) { struct amdgpu_dm_connector *aconn; - struct dm_connector_state *state; struct link_service *link_srv; - struct amdgpu_device *adev; - struct dc_context *ctx; - struct dc_link *link; - struct dc *dc; - adev = dm_kunit_alloc_adev(test); - mutex_init(&adev->dm.dc_lock); - - aconn = dm_kunit_alloc_connector(test, adev, NULL); - mutex_init(&aconn->hpd_lock); - INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work, - amdgpu_dm_hdmi_hpd_debounce_work); - - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); - aconn->base.state = &state->base; - - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); - - link_srv->detect_connection_type = dm_test_detect_connection_none; + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); link_srv->detect_link = dm_test_detect_link_false; - dc->ctx = ctx; - dc->link_srv = link_srv; - ctx->dc = dc; - link->dc = dc; - link->ctx = ctx; - aconn->dc_link = link; aconn->fake_enable = true; /* No debounce delay and no force -> immediate-detect else branch. */ @@ -3315,16 +3308,8 @@ static void dm_test_pflip_high_irq_not_submitted(struct kunit *test) struct amdgpu_device *adev; adev = dm_kunit_alloc_adev(test); - acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); - - INIT_LIST_HEAD(&acrtc->base.head); - acrtc->base.dev = &adev->ddev; - acrtc->otg_inst = 0; + acrtc = dm_test_add_crtc(test, adev); acrtc->pflip_status = AMDGPU_FLIP_NONE; - list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); - KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, - dm_test_crtc_list_del, acrtc), 0); params.adev = adev; params.irq_src = (enum dc_irq_source)IRQ_TYPE_PFLIP; @@ -3380,17 +3365,9 @@ static void dm_test_crtc_high_irq_vrr_pre_ai(struct kunit *test) struct amdgpu_device *adev; adev = dm_kunit_alloc_adev(test); - acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); - - INIT_LIST_HEAD(&acrtc->base.head); - acrtc->base.dev = &adev->ddev; - acrtc->otg_inst = 0; + acrtc = dm_test_add_crtc(test, adev); /* VRR active so the !vrr_active vblank handler is skipped. */ acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE; - list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); - KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, - dm_test_crtc_list_del, acrtc), 0); /* Pre-AI family returns right after CRC handling. */ adev->family = AMDGPU_FAMILY_SI; @@ -3417,18 +3394,10 @@ static void dm_test_crtc_high_irq_vrr_ai_no_stream(struct kunit *test) struct amdgpu_device *adev; adev = dm_kunit_alloc_adev(test); - acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); - - INIT_LIST_HEAD(&acrtc->base.head); - acrtc->base.dev = &adev->ddev; - acrtc->otg_inst = 0; + acrtc = dm_test_add_crtc(test, adev); acrtc->pflip_status = AMDGPU_FLIP_NONE; /* VRR active so the !vrr_active vblank handler is skipped. */ acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE; - list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); - KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, - dm_test_crtc_list_del, acrtc), 0); /* AI+ family runs the freesync section; no stream skips it. */ adev->family = AMDGPU_FAMILY_AI; @@ -3625,14 +3594,14 @@ static void dm_test_dce110_register_irq_handlers_rejects_uninitialized_sources(s KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), -EINVAL); } -/** - * dm_test_dce110_register_irq_handlers_one_crtc - Test DCE110 with 1 CRTC - * @test: The KUnit test context - * - * Exercises the VBLANK, VUPDATE, PFLIP and HPD for-loop bodies with a - * fake IRQ service that maps source IDs to DC IRQ sources. +/* + * Build an adev/dc pair with one CRTC, ready for either register_irq_handlers() + * entry point, using the given fake IRQ service to map source IDs. A service + * that only maps a subset lets a chosen register loop hit its invalid-source + * guard, and clearing an amdgpu_irq_src's funcs makes its add_id() fail. */ -static void dm_test_dce110_register_irq_handlers_one_crtc(struct kunit *test) +static struct amdgpu_device *dm_test_setup_irq_regs(struct kunit *test, + const struct irq_service_funcs *funcs) { struct amdgpu_device *adev; struct dc *dc; @@ -3640,14 +3609,31 @@ static void dm_test_dce110_register_irq_handlers_one_crtc(struct kunit *test) adev = dm_kunit_alloc_adev(test); KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources, adev), 0); - dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dce110); + dc = dm_test_alloc_dc_with_irq_service(test, funcs); dc->ctx->dce_version = DCE_VERSION_11_0; + dc->caps.max_otg_num = 1; adev->dm.dc = dc; adev->mode_info.num_crtc = 1; adev->mode_info.num_hpd = 1; amdgpu_dm_set_irq_funcs(adev); KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); + return adev; +} + +/** + * dm_test_dce110_register_irq_handlers_one_crtc - Test DCE110 with 1 CRTC + * @test: The KUnit test context + * + * Exercises the VBLANK, VUPDATE, PFLIP and HPD for-loop bodies with a + * fake IRQ service that maps source IDs to DC IRQ sources. + */ +static void dm_test_dce110_register_irq_handlers_one_crtc(struct kunit *test) +{ + struct amdgpu_device *adev; + + adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_dce110); + KUNIT_EXPECT_EQ(test, amdgpu_dm_dce110_register_irq_handlers(adev), 0); /* Verify VBLANK params were populated */ @@ -3702,18 +3688,8 @@ static void dm_test_dcn10_register_irq_handlers_zero_crtc(struct kunit *test) static void dm_test_dcn10_register_irq_handlers_one_crtc(struct kunit *test) { struct amdgpu_device *adev; - struct dc *dc; - adev = dm_kunit_alloc_adev(test); - KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_free_irq_sources, - adev), 0); - dc = dm_test_alloc_dc_with_irq_service(test, &dm_test_irq_service_funcs_dcn10); - adev->dm.dc = dc; - adev->mode_info.num_crtc = 1; - adev->mode_info.num_hpd = 1; - dc->caps.max_otg_num = 1; - amdgpu_dm_set_irq_funcs(adev); - KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); + adev = dm_test_setup_irq_regs(test, &dm_test_irq_service_funcs_dcn10); KUNIT_EXPECT_EQ(test, amdgpu_dm_dcn10_register_irq_handlers(adev), 0); -- 2.43.0
