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 499710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 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 639710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 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 839710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 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 1109710631cSChristian König drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES); 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 1299710631cSChristian König 1309710631cSChristian König static void test_prepare(struct kunit *test) 1319710631cSChristian König { 1320f249678SArthur Grillo struct drm_exec_priv *priv = test->priv; 1339710631cSChristian König struct drm_gem_object gobj = { }; 1349710631cSChristian König struct drm_exec exec; 1359710631cSChristian König int ret; 1369710631cSChristian König 1370f249678SArthur Grillo drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 1389710631cSChristian König 1399710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 1409710631cSChristian König drm_exec_until_all_locked(&exec) { 1419710631cSChristian König ret = drm_exec_prepare_obj(&exec, &gobj, 1); 1429710631cSChristian König drm_exec_retry_on_contention(&exec); 1439710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 1449710631cSChristian König if (ret) 1459710631cSChristian König break; 1469710631cSChristian König } 1479710631cSChristian König drm_exec_fini(&exec); 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 1629710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 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); 1689710631cSChristian König } 1699710631cSChristian König 170*991eb531SChristian König static void test_multiple_loops(struct kunit *test) 171*991eb531SChristian König { 172*991eb531SChristian König struct drm_exec exec; 173*991eb531SChristian König 174*991eb531SChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 175*991eb531SChristian König drm_exec_until_all_locked(&exec) 176*991eb531SChristian König { 177*991eb531SChristian König break; 178*991eb531SChristian König } 179*991eb531SChristian König drm_exec_fini(&exec); 180*991eb531SChristian König 181*991eb531SChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 182*991eb531SChristian König drm_exec_until_all_locked(&exec) 183*991eb531SChristian König { 184*991eb531SChristian König break; 185*991eb531SChristian König } 186*991eb531SChristian König drm_exec_fini(&exec); 187*991eb531SChristian König KUNIT_SUCCEED(test); 188*991eb531SChristian König } 189*991eb531SChristian König 1909710631cSChristian König static struct kunit_case drm_exec_tests[] = { 1919710631cSChristian König KUNIT_CASE(sanitycheck), 1929710631cSChristian König KUNIT_CASE(test_lock), 1939710631cSChristian König KUNIT_CASE(test_lock_unlock), 1949710631cSChristian König KUNIT_CASE(test_duplicates), 1959710631cSChristian König KUNIT_CASE(test_prepare), 1969710631cSChristian König KUNIT_CASE(test_prepare_array), 197*991eb531SChristian König KUNIT_CASE(test_multiple_loops), 1989710631cSChristian König {} 1999710631cSChristian König }; 2009710631cSChristian König 2019710631cSChristian König static struct kunit_suite drm_exec_test_suite = { 2029710631cSChristian König .name = "drm_exec", 2030f249678SArthur Grillo .init = drm_exec_test_init, 2049710631cSChristian König .test_cases = drm_exec_tests, 2059710631cSChristian König }; 2069710631cSChristian König 2079710631cSChristian König kunit_test_suite(drm_exec_test_suite); 2089710631cSChristian König 2099710631cSChristian König MODULE_AUTHOR("AMD"); 2109710631cSChristian König MODULE_LICENSE("GPL and additional rights"); 211