[PATCH 34/59] drm/amd/display: Test page flip interrupt state update
Alex Hung <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
[WHAT] Add KUnit tests for dm_update_pflip_irq_state() covering DCN, where there is nothing to reapply, and DCE, where the current interrupt state is reapplied to the pageflip source. [HOW] Add a spy for the pageflip IRQ source. amdgpu_irq_update() always dispatches through src->funcs->set(), which needs a registered IH ring on real hardware, so the spy records the requested type and state instead. Assisted-by: Copilot:Claude-Opus-5 GPT-5.6-Sol Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 + .../display/amdgpu_dm/tests/amdgpu_dm_test.c | 78 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1eb2f0973aac..4650b5f09c08 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3419,8 +3419,8 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, } } -static void dm_update_pflip_irq_state(struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc) +STATIC_IFN_KUNIT void dm_update_pflip_irq_state(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc) { int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); @@ -3435,6 +3435,7 @@ static void dm_update_pflip_irq_state(struct amdgpu_device *adev, */ amdgpu_irq_update(adev, &adev->pageflip_irq, irq_type); } +EXPORT_IF_KUNIT(dm_update_pflip_irq_state); STATIC_IFN_KUNIT bool is_scaling_state_different(const struct dm_connector_state *dm_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index e4b67a0b98c3..c22266f534e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1172,6 +1172,8 @@ struct dm_atomic_state *dm_atomic_get_new_state(struct drm_atomic_commit *state) struct drm_private_state *dm_atomic_duplicate_state(struct drm_private_obj *obj); void dm_atomic_destroy_state(struct drm_private_obj *obj, struct drm_private_state *state); +void dm_update_pflip_irq_state(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc); void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state); void amdgpu_dm_update_cursor(struct drm_plane *plane, struct drm_plane_state *old_plane_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c index 648db4a58509..845638fed223 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c @@ -1729,6 +1729,81 @@ static void dm_test_arm_vblank_event_cursor(struct kunit *test) (int)AMDGPU_FLIP_NONE); } +/** + * dm_test_update_pflip_irq_state_dcn - Test DCN skips the GRPH_PFLIP reapply + * @test: The KUnit test context + */ +static void dm_test_update_pflip_irq_state_dcn(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct amdgpu_crtc *acrtc; + + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, acrtc); + + adev->mode_info.num_crtc = 1; + adev->ip_versions[DCE_HWIP][0] = IP_VERSION(3, 2, 0); + + dm_update_pflip_irq_state(adev, acrtc); +} + +/* + * Spy for the pageflip IRQ source: amdgpu_irq_update() always dispatches + * through src->funcs->set(), which needs a registered IH ring on real + * hardware. Recording the requested state instead keeps the DCE reapply path + * reachable and observable. + */ +struct dm_test_irq_spy { + unsigned int set_count; + unsigned int last_type; + enum amdgpu_interrupt_state last_state; +}; + +static struct dm_test_irq_spy dm_test_irq_spy_data; + +static int dm_test_irq_set(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, unsigned int type, + enum amdgpu_interrupt_state state) +{ + dm_test_irq_spy_data.set_count++; + dm_test_irq_spy_data.last_type = type; + dm_test_irq_spy_data.last_state = state; + + return 0; +} + +static const struct amdgpu_irq_src_funcs dm_test_irq_funcs = { + .set = dm_test_irq_set, +}; + +/** + * dm_test_update_pflip_irq_state_dce - Test DCE reapplies the GRPH_PFLIP state + * @test: The KUnit test context + */ +static void dm_test_update_pflip_irq_state_dce(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct amdgpu_crtc *acrtc; + + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, acrtc); + + memset(&dm_test_irq_spy_data, 0, sizeof(dm_test_irq_spy_data)); + adev->mode_info.num_crtc = 2; + adev->ip_versions[DCE_HWIP][0] = 0; + adev->pageflip_irq.funcs = &dm_test_irq_funcs; + acrtc->crtc_id = 1; + spin_lock_init(&adev->irq.lock); + + dm_update_pflip_irq_state(adev, acrtc); + + KUNIT_EXPECT_EQ(test, dm_test_irq_spy_data.set_count, 1U); + KUNIT_EXPECT_EQ(test, dm_test_irq_spy_data.last_type, + (unsigned int)AMDGPU_CRTC_IRQ_VBLANK2); + KUNIT_EXPECT_EQ(test, (int)dm_test_irq_spy_data.last_state, + (int)AMDGPU_IRQ_STATE_DISABLE); +} + static struct kunit_case amdgpu_dm_tests[] = { /* Simple DM callbacks */ KUNIT_CASE(dm_test_wait_for_idle), @@ -1822,6 +1897,9 @@ static struct kunit_case amdgpu_dm_tests[] = { KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_event), KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_planes), KUNIT_CASE(dm_test_arm_vblank_pre_programming_update), + /* dm_update_pflip_irq_state */ + KUNIT_CASE(dm_test_update_pflip_irq_state_dcn), + KUNIT_CASE(dm_test_update_pflip_irq_state_dce), {} }; -- 2.43.0