1*9710631cSChristian König // SPDX-License-Identifier: MIT 2*9710631cSChristian König /* 3*9710631cSChristian König * Copyright 2022 Advanced Micro Devices, Inc. 4*9710631cSChristian König */ 5*9710631cSChristian König 6*9710631cSChristian König #define pr_fmt(fmt) "drm_exec: " fmt 7*9710631cSChristian König 8*9710631cSChristian König #include <kunit/test.h> 9*9710631cSChristian König 10*9710631cSChristian König #include <linux/module.h> 11*9710631cSChristian König #include <linux/prime_numbers.h> 12*9710631cSChristian König 13*9710631cSChristian König #include <drm/drm_exec.h> 14*9710631cSChristian König #include <drm/drm_device.h> 15*9710631cSChristian König #include <drm/drm_gem.h> 16*9710631cSChristian König 17*9710631cSChristian König #include "../lib/drm_random.h" 18*9710631cSChristian König 19*9710631cSChristian König static struct drm_device dev; 20*9710631cSChristian König 21*9710631cSChristian König static void sanitycheck(struct kunit *test) 22*9710631cSChristian König { 23*9710631cSChristian König struct drm_exec exec; 24*9710631cSChristian König 25*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 26*9710631cSChristian König drm_exec_fini(&exec); 27*9710631cSChristian König KUNIT_SUCCEED(test); 28*9710631cSChristian König } 29*9710631cSChristian König 30*9710631cSChristian König static void test_lock(struct kunit *test) 31*9710631cSChristian König { 32*9710631cSChristian König struct drm_gem_object gobj = { }; 33*9710631cSChristian König struct drm_exec exec; 34*9710631cSChristian König int ret; 35*9710631cSChristian König 36*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj, PAGE_SIZE); 37*9710631cSChristian König 38*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 39*9710631cSChristian König drm_exec_until_all_locked(&exec) { 40*9710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 41*9710631cSChristian König drm_exec_retry_on_contention(&exec); 42*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 43*9710631cSChristian König if (ret) 44*9710631cSChristian König break; 45*9710631cSChristian König } 46*9710631cSChristian König drm_exec_fini(&exec); 47*9710631cSChristian König } 48*9710631cSChristian König 49*9710631cSChristian König static void test_lock_unlock(struct kunit *test) 50*9710631cSChristian König { 51*9710631cSChristian König struct drm_gem_object gobj = { }; 52*9710631cSChristian König struct drm_exec exec; 53*9710631cSChristian König int ret; 54*9710631cSChristian König 55*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj, PAGE_SIZE); 56*9710631cSChristian König 57*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 58*9710631cSChristian König drm_exec_until_all_locked(&exec) { 59*9710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 60*9710631cSChristian König drm_exec_retry_on_contention(&exec); 61*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 62*9710631cSChristian König if (ret) 63*9710631cSChristian König break; 64*9710631cSChristian König 65*9710631cSChristian König drm_exec_unlock_obj(&exec, &gobj); 66*9710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 67*9710631cSChristian König drm_exec_retry_on_contention(&exec); 68*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 69*9710631cSChristian König if (ret) 70*9710631cSChristian König break; 71*9710631cSChristian König } 72*9710631cSChristian König drm_exec_fini(&exec); 73*9710631cSChristian König } 74*9710631cSChristian König 75*9710631cSChristian König static void test_duplicates(struct kunit *test) 76*9710631cSChristian König { 77*9710631cSChristian König struct drm_gem_object gobj = { }; 78*9710631cSChristian König struct drm_exec exec; 79*9710631cSChristian König int ret; 80*9710631cSChristian König 81*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj, PAGE_SIZE); 82*9710631cSChristian König 83*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES); 84*9710631cSChristian König drm_exec_until_all_locked(&exec) { 85*9710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 86*9710631cSChristian König drm_exec_retry_on_contention(&exec); 87*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 88*9710631cSChristian König if (ret) 89*9710631cSChristian König break; 90*9710631cSChristian König 91*9710631cSChristian König ret = drm_exec_lock_obj(&exec, &gobj); 92*9710631cSChristian König drm_exec_retry_on_contention(&exec); 93*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 94*9710631cSChristian König if (ret) 95*9710631cSChristian König break; 96*9710631cSChristian König } 97*9710631cSChristian König drm_exec_unlock_obj(&exec, &gobj); 98*9710631cSChristian König drm_exec_fini(&exec); 99*9710631cSChristian König } 100*9710631cSChristian König 101*9710631cSChristian König 102*9710631cSChristian König 103*9710631cSChristian König static void test_prepare(struct kunit *test) 104*9710631cSChristian König { 105*9710631cSChristian König struct drm_gem_object gobj = { }; 106*9710631cSChristian König struct drm_exec exec; 107*9710631cSChristian König int ret; 108*9710631cSChristian König 109*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj, PAGE_SIZE); 110*9710631cSChristian König 111*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 112*9710631cSChristian König drm_exec_until_all_locked(&exec) { 113*9710631cSChristian König ret = drm_exec_prepare_obj(&exec, &gobj, 1); 114*9710631cSChristian König drm_exec_retry_on_contention(&exec); 115*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 116*9710631cSChristian König if (ret) 117*9710631cSChristian König break; 118*9710631cSChristian König } 119*9710631cSChristian König drm_exec_fini(&exec); 120*9710631cSChristian König } 121*9710631cSChristian König 122*9710631cSChristian König static void test_prepare_array(struct kunit *test) 123*9710631cSChristian König { 124*9710631cSChristian König struct drm_gem_object gobj1 = { }; 125*9710631cSChristian König struct drm_gem_object gobj2 = { }; 126*9710631cSChristian König struct drm_gem_object *array[] = { &gobj1, &gobj2 }; 127*9710631cSChristian König struct drm_exec exec; 128*9710631cSChristian König int ret; 129*9710631cSChristian König 130*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj1, PAGE_SIZE); 131*9710631cSChristian König drm_gem_private_object_init(&dev, &gobj2, PAGE_SIZE); 132*9710631cSChristian König 133*9710631cSChristian König drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 134*9710631cSChristian König drm_exec_until_all_locked(&exec) 135*9710631cSChristian König ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), 136*9710631cSChristian König 1); 137*9710631cSChristian König KUNIT_EXPECT_EQ(test, ret, 0); 138*9710631cSChristian König drm_exec_fini(&exec); 139*9710631cSChristian König } 140*9710631cSChristian König 141*9710631cSChristian König static struct kunit_case drm_exec_tests[] = { 142*9710631cSChristian König KUNIT_CASE(sanitycheck), 143*9710631cSChristian König KUNIT_CASE(test_lock), 144*9710631cSChristian König KUNIT_CASE(test_lock_unlock), 145*9710631cSChristian König KUNIT_CASE(test_duplicates), 146*9710631cSChristian König KUNIT_CASE(test_prepare), 147*9710631cSChristian König KUNIT_CASE(test_prepare_array), 148*9710631cSChristian König {} 149*9710631cSChristian König }; 150*9710631cSChristian König 151*9710631cSChristian König static struct kunit_suite drm_exec_test_suite = { 152*9710631cSChristian König .name = "drm_exec", 153*9710631cSChristian König .test_cases = drm_exec_tests, 154*9710631cSChristian König }; 155*9710631cSChristian König 156*9710631cSChristian König kunit_test_suite(drm_exec_test_suite); 157*9710631cSChristian König 158*9710631cSChristian König MODULE_AUTHOR("AMD"); 159*9710631cSChristian König MODULE_LICENSE("GPL and additional rights"); 160