diff options
| author | Ray Wu <ray.wu@amd.com> | 2026-08-28 10:58:39 +0800 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-09-17 11:38:26 -0400 |
| commit | 2f08de495c6d443a7964e30edb0e4d16597f0cfd (patch) | |
| tree | 37eabdb28393079283a2355edaf8015aa2168c39 /drivers/gpu/drm/amd/display/amdgpu_dm/tests | |
| parent | acb623f3c2fb3493e8521362e07492eb46920392 (diff) | |
| download | linux-next-2f08de495c6d443a7964e30edb0e4d16597f0cfd.tar.gz linux-next-2f08de495c6d443a7964e30edb0e4d16597f0cfd.zip | |
drm/amd/display: Flush ISM work before releasing the stream
[Why]
ISM timers are not tied to the atomic commit, so a timer armed before a
DPMS off can still fire after the stream is released. The external display
check in dcn35_apply_idle_power_optimizations() loops over the active
streams, so with none left it never runs and idle is allowed on an
external-only system.
[How]
Wait out pending and in-flight ISM work before dc_stream_release(); dc_lock
is not held there, so the sync wait is safe. Rename amdgpu_dm_ism_fini() to
amdgpu_dm_ism_flush() and assert dc_lock is not held.
Assisted-by: Cursor:Claude-Opus-5
Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/tests')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_ism_test.c | 83 |
1 files changed, 42 insertions, 41 deletions
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 b77df47d3095..a9c6485e2a9e 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 @@ -642,31 +642,6 @@ static void dm_test_ism_init_sets_initial_state(struct kunit *test) KUNIT_EXPECT_EQ(test, ism->config.sso_num_frames, config.sso_num_frames); } -/* ===== Tests for amdgpu_dm_ism_fini ===== */ - -/** - * dm_test_ism_fini_after_init - fini cancels never-scheduled work without error - * @test: KUnit test context - */ -static void dm_test_ism_fini_after_init(struct kunit *test) -{ - struct amdgpu_dm_ism *ism = alloc_test_ism(test); - struct amdgpu_dm_ism_config config = { - .filter_num_frames = 5, - .filter_entry_count = 3, - .activation_num_delay_frames = 10, - .sso_num_frames = 2, - }; - - amdgpu_dm_ism_init(ism, &config); - /* Work was never scheduled; cancel_delayed_work_sync is a no-op. */ - amdgpu_dm_ism_fini(ism); - - /* FSM state is untouched by fini */ - KUNIT_EXPECT_EQ(test, (int)ism->current_state, - (int)DM_ISM_STATE_FULL_POWER_RUNNING); -} - /* ===== Tests for dm_ism_set_last_idle_ts ===== */ /** @@ -897,6 +872,32 @@ static void register_test_acrtc(struct amdgpu_device *adev, list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); } +/* ===== Tests for amdgpu_dm_ism_flush ===== */ + +/** + * dm_test_ism_flush_after_init - flush cancels never-scheduled work without error + * @test: KUnit test context + */ +static void dm_test_ism_flush_after_init(struct kunit *test) +{ + struct amdgpu_crtc *acrtc = alloc_test_acrtc(test, NULL); + struct amdgpu_dm_ism *ism = &acrtc->ism; + struct amdgpu_dm_ism_config config = { + .filter_num_frames = 5, + .filter_entry_count = 3, + .activation_num_delay_frames = 10, + .sso_num_frames = 2, + }; + + amdgpu_dm_ism_init(ism, &config); + /* Work was never scheduled; cancel_delayed_work_sync is a no-op. */ + amdgpu_dm_ism_flush(ism); + + /* FSM state is untouched by flush */ + KUNIT_EXPECT_EQ(test, (int)ism->current_state, + (int)DM_ISM_STATE_FULL_POWER_RUNNING); +} + /* ===== Tests for amdgpu_dm_ism_commit_event ===== */ /** @@ -922,7 +923,7 @@ static void dm_test_ism_commit_event_no_state(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, (int)DM_ISM_STATE_FULL_POWER_RUNNING); - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -958,7 +959,7 @@ static void dm_test_ism_commit_event_cursor_transition(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, (int)DM_ISM_STATE_FULL_POWER_RUNNING); - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -988,7 +989,7 @@ static void dm_test_ism_commit_event_invalid_event(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, (int)DM_ISM_STATE_FULL_POWER_RUNNING); - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /* ===== Tests for amdgpu_dm_ism_force_full_power ===== */ @@ -1020,7 +1021,7 @@ static void dm_test_ism_force_full_power(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, (int)DM_ISM_STATE_FULL_POWER_RUNNING); - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /* ===== Tests for amdgpu_dm_ism_disable / amdgpu_dm_ism_enable ===== */ @@ -1048,7 +1049,7 @@ static void dm_test_ism_disable_enable_cycle(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state, (int)DM_ISM_STATE_FULL_POWER_RUNNING); - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /* ===== Tests for dm_ism_dispatch_power_state (via commit_event) ===== */ @@ -1127,7 +1128,7 @@ static void dm_test_ism_dispatch_hysteresis_schedule_and_cancel(struct kunit *te (int)DM_ISM_STATE_HYSTERESIS_BUSY); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1183,7 +1184,7 @@ static void dm_test_ism_dispatch_optimized_idle_defers_sso(struct kunit *test) cancel_delayed_work(&acrtc->ism.sso_delayed_work); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /* @@ -1285,7 +1286,7 @@ static void dm_test_ism_commit_allows_idle_on_optimized_idle(struct kunit *test) cancel_delayed_work(&acrtc->ism.sso_delayed_work); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1322,7 +1323,7 @@ static void dm_test_ism_commit_enables_sso_on_optimized_idle_sso(struct kunit *t KUNIT_EXPECT_TRUE(test, adev->dm.dc->idle_optimizations_allowed); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1371,7 +1372,7 @@ static void dm_test_ism_commit_disallows_idle_on_timer_aborted(struct kunit *tes KUNIT_EXPECT_FALSE(test, adev->dm.dc->idle_optimizations_allowed); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1413,7 +1414,7 @@ static void dm_test_ism_exit_from_optimized_idle_disallows_idle(struct kunit *te KUNIT_EXPECT_EQ(test, acrtc->ism.next_record_idx, 1); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1452,7 +1453,7 @@ static void dm_test_ism_exit_from_sso_disallows_idle(struct kunit *test) KUNIT_EXPECT_EQ(test, acrtc->ism.next_record_idx, 1); } - amdgpu_dm_ism_fini(&acrtc->ism); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1496,7 +1497,7 @@ static void dm_test_ism_delayed_work_runs_timer_elapsed(struct kunit *test) 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); + amdgpu_dm_ism_flush(&acrtc->ism); } /** @@ -1534,7 +1535,7 @@ static void dm_test_ism_sso_delayed_work_runs_sso_elapsed(struct kunit *test) 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); + amdgpu_dm_ism_flush(&acrtc->ism); } static struct kunit_case dm_ism_test_cases[] = { @@ -1582,8 +1583,8 @@ static struct kunit_case dm_ism_test_cases[] = { KUNIT_CASE(dm_test_ism_idle_delay_entry_count_exceeds_history_size), /* amdgpu_dm_ism_init */ KUNIT_CASE(dm_test_ism_init_sets_initial_state), - /* amdgpu_dm_ism_fini */ - KUNIT_CASE(dm_test_ism_fini_after_init), + /* amdgpu_dm_ism_flush */ + KUNIT_CASE(dm_test_ism_flush_after_init), /* dm_ism_set_last_idle_ts */ KUNIT_CASE(dm_test_ism_set_last_idle_ts_updates_timestamp), /* dm_ism_insert_record */ |
