[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