[PATCH 03/59] drm/amd/display: Test ISM idle exit arms

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for the OPTIMIZED_IDLE and OPTIMIZED_IDLE_SSO
previous-state arms of dm_ism_dispatch_power_state().

[HOW]
Cascade into each idle state, post EXIT_IDLE_REQUESTED, then check
that idle is disallowed and the idle period recorded.

These arms run on a state departure rather than on entry, so a single
event cannot reach them; the FSM has to occupy the idle state first.
Driving both steps through amdgpu_dm_ism_commit_event() keeps the test
on the real path instead of calling the dispatcher directly.

Both arms end in FULL_POWER_RUNNING and both disallow idle, so the
state alone does not tell them apart. Asserting ism->next_record_idx
pins the side effect that matters: the idle period is added to the
hysteresis history on the way out.

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      | 84 +++++++++++++++++++
 1 file changed, 84 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 5b348ded482f..76c2004224b8 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
@@ -1374,6 +1374,87 @@ static void dm_test_ism_commit_disallows_idle_on_timer_aborted(struct kunit *tes
 	amdgpu_dm_ism_fini(&acrtc->ism);
 }
 
+/**
+ * dm_test_ism_exit_from_optimized_idle_disallows_idle - leaving OPTIMIZED_IDLE
+ * @test: KUnit test context
+ *
+ * EXIT_IDLE_REQUESTED from OPTIMIZED_IDLE runs the previous-state arm of
+ * dm_ism_dispatch_power_state(): the pending SSO worker is cancelled, the idle
+ * period is recorded and the commit runs with vblank_enabled = true, which
+ * disallows idle again.
+ */
+static void dm_test_ism_exit_from_optimized_idle_disallows_idle(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);
+
+		amdgpu_dm_ism_commit_event(&acrtc->ism,
+					   DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+		KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state,
+				(int)DM_ISM_STATE_FULL_POWER_RUNNING);
+
+		/* Allow on entry, disallow on exit. */
+		KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 2);
+		KUNIT_EXPECT_FALSE(test, dm_ism_test_idle.last_allow);
+		KUNIT_EXPECT_FALSE(test, adev->dm.dc->idle_optimizations_allowed);
+		/* The idle period was recorded on the way out. */
+		KUNIT_EXPECT_EQ(test, acrtc->ism.next_record_idx, 1);
+	}
+
+	amdgpu_dm_ism_fini(&acrtc->ism);
+}
+
+/**
+ * dm_test_ism_exit_from_sso_disallows_idle - leaving OPTIMIZED_IDLE_SSO
+ * @test: KUnit test context
+ *
+ * EXIT_IDLE_REQUESTED from OPTIMIZED_IDLE_SSO runs the SSO previous-state arm:
+ * the idle period is recorded and the commit disallows idle. Unlike the
+ * OPTIMIZED_IDLE arm there is no pending SSO worker left to cancel.
+ */
+static void dm_test_ism_exit_from_sso_disallows_idle(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 = 0,
+	};
+
+	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_SSO);
+
+		amdgpu_dm_ism_commit_event(&acrtc->ism,
+					   DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+		KUNIT_EXPECT_EQ(test, (int)acrtc->ism.current_state,
+				(int)DM_ISM_STATE_FULL_POWER_RUNNING);
+
+		KUNIT_EXPECT_EQ(test, dm_ism_test_idle.calls, 2);
+		KUNIT_EXPECT_FALSE(test, dm_ism_test_idle.last_allow);
+		KUNIT_EXPECT_FALSE(test, adev->dm.dc->idle_optimizations_allowed);
+		KUNIT_EXPECT_EQ(test, acrtc->ism.next_record_idx, 1);
+	}
+
+	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),
@@ -1451,6 +1532,9 @@ static struct kunit_case dm_ism_test_cases[] = {
 	KUNIT_CASE(dm_test_ism_commit_allows_idle_on_optimized_idle),
 	KUNIT_CASE(dm_test_ism_commit_enables_sso_on_optimized_idle_sso),
 	KUNIT_CASE(dm_test_ism_commit_disallows_idle_on_timer_aborted),
+	/* 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),
 	{}
 };
 
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.