[PATCH 40/59] drm/amd/display: Test global modeset lock acquisition

Alex Hung <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
[WHAT]
Add KUnit tests for do_aquire_global_lock() covering a device without
CRTCs, a CRTC with no pending commit, and a CRTC whose commit has already
completed.

[HOW]
Pre-signal the commit completions so the waits return immediately. The
extra reference the loop takes is released again, so the commit never
reaches zero and stays test-managed.

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  | 101 ++++++++++++++++++
 3 files changed, 106 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 5b69794acc58..72962c1c63e3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5311,8 +5311,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state)
  * Grabs all modesetting locks to serialize against any blocking commits,
  * Waits for completion of all non blocking commits.
  */
-static int do_aquire_global_lock(struct drm_device *dev,
-				 struct drm_atomic_commit *state)
+STATIC_IFN_KUNIT int do_aquire_global_lock(struct drm_device *dev,
+					   struct drm_atomic_commit *state)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_commit *commit;
@@ -5357,6 +5357,7 @@ static int do_aquire_global_lock(struct drm_device *dev,
 
 	return ret < 0 ? ret : 0;
 }
+EXPORT_IF_KUNIT(do_aquire_global_lock);
 
 static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 			 struct drm_atomic_commit *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 ed3210be7ab8..cec86779b959 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1203,6 +1203,8 @@ bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
 				     struct drm_crtc_state *crtc_state);
 void amdgpu_dm_dump_links_and_sinks(struct amdgpu_device *adev);
 void amdgpu_dm_update_hdcp(struct drm_atomic_commit *state);
+int do_aquire_global_lock(struct drm_device *dev,
+			  struct drm_atomic_commit *state);
 int dm_plane_layer_index_cmp(const void *a, const void *b);
 int fill_plane_color_attributes(const struct drm_plane_state *plane_state,
 				const enum surface_pixel_format format,
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 de2f2f8af230..97ff91dd7e0f 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
@@ -2942,6 +2942,104 @@ static void dm_test_update_hdcp_unchanged(struct kunit *test)
 						  DRM_MODE_CONNECTOR_DisplayPort));
 }
 
+/*
+ * Run do_aquire_global_lock() with a fresh acquire context, releasing the locks
+ * it leaves held on @state->acquire_ctx.
+ */
+static int dm_test_run_global_lock(struct kunit *test,
+				   struct amdgpu_device *adev)
+{
+	struct drm_atomic_commit *state = dm_test_alloc_commit(test, adev);
+	struct drm_modeset_acquire_ctx acquire_ctx;
+	int ret;
+
+	drm_modeset_acquire_init(&acquire_ctx, 0);
+	state->acquire_ctx = &acquire_ctx;
+
+	ret = do_aquire_global_lock(&adev->ddev, state);
+
+	drm_modeset_drop_locks(&acquire_ctx);
+	drm_modeset_acquire_fini(&acquire_ctx);
+
+	return ret;
+}
+
+/**
+ * dm_test_aquire_global_lock_no_crtc - Test the global lock is taken without CRTCs
+ * @test: The KUnit test context
+ */
+static void dm_test_aquire_global_lock_no_crtc(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	KUNIT_EXPECT_EQ(test, dm_test_run_global_lock(test, adev), 0);
+}
+
+/*
+ * A CRTC registered on @adev, needed to walk the per-CRTC commit loop.
+ */
+static struct drm_crtc *dm_test_alloc_crtc(struct kunit *test,
+					   struct amdgpu_device *adev)
+{
+	struct drm_plane *primary;
+	struct drm_crtc *crtc;
+
+	primary = drm_kunit_helper_create_primary_plane(test, &adev->ddev, NULL,
+							NULL, NULL, 0, NULL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, primary);
+	crtc = drm_kunit_helper_create_crtc(test, &adev->ddev, primary, NULL,
+					    NULL, NULL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
+
+	return crtc;
+}
+
+/**
+ * dm_test_aquire_global_lock_no_commit - Test a CRTC without a pending commit
+ * @test: The KUnit test context
+ */
+static void dm_test_aquire_global_lock_no_commit(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+
+	dm_test_alloc_crtc(test, adev);
+
+	KUNIT_EXPECT_EQ(test, dm_test_run_global_lock(test, adev), 0);
+}
+
+/**
+ * dm_test_aquire_global_lock_waits_commit - Test a completed commit is waited on
+ * @test: The KUnit test context
+ */
+static void dm_test_aquire_global_lock_waits_commit(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct drm_crtc_commit *commit;
+	struct drm_crtc *crtc;
+	int ret;
+
+	crtc = dm_test_alloc_crtc(test, adev);
+	commit = kunit_kzalloc(test, sizeof(*commit), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, commit);
+
+	/*
+	 * The extra reference taken by the loop is dropped again, so the commit
+	 * never reaches zero and stays KUnit-managed.
+	 */
+	kref_init(&commit->ref);
+	init_completion(&commit->hw_done);
+	init_completion(&commit->flip_done);
+	complete_all(&commit->hw_done);
+	complete_all(&commit->flip_done);
+	list_add_tail(&commit->commit_entry, &crtc->commit_list);
+
+	ret = dm_test_run_global_lock(test, adev);
+
+	list_del(&commit->commit_entry);
+
+	KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
 static struct kunit_case amdgpu_dm_tests[] = {
 	/* Simple DM callbacks */
 	KUNIT_CASE(dm_test_wait_for_idle),
@@ -3088,6 +3186,9 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_update_hdcp_no_workqueue),
 	KUNIT_CASE(dm_test_update_hdcp_writeback_skipped),
 	KUNIT_CASE(dm_test_update_hdcp_unchanged),
+	KUNIT_CASE(dm_test_aquire_global_lock_no_crtc),
+	KUNIT_CASE(dm_test_aquire_global_lock_no_commit),
+	KUNIT_CASE(dm_test_aquire_global_lock_waits_commit),
 	{}
 };
 
-- 
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.