19710631cSChristian König // SPDX-License-Identifier: MIT 29710631cSChristian König /* 39710631cSChristian König * Copyright 2022 Advanced Micro Devices, Inc. 49710631cSChristian König */ 59710631cSChristian König 69710631cSChristian König #define pr_fmt(fmt) "drm_exec: " fmt 79710631cSChristian König 89710631cSChristian König #include <kunit/test.h> 99710631cSChristian König 109710631cSChristian König #include <linux/module.h> 119710631cSChristian König #include <linux/prime_numbers.h> 129710631cSChristian König 139710631cSChristian König #include <drm/drm_exec.h> 149710631cSChristian König #include <drm/drm_device.h> 150f249678SArthur Grillo #include <drm/drm_drv.h> 169710631cSChristian König #include <drm/drm_gem.h> 170f249678SArthur Grillo #include <drm/drm_kunit_helpers.h> 189710631cSChristian König 199710631cSChristian König #include "../lib/drm_random.h" 209710631cSChristian König 210f249678SArthur Grillo struct drm_exec_priv { 220f249678SArthur Grillo struct device *dev; 230f249678SArthur Grillo struct drm_device *drm; 240f249678SArthur Grillo }; 250f249678SArthur Grillo 260f249678SArthur Grillo static int drm_exec_test_init(struct kunit *test) 270f249678SArthur Grillo { 280f249678SArthur Grillo struct drm_exec_priv *priv; 290f249678SArthur Grillo 300f249678SArthur Grillo priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 310f249678SArthur Grillo KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 320f249678SArthur Grillo 330f249678SArthur Grillo test->priv = priv; 340f249678SArthur Grillo 350f249678SArthur Grillo priv->dev = drm_kunit_helper_alloc_device(test); 360f249678SArthur Grillo KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); 370f249678SArthur Grillo 380f249678SArthur Grillo priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, sizeof(*priv->drm), 0, 390f249678SArthur Grillo DRIVER_MODESET); 400f249678SArthur Grillo KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); 410f249678SArthur Grillo 420f249678SArthur Grillo return 0; 430f249678SArthur Grillo } 449710631cSChristian König 459710631cSChristian König static void sanitycheck(struct kunit *test) 469710631cSChristian König { 479710631cSChristian König struct drm_exec exec; 489710631cSChristian König 49*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 509710631cSChristian König drm_exec_fini(&exec); 519710631cSChristian König KUNIT_SUCCEED(test); 529710631cSChristian König } 539710631cSChristian König 549710631cSChristian König static void test_lock(struct kunit *test) 559710631cSChristian König { 560f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 579710631cSChristian König struct drm_gem_object gobj = { }; 589710631cSChristian König struct drm_exec exec; 599710631cSChristian König int ret; 609710631cSChristian König 610f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 629710631cSChristian König 63*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 649710631cSChristian König drm_exec_until_all_locked(&exec) { 659710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 669710631cSChristian König drm_exec_retry_on_contention(&exec); 679710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 689710631cSChristian König if (ret) 699710631cSChristian König break; 709710631cSChristian König } 719710631cSChristian König drm_exec_fini(&exec); 729710631cSChristian König } 739710631cSChristian König 749710631cSChristian König static void test_lock_unlock(struct kunit *test) 759710631cSChristian König { 760f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 779710631cSChristian König struct drm_gem_object gobj = { }; 789710631cSChristian König struct drm_exec exec; 799710631cSChristian König int ret; 809710631cSChristian König 810f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 829710631cSChristian König 83*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 849710631cSChristian König drm_exec_until_all_locked(&exec) { 859710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 869710631cSChristian König drm_exec_retry_on_contention(&exec); 879710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 889710631cSChristian König if (ret) 899710631cSChristian König break; 909710631cSChristian König 919710631cSChristian König drm_exec_unlock_obj(&exec, &gobj); 929710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 939710631cSChristian König drm_exec_retry_on_contention(&exec); 949710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 959710631cSChristian König if (ret) 969710631cSChristian König break; 979710631cSChristian König } 989710631cSChristian König drm_exec_fini(&exec); 999710631cSChristian König } 1009710631cSChristian König 1019710631cSChristian König static void test_duplicates(struct kunit *test) 1029710631cSChristian König { 1030f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 1049710631cSChristian König struct drm_gem_object gobj = { }; 1059710631cSChristian König struct drm_exec exec; 1069710631cSChristian König int ret; 1079710631cSChristian König 1080f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 1099710631cSChristian König 110*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0); 1119710631cSChristian König drm_exec_until_all_locked(&exec) { 1129710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 1139710631cSChristian König drm_exec_retry_on_contention(&exec); 1149710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 1159710631cSChristian König if (ret) 1169710631cSChristian König break; 1179710631cSChristian König 1189710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 1199710631cSChristian König drm_exec_retry_on_contention(&exec); 1209710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 1219710631cSChristian König if (ret) 1229710631cSChristian König break; 1239710631cSChristian König } 1249710631cSChristian König drm_exec_unlock_obj(&exec, &gobj); 1259710631cSChristian König drm_exec_fini(&exec); 1269710631cSChristian König } 1279710631cSChristian König 1289710631cSChristian König static void test_prepare(struct kunit *test) 1299710631cSChristian König { 1300f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 1319710631cSChristian König struct drm_gem_object gobj = { }; 1329710631cSChristian König struct drm_exec exec; 1339710631cSChristian König int ret; 1349710631cSChristian König 1350f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 1369710631cSChristian König 137*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 1389710631cSChristian König drm_exec_until_all_locked(&exec) { 1399710631cSChristian König ret = drm_exec_prepare_obj(&exec, &gobj, 1); 1409710631cSChristian König drm_exec_retry_on_contention(&exec); 1419710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 1429710631cSChristian König if (ret) 1439710631cSChristian König break; 1449710631cSChristian König } 1459710631cSChristian König drm_exec_fini(&exec); 146806fd6d0SDanilo Krummrich 147806fd6d0SDanilo Krummrich drm_gem_private_object_fini(&gobj); 1489710631cSChristian König } 1499710631cSChristian König 1509710631cSChristian König static void test_prepare_array(struct kunit *test) 1519710631cSChristian König { 1520f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 1539710631cSChristian König struct drm_gem_object gobj1 = { }; 1549710631cSChristian König struct drm_gem_object gobj2 = { }; 1559710631cSChristian König struct drm_gem_object *array[] = { &gobj1, &gobj2 }; 1569710631cSChristian König struct drm_exec exec; 1579710631cSChristian König int ret; 1589710631cSChristian König 1590f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj1, PAGE_SIZE); 1600f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj2, PAGE_SIZE); 1619710631cSChristian König 162*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 1639710631cSChristian König drm_exec_until_all_locked(&exec) 1649710631cSChristian König ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), 1659710631cSChristian König 1); 1669710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 1679710631cSChristian König drm_exec_fini(&exec); 168806fd6d0SDanilo Krummrich 169806fd6d0SDanilo Krummrich drm_gem_private_object_fini(&gobj1); 170806fd6d0SDanilo Krummrich drm_gem_private_object_fini(&gobj2); 1719710631cSChristian König } 1729710631cSChristian König 173991eb531SChristian König static void test_multiple_loops(struct kunit *test) 174991eb531SChristian König { 175991eb531SChristian König struct drm_exec exec; 176991eb531SChristian König 177*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 178991eb531SChristian König drm_exec_until_all_locked(&exec) 179991eb531SChristian König { 180991eb531SChristian König break; 181991eb531SChristian König } 182991eb531SChristian König drm_exec_fini(&exec); 183991eb531SChristian König 184*05d24935SRob Clark drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 185991eb531SChristian König drm_exec_until_all_locked(&exec) 186991eb531SChristian König { 187991eb531SChristian König break; 188991eb531SChristian König } 189991eb531SChristian König drm_exec_fini(&exec); 190991eb531SChristian König KUNIT_SUCCEED(test); 191991eb531SChristian König } 192991eb531SChristian König 1939710631cSChristian König static struct kunit_case drm_exec_tests[] = { 1949710631cSChristian König KUNIT_CASE(sanitycheck), 1959710631cSChristian König KUNIT_CASE(test_lock), 1969710631cSChristian König KUNIT_CASE(test_lock_unlock), 1979710631cSChristian König KUNIT_CASE(test_duplicates), 1989710631cSChristian König KUNIT_CASE(test_prepare), 1999710631cSChristian König KUNIT_CASE(test_prepare_array), 200991eb531SChristian König KUNIT_CASE(test_multiple_loops), 2019710631cSChristian König {} 2029710631cSChristian König }; 2039710631cSChristian König 2049710631cSChristian König static struct kunit_suite drm_exec_test_suite = { 2059710631cSChristian König .name = "drm_exec", 2060f249678SArthur Grillo .init = drm_exec_test_init, 2079710631cSChristian König .test_cases = drm_exec_tests, 2089710631cSChristian König }; 2099710631cSChristian König 2109710631cSChristian König kunit_test_suite(drm_exec_test_suite); 2119710631cSChristian König 2129710631cSChristian König MODULE_AUTHOR("AMD"); 2139710631cSChristian König MODULE_LICENSE("GPL and additional rights"); 214