From: Alex Hung <[email protected]> [Why] Add KUnit tests for dm_clear_writeback() removing stream writeback state and dm_set_writeback() leaving a job unarmed when no DC pipe matches.
[How] Use the real DC removal helper with a state-only update_bandwidth fake, and construct the minimal DRM writeback objects needed to reach the no-pipe cleanup path. Assisted-by: Copilot:Claude-Opus-5 GPT-5.6 Sol Reviewed-by: Bhawanpreet Lakha <[email protected]> Signed-off-by: Alex Hung <[email protected]> Signed-off-by: Ray Wu <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++-- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 ++ .../display/amdgpu_dm/tests/amdgpu_dm_test.c | 77 +++++++++++++++++++ 3 files changed, 94 insertions(+), 7 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 42e2ef74c687..d94d18e884ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4375,9 +4375,9 @@ bool amdgpu_dm_crtc_complete_writeback(struct amdgpu_crtc *acrtc) } EXPORT_IF_KUNIT(amdgpu_dm_crtc_complete_writeback); -static void dm_clear_writeback(struct amdgpu_display_manager *dm, - struct amdgpu_crtc *acrtc, - struct dm_crtc_state *crtc_state) +STATIC_IFN_KUNIT void dm_clear_writeback(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + struct dm_crtc_state *crtc_state) { dc_stream_remove_writeback(dm->dc, crtc_state->stream, 0); @@ -4389,6 +4389,7 @@ static void dm_clear_writeback(struct amdgpu_display_manager *dm, */ amdgpu_dm_crtc_complete_writeback(acrtc); } +EXPORT_IF_KUNIT(dm_clear_writeback); /** * amdgpu_dm_mod_power_update_streams - update mod_power stream state on modeset @@ -4722,10 +4723,11 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_commit *state, } } -static void dm_set_writeback(struct amdgpu_display_manager *dm, - struct dm_crtc_state *crtc_state, - struct drm_connector *connector, - struct drm_connector_state *new_con_state) +STATIC_IFN_KUNIT void +dm_set_writeback(struct amdgpu_display_manager *dm, + struct dm_crtc_state *crtc_state, + struct drm_connector *connector, + struct drm_connector_state *new_con_state) { struct drm_writeback_connector *wb_conn = drm_connector_to_writeback(connector); struct amdgpu_device *adev = dm->adev; @@ -4842,6 +4844,7 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm, cleanup: kfree(wb_info); } +EXPORT_IF_KUNIT(dm_set_writeback); STATIC_IFN_KUNIT void amdgpu_dm_update_hdcp(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 4d12632d048f..3c63dfcc2343 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1278,6 +1278,13 @@ void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, struct dc_state * enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc); int dm_cache_state(struct amdgpu_device *adev); void dm_destroy_cached_state(struct amdgpu_device *adev); +void dm_clear_writeback(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + struct dm_crtc_state *crtc_state); +void dm_set_writeback(struct amdgpu_display_manager *dm, + struct dm_crtc_state *crtc_state, + struct drm_connector *connector, + struct drm_connector_state *new_con_state); int dm_early_init(struct amdgpu_ip_block *ip_block); int fill_dc_plane_info_and_addr(struct amdgpu_device *adev, const struct drm_plane_state *plane_state, 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 61fa553c7a99..3209608a41b8 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 @@ -4422,6 +4422,81 @@ static void dm_test_destroy_cached_state_none(struct kunit *test) KUNIT_EXPECT_NULL(test, adev->dm.cached_state); } +static bool dm_test_update_bandwidth(struct dc *dc, struct dc_state *context) +{ + return true; +} + +/** + * dm_test_clear_writeback_removes_stream - Test teardown removes the stream writeback + * @test: The KUnit test context + */ +static void dm_test_clear_writeback_removes_stream(struct kunit *test) +{ + struct amdgpu_display_manager *dm; + struct dm_crtc_state *crtc_state; + struct amdgpu_crtc *acrtc; + struct dc_stream_state *stream; + + dm = dm_kunit_alloc_dm(test); + crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, crtc_state); + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, acrtc); + stream = dm_kunit_alloc_stream(test, NULL); + dm->dc->hwss.update_bandwidth = dm_test_update_bandwidth; + crtc_state->stream = stream; + stream->num_wb_info = 1; + stream->writeback_info[0].dwb_pipe_inst = 0; + + dm_clear_writeback(dm, acrtc, crtc_state); + + KUNIT_EXPECT_EQ(test, stream->num_wb_info, 0U); +} + +/** + * dm_test_set_writeback_no_pipe - Test a stream without a DC pipe is not armed + * @test: The KUnit test context + */ +static void dm_test_set_writeback_no_pipe(struct kunit *test) +{ + struct amdgpu_device *adev = dm_kunit_alloc_adev(test); + struct drm_writeback_connector *wb_conn; + struct drm_connector_state *conn_state; + struct drm_writeback_job *job; + struct amdgpu_framebuffer *afb; + struct dm_crtc_state *crtc_state; + struct amdgpu_crtc *acrtc; + struct dc *dc; + + wb_conn = kunit_kzalloc(test, sizeof(*wb_conn), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, wb_conn); + conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, conn_state); + job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, job); + afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, afb); + crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, crtc_state); + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, acrtc); + dc = dm_kunit_alloc_dc_with_ctx(test); + dc->current_state = dm_kunit_alloc_dc_state(test); + + adev->dm.adev = adev; + adev->dm.dc = dc; + wb_conn->encoder.crtc = &acrtc->base; + job->fb = &afb->base; + conn_state->writeback_job = job; + crtc_state->stream = dm_kunit_alloc_stream(test, NULL); + + dm_set_writeback(&adev->dm, crtc_state, &wb_conn->base, conn_state); + + KUNIT_EXPECT_NULL(test, acrtc->wb_conn); + KUNIT_EXPECT_FALSE(test, acrtc->wb_pending); +} + /* Tests for dm_update_mst_vcpi_slots_for_dsc() */ /** @@ -5237,6 +5312,8 @@ static struct kunit_case amdgpu_dm_tests[] = { KUNIT_CASE(dm_test_cache_state_empty_device), KUNIT_CASE(dm_test_cache_state_error), KUNIT_CASE(dm_test_destroy_cached_state_none), + KUNIT_CASE(dm_test_clear_writeback_removes_stream), + KUNIT_CASE(dm_test_set_writeback_no_pipe), /* dm_update_mst_vcpi_slots_for_dsc */ KUNIT_CASE(dm_test_mst_vcpi_slots_no_connector), KUNIT_CASE(dm_test_mst_vcpi_slots_skips_writeback), -- 2.43.0
