mirror of
https://github.com/torvalds/linux.git
synced 2026-10-30 14:06:03 +01:00
drm/amd/display: Test vblank event arming
[WHAT] Add KUnit tests for dm_arm_vblank_event() and dm_arm_vblank_event_pre_programming() covering missing events, inactive CRTCs, page-flip and cursor updates, and vblank reference acquisition. [HOW] Use one pending-event fixture. Initialize DRM vblank state only for the pre-programming tests and release every acquired reference. Assisted-by: Copilot:Claude-Opus-5 GPT-5.6-Sol Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
1903ffbca1
commit
b56e334dbd
|
|
@ -3723,10 +3723,10 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
}
|
||||
|
||||
static void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update,
|
||||
bool cursor_update)
|
||||
STATIC_IFN_KUNIT void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update,
|
||||
bool cursor_update)
|
||||
{
|
||||
assert_spin_locked(&acrtc->base.dev->event_lock);
|
||||
|
||||
|
|
@ -3749,6 +3749,7 @@ static void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
|||
acrtc->base.state->event = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_arm_vblank_event);
|
||||
|
||||
/**
|
||||
* dm_arm_vblank_event_pre_programming - Prepare for programming
|
||||
|
|
@ -3761,10 +3762,10 @@ static void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
|||
* be programmed. Do this before programming so the HW is not in any
|
||||
* idle-optimized state (such as PSR).
|
||||
*/
|
||||
static void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update,
|
||||
bool cursor_update)
|
||||
STATIC_IFN_KUNIT void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update,
|
||||
bool cursor_update)
|
||||
{
|
||||
assert_spin_locked(&acrtc->base.dev->event_lock);
|
||||
|
||||
|
|
@ -3774,6 +3775,7 @@ static void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
|
|||
if (pflip_update || cursor_update)
|
||||
drm_crtc_vblank_get(&acrtc->base);
|
||||
}
|
||||
EXPORT_IF_KUNIT(dm_arm_vblank_event_pre_programming);
|
||||
|
||||
static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
|
||||
struct drm_device *dev,
|
||||
|
|
|
|||
|
|
@ -1176,6 +1176,12 @@ void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state);
|
|||
void amdgpu_dm_update_cursor(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_plane_state,
|
||||
struct dc_stream_update *update);
|
||||
void dm_arm_vblank_event(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update, bool cursor_update);
|
||||
void dm_arm_vblank_event_pre_programming(struct amdgpu_crtc *acrtc,
|
||||
struct dm_crtc_state *acrtc_state,
|
||||
bool pflip_update, bool cursor_update);
|
||||
int add_affected_mst_dsc_crtcs(struct drm_atomic_commit *state,
|
||||
struct drm_crtc *crtc);
|
||||
int dm_plane_layer_index_cmp(const void *a, const void *b);
|
||||
|
|
|
|||
|
|
@ -1552,6 +1552,183 @@ static void dm_test_update_cursor_disables_stream(struct kunit *test)
|
|||
KUNIT_EXPECT_NULL(test, update->cursor_attributes);
|
||||
}
|
||||
|
||||
/* Tests for dm_arm_vblank_event() */
|
||||
|
||||
struct dm_test_vblank_ctx {
|
||||
struct amdgpu_device *adev;
|
||||
struct amdgpu_crtc *acrtc;
|
||||
struct dm_crtc_state *acrtc_state;
|
||||
struct drm_pending_vblank_event *event;
|
||||
};
|
||||
|
||||
/*
|
||||
* A CRTC with one active plane and a pending vblank event. There is no
|
||||
* initialised vblank, so drm_crtc_vblank_get() fails, which the function under
|
||||
* test ignores.
|
||||
*/
|
||||
static struct dm_test_vblank_ctx *dm_test_vblank_ctx_alloc(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ctx);
|
||||
|
||||
ctx->adev = dm_kunit_alloc_adev(test);
|
||||
ctx->acrtc = kunit_kzalloc(test, sizeof(*ctx->acrtc), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc);
|
||||
ctx->acrtc_state = kunit_kzalloc(test, sizeof(*ctx->acrtc_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ctx->acrtc_state);
|
||||
ctx->event = kunit_kzalloc(test, sizeof(*ctx->event), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ctx->event);
|
||||
|
||||
ctx->acrtc->base.dev = &ctx->adev->ddev;
|
||||
ctx->acrtc->base.state = &ctx->acrtc_state->base;
|
||||
ctx->acrtc_state->base.event = ctx->event;
|
||||
ctx->acrtc_state->active_planes = 1;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void dm_test_arm_vblank(struct dm_test_vblank_ctx *ctx, bool pflip_update,
|
||||
bool cursor_update)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->adev->ddev.event_lock, flags);
|
||||
dm_arm_vblank_event(ctx->acrtc, ctx->acrtc_state, pflip_update,
|
||||
cursor_update);
|
||||
spin_unlock_irqrestore(&ctx->adev->ddev.event_lock, flags);
|
||||
}
|
||||
|
||||
static void dm_test_arm_vblank_pre_programming(struct dm_test_vblank_ctx *ctx,
|
||||
bool pflip_update, bool cursor_update)
|
||||
{
|
||||
struct dm_crtc_state *state = ctx->acrtc_state;
|
||||
struct amdgpu_crtc *acrtc = ctx->acrtc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->adev->ddev.event_lock, flags);
|
||||
dm_arm_vblank_event_pre_programming(acrtc, state, pflip_update, cursor_update);
|
||||
spin_unlock_irqrestore(&ctx->adev->ddev.event_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_pre_programming_no_event - Test missing event takes no reference
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_pre_programming_no_event(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
struct drm_vblank_crtc *vblank;
|
||||
|
||||
KUNIT_ASSERT_EQ(test, drm_vblank_init(&ctx->adev->ddev, 1), 0);
|
||||
vblank = drm_crtc_vblank_crtc(&ctx->acrtc->base);
|
||||
ctx->acrtc_state->base.event = NULL;
|
||||
|
||||
dm_test_arm_vblank_pre_programming(ctx, true, false);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, atomic_read(&vblank->refcount), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_pre_programming_no_planes - Test inactive CRTC takes no reference
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_pre_programming_no_planes(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
struct drm_vblank_crtc *vblank;
|
||||
|
||||
KUNIT_ASSERT_EQ(test, drm_vblank_init(&ctx->adev->ddev, 1), 0);
|
||||
vblank = drm_crtc_vblank_crtc(&ctx->acrtc->base);
|
||||
ctx->acrtc_state->active_planes = 0;
|
||||
|
||||
dm_test_arm_vblank_pre_programming(ctx, false, true);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, atomic_read(&vblank->refcount), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_pre_programming_update - Test an update takes a vblank reference
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_pre_programming_update(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
struct drm_vblank_crtc *vblank;
|
||||
|
||||
KUNIT_ASSERT_EQ(test, drm_vblank_init(&ctx->adev->ddev, 1), 0);
|
||||
vblank = drm_crtc_vblank_crtc(&ctx->acrtc->base);
|
||||
|
||||
dm_test_arm_vblank_pre_programming(ctx, true, false);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, atomic_read(&vblank->refcount), 1);
|
||||
drm_crtc_vblank_put(&ctx->acrtc->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_event_no_event - Test a commit without an event is a no-op
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_event_no_event(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
|
||||
ctx->acrtc_state->base.event = NULL;
|
||||
|
||||
dm_test_arm_vblank(ctx, true, false);
|
||||
|
||||
KUNIT_EXPECT_NULL(test, ctx->acrtc->event);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_event_no_active_planes - Test an event is left armed without planes
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_event_no_active_planes(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
|
||||
ctx->acrtc_state->active_planes = 0;
|
||||
|
||||
dm_test_arm_vblank(ctx, false, true);
|
||||
|
||||
KUNIT_EXPECT_NULL(test, ctx->acrtc->event);
|
||||
KUNIT_EXPECT_PTR_EQ(test, ctx->acrtc_state->base.event, ctx->event);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_event_pflip - Test a page flip arms the flip ISR
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_event_pflip(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
|
||||
dm_test_arm_vblank(ctx, true, false);
|
||||
|
||||
KUNIT_EXPECT_PTR_EQ(test, ctx->acrtc->event, ctx->event);
|
||||
KUNIT_EXPECT_NULL(test, ctx->acrtc_state->base.event);
|
||||
KUNIT_EXPECT_EQ(test, (int)ctx->acrtc->pflip_status,
|
||||
(int)AMDGPU_FLIP_SUBMITTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_arm_vblank_event_cursor - Test a cursor update consumes the event
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_arm_vblank_event_cursor(struct kunit *test)
|
||||
{
|
||||
struct dm_test_vblank_ctx *ctx = dm_test_vblank_ctx_alloc(test);
|
||||
|
||||
dm_test_arm_vblank(ctx, false, true);
|
||||
|
||||
KUNIT_EXPECT_PTR_EQ(test, ctx->acrtc->event, ctx->event);
|
||||
KUNIT_EXPECT_NULL(test, ctx->acrtc_state->base.event);
|
||||
KUNIT_EXPECT_EQ(test, (int)ctx->acrtc->pflip_status,
|
||||
(int)AMDGPU_FLIP_NONE);
|
||||
}
|
||||
|
||||
static struct kunit_case amdgpu_dm_tests[] = {
|
||||
/* Simple DM callbacks */
|
||||
KUNIT_CASE(dm_test_wait_for_idle),
|
||||
|
|
@ -1637,6 +1814,14 @@ static struct kunit_case amdgpu_dm_tests[] = {
|
|||
KUNIT_CASE(dm_test_commit_cursors_updates_cursor),
|
||||
KUNIT_CASE(dm_test_update_cursor_no_framebuffer),
|
||||
KUNIT_CASE(dm_test_update_cursor_disables_stream),
|
||||
/* dm_arm_vblank_event */
|
||||
KUNIT_CASE(dm_test_arm_vblank_event_no_event),
|
||||
KUNIT_CASE(dm_test_arm_vblank_event_no_active_planes),
|
||||
KUNIT_CASE(dm_test_arm_vblank_event_pflip),
|
||||
KUNIT_CASE(dm_test_arm_vblank_event_cursor),
|
||||
KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_event),
|
||||
KUNIT_CASE(dm_test_arm_vblank_pre_programming_no_planes),
|
||||
KUNIT_CASE(dm_test_arm_vblank_pre_programming_update),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user