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>
This commit is contained in:
Maxime Ripard
2025-03-13 13:00:03 +01:00
parent 56ae621241
commit d4dfff472e

View File

@@ -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");