[PATCH 04/59] drm/amd/display: Test ISM delayed workers
Alex Hung <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
[WHAT] Add KUnit tests for dm_ism_delayed_work_func() and dm_ism_sso_delayed_work_func(). [HOW] Arm each worker through the FSM, drop dc_lock, then run the handler with flush_delayed_work(). Assisted-by: Copilot:Claude-Opus-5 Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> --- .../amdgpu_dm/tests/amdgpu_dm_ism_test.c | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_ism_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_ism_test.c index 76c2004224b8..b77df47d3095 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_ism_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_ism_test.c @@ -1455,6 +1455,88 @@ static void dm_test_ism_exit_from_sso_disallows_idle(struct kunit *test) amdgpu_dm_ism_fini(&acrtc->ism); } +/** + * dm_test_ism_delayed_work_runs_timer_elapsed - hysteresis worker fires + * @test: KUnit test context + * + * A non-zero idle-allow delay parks the FSM in HYSTERESIS_WAITING and arms the + * hysteresis worker. Flushing it runs dm_ism_delayed_work_func(), which takes + * dc_lock itself and posts TIMER_ELAPSED, cascading to OPTIMIZED_IDLE_SSO + * because the SSO delay is zero. The flush must happen without dc_lock held. + */ +static void dm_test_ism_delayed_work_runs_timer_elapsed(struct kunit *test) +{ + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc = alloc_test_acrtc(test, &adev); + struct dc_stream_state *stream; + struct amdgpu_dm_ism_config config = { + .filter_num_frames = 5, + .filter_entry_count = 3, + .activation_num_delay_frames = 10, + .filter_history_size = 8, + .filter_old_history_threshold = 0, + .sso_num_frames = 0, + }; + + stream = setup_commit_test(test, acrtc, &config); + setup_idle_delay_history(&acrtc->ism, stream); + + scoped_guard(mutex, &adev->dm.dc_lock) { + amdgpu_dm_ism_commit_event(&acrtc->ism, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED); + KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, + (int)DM_ISM_STATE_HYSTERESIS_WAITING); + KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 0); + } + + flush_delayed_work(&acrtc->ism.delayed_work); + + KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, + (int)DM_ISM_STATE_OPTIMIZED_IDLE_SSO); + KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 1); + KUNIT_EXPECT_TRUE(test, adev->dm.dc->idle_optimizations_allowed); + + amdgpu_dm_ism_fini(&acrtc->ism); +} + +/** + * dm_test_ism_sso_delayed_work_runs_sso_elapsed - SSO worker fires + * @test: KUnit test context + * + * With sso_num_frames >= filter_num_frames the OPTIMIZED_IDLE arm allows idle + * and arms the SSO worker. Flushing it runs dm_ism_sso_delayed_work_func(), + * which posts SSO_TIMER_ELAPSED; engaging SSO disallows and re-allows idle, so + * two further transitions follow the initial allow. + */ +static void dm_test_ism_sso_delayed_work_runs_sso_elapsed(struct kunit *test) +{ + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc = alloc_test_acrtc(test, &adev); + struct amdgpu_dm_ism_config config = { + .filter_num_frames = 0, + .sso_num_frames = 2, + }; + + setup_commit_test(test, acrtc, &config); + + scoped_guard(mutex, &adev->dm.dc_lock) { + amdgpu_dm_ism_commit_event(&acrtc->ism, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED); + KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, + (int)DM_ISM_STATE_OPTIMIZED_IDLE); + KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 1); + } + + flush_delayed_work(&acrtc->ism.sso_delayed_work); + + KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, + (int)DM_ISM_STATE_OPTIMIZED_IDLE_SSO); + KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 3); + KUNIT_EXPECT_TRUE(test, adev->dm.dc->idle_optimizations_allowed); + + amdgpu_dm_ism_fini(&acrtc->ism); +} + static struct kunit_case dm_ism_test_cases[] = { /* dm_ism_next_state — FULL_POWER_RUNNING */ KUNIT_CASE(dm_test_ism_next_state_running_enter_idle), @@ -1535,6 +1617,9 @@ static struct kunit_case dm_ism_test_cases[] = { /* dm_ism_dispatch_power_state previous-state arms */ KUNIT_CASE(dm_test_ism_exit_from_optimized_idle_disallows_idle), KUNIT_CASE(dm_test_ism_exit_from_sso_disallows_idle), + /* dm_ism_delayed_work_func / dm_ism_sso_delayed_work_func */ + KUNIT_CASE(dm_test_ism_delayed_work_runs_timer_elapsed), + KUNIT_CASE(dm_test_ism_sso_delayed_work_runs_sso_elapsed), {} }; -- 2.43.0