Add KUnit tests for the newly introduced devm_drm_bridge_alloc(). Signed-off-by: Luca Ceresoli <luca.ceres...@bootlin.com>
--- Changed in v9: - fold drm_bridge_alloc_test_ctx into drm_bridge_init_priv (do not introduce another test context struct specific to alloc tests) - use the existing func sets for .destroy (do not introduce another struct drm_ridge_funcs specific to alloc tests) - adapt existing tests accordingly by setting .data, to allow .destroy to work - rename 'ctx' variables to 'priv' - add comment describing new tests - use KUNIT_EXPECT_TRUE instead of KUNIT_ASSERT_TRUE where applicable Changed in v8: - rebase on new patch converting drm_bridge_test.c to devm_drm_bridge_alloc() - add check that bridge is removed (thanks to the .destroy callback) - add a check with get/put Changed in v7: - rebase on current drm-misc-next, which now has a drm_bridge_test.c file - cleanup commit message Changed in v6: - update to new devm_drm_bridge_alloc() API - remove drm_test_drm_bridge_put test, not straightforward to write with the new API and the current notification mechanism - do not allocate a drm_device: a bridge is allocated without one - rename some identifiers for easier code reading This patch was added in v5. --- drivers/gpu/drm/tests/drm_bridge_test.c | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_bridge_test.c b/drivers/gpu/drm/tests/drm_bridge_test.c index af1b9f9694b0091e6eaef78cb71e39327ad8c3fa..887020141c7f42b5ae74655f9544c224d3b07605 100644 --- a/drivers/gpu/drm/tests/drm_bridge_test.c +++ b/drivers/gpu/drm/tests/drm_bridge_test.c @@ -8,6 +8,7 @@ #include <drm/drm_bridge_helper.h> #include <drm/drm_kunit_helpers.h> +#include <kunit/device.h> #include <kunit/test.h> /* @@ -21,15 +22,19 @@ struct drm_bridge_priv { unsigned int enable_count; unsigned int disable_count; struct drm_bridge bridge; + void *data; }; struct drm_bridge_init_priv { struct drm_device drm; + /** @dev: device, only for tests not needing a whole drm_device */ + struct device *dev; struct drm_plane *plane; struct drm_crtc *crtc; struct drm_encoder encoder; struct drm_bridge_priv *test_bridge; struct drm_connector *connector; + bool destroyed; }; static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge) @@ -37,6 +42,14 @@ static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge) return container_of(bridge, struct drm_bridge_priv, bridge); } +static void drm_test_bridge_priv_destroy(struct drm_bridge *bridge) +{ + struct drm_bridge_priv *bridge_priv = bridge_to_priv(bridge); + struct drm_bridge_init_priv *priv = (struct drm_bridge_init_priv *)bridge_priv->data; + + priv->destroyed = true; +} + static void drm_test_bridge_enable(struct drm_bridge *bridge) { struct drm_bridge_priv *priv = bridge_to_priv(bridge); @@ -52,6 +65,7 @@ static void drm_test_bridge_disable(struct drm_bridge *bridge) } static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = { + .destroy = drm_test_bridge_priv_destroy, .enable = drm_test_bridge_enable, .disable = drm_test_bridge_disable, }; @@ -73,6 +87,7 @@ static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge, } static const struct drm_bridge_funcs drm_test_bridge_atomic_funcs = { + .destroy = drm_test_bridge_priv_destroy, .atomic_enable = drm_test_bridge_atomic_enable, .atomic_disable = drm_test_bridge_atomic_disable, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, @@ -118,6 +133,8 @@ drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs) if (IS_ERR(priv->test_bridge)) return ERR_CAST(priv->test_bridge); + priv->test_bridge->data = priv; + drm = &priv->drm; priv->plane = drm_kunit_helper_create_primary_plane(test, drm, NULL, @@ -422,11 +439,83 @@ static struct kunit_suite drm_bridge_helper_reset_crtc_test_suite = { .test_cases = drm_bridge_helper_reset_crtc_tests, }; +static int drm_test_bridge_alloc_init(struct kunit *test) +{ + struct drm_bridge_init_priv *priv; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); + + priv->dev = kunit_device_register(test, "drm-bridge-dev"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + test->priv = priv; + + priv->test_bridge = devm_drm_bridge_alloc(priv->dev, struct drm_bridge_priv, bridge, + &drm_test_bridge_atomic_funcs); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->test_bridge); + + priv->test_bridge->data = priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + return 0; +} + +/* + * Test that a bridge is freed when the device is destroyed in lack of + * other drm_bridge_get/put() operations. + */ +static void drm_test_drm_bridge_alloc_basic(struct kunit *test) +{ + struct drm_bridge_init_priv *priv = test->priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + kunit_device_unregister(test, priv->dev); + KUNIT_EXPECT_TRUE(test, priv->destroyed); +} + +/* + * Test that a bridge is not freed when the device is destroyed when there + * is still a reference to it, and freed when that reference is put. + */ +static void drm_test_drm_bridge_alloc_get_put(struct kunit *test) +{ + struct drm_bridge_init_priv *priv = test->priv; + + KUNIT_ASSERT_FALSE(test, priv->destroyed); + + drm_bridge_get(&priv->test_bridge->bridge); + KUNIT_EXPECT_FALSE(test, priv->destroyed); + + kunit_device_unregister(test, priv->dev); + KUNIT_EXPECT_FALSE(test, priv->destroyed); + + drm_bridge_put(&priv->test_bridge->bridge); + KUNIT_EXPECT_TRUE(test, priv->destroyed); +} + +static struct kunit_case drm_bridge_alloc_tests[] = { + KUNIT_CASE(drm_test_drm_bridge_alloc_basic), + KUNIT_CASE(drm_test_drm_bridge_alloc_get_put), + { } +}; + +static struct kunit_suite drm_bridge_alloc_test_suite = { + .name = "drm_bridge_alloc", + .init = drm_test_bridge_alloc_init, + .test_cases = drm_bridge_alloc_tests, +}; + kunit_test_suites( &drm_bridge_get_current_state_test_suite, &drm_bridge_helper_reset_crtc_test_suite, + &drm_bridge_alloc_test_suite, ); MODULE_AUTHOR("Maxime Ripard <mrip...@kernel.org>"); +MODULE_AUTHOR("Luca Ceresoli <luca.ceres...@bootlin.com>"); + MODULE_DESCRIPTION("Kunit test for drm_bridge functions"); MODULE_LICENSE("GPL"); -- 2.49.0