[PATCH 43/59] drm/amd/display: Test mod_power stream updates on modeset
Alex Hung <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
[WHAT] Add KUnit tests for amdgpu_dm_mod_power_update_streams() covering empty and fast commits plus CRTC enable, replacement, and disable, and for amdgpu_dm_mod_power_setup_streams() covering empty, modeset, and fast updates. [HOW] Leave dm->power_module NULL and PSR/Replay feature bits clear so the DM stream transition logic runs without a live power module. 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 | 10 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 + .../display/amdgpu_dm/tests/amdgpu_dm_test.c | 170 ++++++++++++++++++ 3 files changed, 180 insertions(+), 4 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 2085625f8509..8e62d451e0b1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4341,8 +4341,8 @@ static void dm_clear_writeback(struct amdgpu_display_manager *dm, * in preparation for hardware programming. See also * amdgpu_dm_mod_power_setup_streams() for post-modeset mod_power setup. */ -static void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, - struct amdgpu_display_manager *dm) +STATIC_IFN_KUNIT void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, + struct amdgpu_display_manager *dm) { struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -4395,6 +4395,7 @@ static void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, } } } +EXPORT_IF_KUNIT(amdgpu_dm_mod_power_update_streams); /** * amdgpu_dm_mod_power_setup_streams - setup mod_power stream state post modeset @@ -4404,8 +4405,8 @@ static void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, * Notify mod_power of mode_change. This needs to be done after dc_stream * updates have been committed, and VRR parameters have been updated. */ -static void amdgpu_dm_mod_power_setup_streams(struct drm_atomic_commit *state, - struct amdgpu_display_manager *dm) +STATIC_IFN_KUNIT void amdgpu_dm_mod_power_setup_streams(struct drm_atomic_commit *state, + struct amdgpu_display_manager *dm) { struct dm_crtc_state *dm_new_crtc_state; struct drm_crtc_state *new_crtc_state; @@ -4442,6 +4443,7 @@ static void amdgpu_dm_mod_power_setup_streams(struct drm_atomic_commit *state, } } +EXPORT_IF_KUNIT(amdgpu_dm_mod_power_setup_streams); static void amdgpu_dm_commit_streams(struct drm_atomic_commit *state, struct dc_state *dc_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 35b8725a63af..7308067b4d13 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1205,6 +1205,10 @@ 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); +void amdgpu_dm_mod_power_update_streams(struct drm_atomic_commit *state, + struct amdgpu_display_manager *dm); +void amdgpu_dm_mod_power_setup_streams(struct drm_atomic_commit *state, + struct amdgpu_display_manager *dm); int amdgpu_dm_early_fini(struct amdgpu_ip_block *ip_block); int dm_sw_fini(struct amdgpu_ip_block *ip_block); int dm_oem_i2c_hw_init(struct amdgpu_device *adev); 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 27182f65e5c3..bb09ebc07435 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 @@ -3040,6 +3040,30 @@ static void dm_test_aquire_global_lock_waits_commit(struct kunit *test) KUNIT_EXPECT_EQ(test, ret, 0); } +/** + * dm_test_mod_power_update_streams_empty - Test an empty commit updates no streams + * @test: The KUnit test context + */ +static void dm_test_mod_power_update_streams_empty(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + + amdgpu_dm_mod_power_update_streams(dm_test_alloc_commit(test, adev), + &adev->dm); +} + +/** + * dm_test_mod_power_setup_streams_empty - Test an empty commit sets up no streams + * @test: The KUnit test context + */ +static void dm_test_mod_power_setup_streams_empty(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + + amdgpu_dm_mod_power_setup_streams(dm_test_alloc_commit(test, adev), + &adev->dm); +} + /* Tests for amdgpu_dm_trigger_timing_sync() */ /** @@ -3174,6 +3198,144 @@ static void dm_test_emulated_link_detect_bad_signal(struct kunit *test) KUNIT_EXPECT_NULL(test, link->local_sink); } +/* Tests for the mod_power modeset helpers */ + +struct dm_test_modeset_ctx { + struct amdgpu_device *adev; + struct drm_atomic_commit *state; + struct amdgpu_crtc *acrtc; + struct dm_crtc_state *old_crtc_state; + struct dm_crtc_state *new_crtc_state; +}; + +/* + * A modeset commit on one CRTC with an old and a new stream. dm->power_module + * stays NULL, which every mod_power entry point treats as a no-op, so the DM + * side of the modeset can be walked without a live power module. + */ +static struct dm_test_modeset_ctx *dm_test_modeset_ctx_alloc(struct kunit *test) +{ + struct amdgpu_dm_connector *aconnector; + struct dm_test_modeset_ctx *ctx; + struct dc_link *link; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx); + + ctx->adev = dm_kunit_alloc_adev(test); + ctx->state = dm_test_alloc_commit(test, ctx->adev); + ctx->acrtc = kunit_kzalloc(test, sizeof(*ctx->acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc); + ctx->old_crtc_state = kunit_kzalloc(test, sizeof(*ctx->old_crtc_state), + GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->old_crtc_state); + ctx->new_crtc_state = kunit_kzalloc(test, sizeof(*ctx->new_crtc_state), + GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->new_crtc_state); + ctx->state->crtcs = kunit_kzalloc(test, sizeof(*ctx->state->crtcs), + GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ctx->state->crtcs); + aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, aconnector); + + link = dm_kunit_alloc_link(test); + ctx->old_crtc_state->stream = dm_kunit_alloc_stream(test, link); + ctx->new_crtc_state->stream = dm_kunit_alloc_stream(test, link); + ctx->new_crtc_state->stream->dm_stream_context = aconnector; + + ctx->adev->ddev.mode_config.num_crtc = 1; + ctx->adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test); + mutex_init(&ctx->adev->dm.dc_lock); + ctx->new_crtc_state->base.mode_changed = true; + ctx->new_crtc_state->base.state = ctx->state; + ctx->state->crtcs[0].ptr = &ctx->acrtc->base; + ctx->state->crtcs[0].old_state = &ctx->old_crtc_state->base; + ctx->state->crtcs[0].new_state = &ctx->new_crtc_state->base; + + return ctx; +} + +/** + * dm_test_mod_power_update_streams_no_modeset - Test fast updates are skipped + * @test: The KUnit test context + */ +static void dm_test_mod_power_update_streams_no_modeset(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->new_crtc_state->base.mode_changed = false; + ctx->new_crtc_state->base.active = true; + + amdgpu_dm_mod_power_update_streams(ctx->state, &ctx->adev->dm); +} + +/** + * dm_test_mod_power_update_streams_enable - Test enabling a CRTC adds the stream + * @test: The KUnit test context + */ +static void dm_test_mod_power_update_streams_enable(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->new_crtc_state->base.active = true; + + amdgpu_dm_mod_power_update_streams(ctx->state, &ctx->adev->dm); +} + +/** + * dm_test_mod_power_update_streams_replace - Test a re-modeset replaces the stream + * @test: The KUnit test context + */ +static void dm_test_mod_power_update_streams_replace(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->old_crtc_state->base.active = true; + ctx->new_crtc_state->base.active = true; + + amdgpu_dm_mod_power_update_streams(ctx->state, &ctx->adev->dm); +} + +/** + * dm_test_mod_power_update_streams_disable - Test disabling a CRTC removes the stream + * @test: The KUnit test context + */ +static void dm_test_mod_power_update_streams_disable(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->old_crtc_state->base.active = true; + + amdgpu_dm_mod_power_update_streams(ctx->state, &ctx->adev->dm); +} + +/** + * dm_test_mod_power_setup_streams_modeset - Test a modeset sets up the new stream + * @test: The KUnit test context + */ +static void dm_test_mod_power_setup_streams_modeset(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->new_crtc_state->base.active = true; + + amdgpu_dm_mod_power_setup_streams(ctx->state, &ctx->adev->dm); +} + +/** + * dm_test_mod_power_setup_streams_no_modeset - Test fast updates set up no streams + * @test: The KUnit test context + */ +static void dm_test_mod_power_setup_streams_no_modeset(struct kunit *test) +{ + struct dm_test_modeset_ctx *ctx = dm_test_modeset_ctx_alloc(test); + + ctx->new_crtc_state->base.mode_changed = false; + ctx->new_crtc_state->base.active = true; + + amdgpu_dm_mod_power_setup_streams(ctx->state, &ctx->adev->dm); +} + static struct kunit_case amdgpu_dm_tests[] = { /* Simple DM callbacks */ KUNIT_CASE(dm_test_wait_for_idle), @@ -3323,6 +3485,14 @@ static struct kunit_case amdgpu_dm_tests[] = { 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), + KUNIT_CASE(dm_test_mod_power_update_streams_empty), + KUNIT_CASE(dm_test_mod_power_update_streams_no_modeset), + KUNIT_CASE(dm_test_mod_power_update_streams_enable), + KUNIT_CASE(dm_test_mod_power_update_streams_replace), + KUNIT_CASE(dm_test_mod_power_update_streams_disable), + KUNIT_CASE(dm_test_mod_power_setup_streams_empty), + KUNIT_CASE(dm_test_mod_power_setup_streams_modeset), + KUNIT_CASE(dm_test_mod_power_setup_streams_no_modeset), /* amdgpu_dm_trigger_timing_sync */ KUNIT_CASE(dm_test_trigger_timing_sync_no_state), KUNIT_CASE(dm_test_trigger_timing_sync_streams), -- 2.43.0