diff options
| author | Maxime Ripard <mripard@kernel.org> | 2025-03-13 13:00:03 +0100 |
|---|---|---|
| committer | Maxime Ripard <mripard@kernel.org> | 2025-03-20 14:45:49 +0100 |
| commit | d4dfff472e3936bd2ff3a61c3830237f8c442e41 (patch) | |
| tree | d6e36448545c2411d56218de6ebf4ae6798ce5a9 | |
| parent | 56ae6212417702f7e456007b2afa834810ed10a6 (diff) | |
drm/tests: bridge: Provide tests for drm_bridge_helper_reset_crtc
Let's provide a bunch of kunit tests to make sure
drm_bridge_helper_reset_crtc() works as expected.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20250313-bridge-connector-v6-9-511c54a604fb@kernel.org
Signed-off-by: Maxime Ripard <mripard@kernel.org>
| -rw-r--r-- | drivers/gpu/drm/tests/drm_bridge_test.c | 209 |
1 files changed, 208 insertions, 1 deletions
diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c index c0a05c459d95..ff88ec2e911c 100644 --- a/drivers/gpu/drm/tests/drm_bridge_test.c +++ b/drivers/gpu/drm/tests/drm_bridge_test.c @@ -5,6 +5,7 @@ #include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_bridge_connector.h> +#include <drm/drm_bridge_helper.h> #include <drm/drm_kunit_helpers.h> #include <kunit/test.h> @@ -16,12 +17,52 @@ struct drm_bridge_init_priv { struct drm_encoder encoder; struct drm_bridge bridge; struct drm_connector *connector; + unsigned int enable_count; + unsigned int disable_count; }; +static void drm_test_bridge_enable(struct drm_bridge *bridge) +{ + struct drm_bridge_init_priv *priv = + container_of(bridge, struct drm_bridge_init_priv, bridge); + + priv->enable_count++; +} + +static void drm_test_bridge_disable(struct drm_bridge *bridge) +{ + struct drm_bridge_init_priv *priv = + container_of(bridge, struct drm_bridge_init_priv, bridge); + + priv->disable_count++; +} + static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = { + .enable = drm_test_bridge_enable, + .disable = drm_test_bridge_disable, }; +static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct drm_bridge_init_priv *priv = + container_of(bridge, struct drm_bridge_init_priv, bridge); + + priv->enable_count++; +} + +static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct drm_bridge_init_priv *priv = + container_of(bridge, struct drm_bridge_init_priv, bridge); + + priv->disable_count++; +} + static const struct drm_bridge_funcs drm_test_bridge_atomic_funcs = { + .atomic_enable = drm_test_bridge_atomic_enable, + .atomic_disable = drm_test_bridge_atomic_disable, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_reset = drm_atomic_helper_bridge_reset, @@ -203,7 +244,173 @@ static struct kunit_suite drm_bridge_get_current_state_test_suite = { .test_cases = drm_bridge_get_current_state_tests, }; -kunit_test_suite(drm_bridge_get_current_state_test_suite); +/* + * Test that an atomic bridge is properly power-cycled when calling + * drm_bridge_helper_reset_crtc(). + */ +static void drm_test_drm_bridge_helper_reset_crtc_atomic(struct kunit *test) +{ + struct drm_modeset_acquire_ctx ctx; + struct drm_bridge_init_priv *priv; + struct drm_display_mode *mode; + struct drm_bridge *bridge; + int ret; + + priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + + mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); + + drm_modeset_acquire_init(&ctx, 0); + +retry_commit: + ret = drm_kunit_helper_enable_crtc_connector(test, + &priv->drm, priv->crtc, + priv->connector, + mode, + &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry_commit; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + bridge = &priv->bridge; + KUNIT_ASSERT_EQ(test, priv->enable_count, 1); + KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + + drm_modeset_acquire_init(&ctx, 0); + +retry_reset: + ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry_reset; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + KUNIT_EXPECT_EQ(test, priv->enable_count, 2); + KUNIT_EXPECT_EQ(test, priv->disable_count, 1); +} + +/* + * Test that calling drm_bridge_helper_reset_crtc() on a disabled atomic + * bridge will fail and not call the enable / disable callbacks + */ +static void drm_test_drm_bridge_helper_reset_crtc_atomic_disabled(struct kunit *test) +{ + struct drm_modeset_acquire_ctx ctx; + struct drm_bridge_init_priv *priv; + struct drm_display_mode *mode; + struct drm_bridge *bridge; + int ret; + + priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + + mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); + + bridge = &priv->bridge; + KUNIT_ASSERT_EQ(test, priv->enable_count, 0); + KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + + drm_modeset_acquire_init(&ctx, 0); + +retry_reset: + ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry_reset; + } + KUNIT_EXPECT_LT(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + KUNIT_EXPECT_EQ(test, priv->enable_count, 0); + KUNIT_EXPECT_EQ(test, priv->disable_count, 0); +} + +/* + * Test that a non-atomic bridge is properly power-cycled when calling + * drm_bridge_helper_reset_crtc(). + */ +static void drm_test_drm_bridge_helper_reset_crtc_legacy(struct kunit *test) +{ + struct drm_modeset_acquire_ctx ctx; + struct drm_bridge_init_priv *priv; + struct drm_display_mode *mode; + struct drm_bridge *bridge; + int ret; + + priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + + mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); + + drm_modeset_acquire_init(&ctx, 0); + +retry_commit: + ret = drm_kunit_helper_enable_crtc_connector(test, + &priv->drm, priv->crtc, + priv->connector, + mode, + &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry_commit; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + bridge = &priv->bridge; + KUNIT_ASSERT_EQ(test, priv->enable_count, 1); + KUNIT_ASSERT_EQ(test, priv->disable_count, 0); + + drm_modeset_acquire_init(&ctx, 0); + +retry_reset: + ret = drm_bridge_helper_reset_crtc(bridge, &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry_reset; + } + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + KUNIT_EXPECT_EQ(test, priv->enable_count, 2); + KUNIT_EXPECT_EQ(test, priv->disable_count, 1); +} + +static struct kunit_case drm_bridge_helper_reset_crtc_tests[] = { + KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic), + KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic_disabled), + KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_legacy), + { } +}; + +static struct kunit_suite drm_bridge_helper_reset_crtc_test_suite = { + .name = "drm_test_bridge_helper_reset_crtc", + .test_cases = drm_bridge_helper_reset_crtc_tests, +}; + +kunit_test_suites( + &drm_bridge_get_current_state_test_suite, + &drm_bridge_helper_reset_crtc_test_suite, +); MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); MODULE_DESCRIPTION("Kunit test for drm_bridge functions"); |
