1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2022 Advanced Micro Devices, Inc. 4 */ 5 6 #define pr_fmt(fmt) "drm_exec: " fmt 7 8 #include <kunit/test.h> 9 10 #include <linux/module.h> 11 #include <linux/prime_numbers.h> 12 13 #include <drm/drm_exec.h> 14 #include <drm/drm_device.h> 15 #include <drm/drm_drv.h> 16 #include <drm/drm_gem.h> 17 #include <drm/drm_kunit_helpers.h> 18 19 #include "../lib/drm_random.h" 20 21 struct drm_exec_priv { 22 struct device *dev; 23 struct drm_device *drm; 24 }; 25 26 static int drm_exec_test_init(struct kunit *test) 27 { 28 struct drm_exec_priv *priv; 29 30 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 31 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 32 33 test->priv = priv; 34 35 priv->dev = drm_kunit_helper_alloc_device(test); 36 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); 37 38 priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, sizeof(*priv->drm), 0, 39 DRIVER_MODESET); 40 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); 41 42 return 0; 43 } 44 45 static void sanitycheck(struct kunit *test) 46 { 47 struct drm_exec exec; 48 49 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 50 drm_exec_fini(&exec); 51 KUNIT_SUCCEED(test); 52 } 53 54 static void test_lock(struct kunit *test) 55 { 56 struct drm_exec_priv *priv = test->priv; 57 struct drm_gem_object gobj = { }; 58 struct drm_exec exec; 59 int ret; 60 61 drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 62 63 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 64 drm_exec_until_all_locked(&exec) { 65 ret = drm_exec_lock_obj(&exec, &gobj); 66 drm_exec_retry_on_contention(&exec); 67 KUNIT_EXPECT_EQ(test, ret, 0); 68 if (ret) 69 break; 70 } 71 drm_exec_fini(&exec); 72 } 73 74 static void test_lock_unlock(struct kunit *test) 75 { 76 struct drm_exec_priv *priv = test->priv; 77 struct drm_gem_object gobj = { }; 78 struct drm_exec exec; 79 int ret; 80 81 drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 82 83 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 84 drm_exec_until_all_locked(&exec) { 85 ret = drm_exec_lock_obj(&exec, &gobj); 86 drm_exec_retry_on_contention(&exec); 87 KUNIT_EXPECT_EQ(test, ret, 0); 88 if (ret) 89 break; 90 91 drm_exec_unlock_obj(&exec, &gobj); 92 ret = drm_exec_lock_obj(&exec, &gobj); 93 drm_exec_retry_on_contention(&exec); 94 KUNIT_EXPECT_EQ(test, ret, 0); 95 if (ret) 96 break; 97 } 98 drm_exec_fini(&exec); 99 } 100 101 static void test_duplicates(struct kunit *test) 102 { 103 struct drm_exec_priv *priv = test->priv; 104 struct drm_gem_object gobj = { }; 105 struct drm_exec exec; 106 int ret; 107 108 drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 109 110 drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES); 111 drm_exec_until_all_locked(&exec) { 112 ret = drm_exec_lock_obj(&exec, &gobj); 113 drm_exec_retry_on_contention(&exec); 114 KUNIT_EXPECT_EQ(test, ret, 0); 115 if (ret) 116 break; 117 118 ret = drm_exec_lock_obj(&exec, &gobj); 119 drm_exec_retry_on_contention(&exec); 120 KUNIT_EXPECT_EQ(test, ret, 0); 121 if (ret) 122 break; 123 } 124 drm_exec_unlock_obj(&exec, &gobj); 125 drm_exec_fini(&exec); 126 } 127 128 static void test_prepare(struct kunit *test) 129 { 130 struct drm_exec_priv *priv = test->priv; 131 struct drm_gem_object gobj = { }; 132 struct drm_exec exec; 133 int ret; 134 135 drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 136 137 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 138 drm_exec_until_all_locked(&exec) { 139 ret = drm_exec_prepare_obj(&exec, &gobj, 1); 140 drm_exec_retry_on_contention(&exec); 141 KUNIT_EXPECT_EQ(test, ret, 0); 142 if (ret) 143 break; 144 } 145 drm_exec_fini(&exec); 146 147 drm_gem_private_object_fini(&gobj); 148 } 149 150 static void test_prepare_array(struct kunit *test) 151 { 152 struct drm_exec_priv *priv = test->priv; 153 struct drm_gem_object gobj1 = { }; 154 struct drm_gem_object gobj2 = { }; 155 struct drm_gem_object *array[] = { &gobj1, &gobj2 }; 156 struct drm_exec exec; 157 int ret; 158 159 drm_gem_private_object_init(priv->drm, &gobj1, PAGE_SIZE); 160 drm_gem_private_object_init(priv->drm, &gobj2, PAGE_SIZE); 161 162 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 163 drm_exec_until_all_locked(&exec) 164 ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), 165 1); 166 KUNIT_EXPECT_EQ(test, ret, 0); 167 drm_exec_fini(&exec); 168 169 drm_gem_private_object_fini(&gobj1); 170 drm_gem_private_object_fini(&gobj2); 171 } 172 173 static void test_multiple_loops(struct kunit *test) 174 { 175 struct drm_exec exec; 176 177 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 178 drm_exec_until_all_locked(&exec) 179 { 180 break; 181 } 182 drm_exec_fini(&exec); 183 184 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 185 drm_exec_until_all_locked(&exec) 186 { 187 break; 188 } 189 drm_exec_fini(&exec); 190 KUNIT_SUCCEED(test); 191 } 192 193 static struct kunit_case drm_exec_tests[] = { 194 KUNIT_CASE(sanitycheck), 195 KUNIT_CASE(test_lock), 196 KUNIT_CASE(test_lock_unlock), 197 KUNIT_CASE(test_duplicates), 198 KUNIT_CASE(test_prepare), 199 KUNIT_CASE(test_prepare_array), 200 KUNIT_CASE(test_multiple_loops), 201 {} 202 }; 203 204 static struct kunit_suite drm_exec_test_suite = { 205 .name = "drm_exec", 206 .init = drm_exec_test_init, 207 .test_cases = drm_exec_tests, 208 }; 209 210 kunit_test_suite(drm_exec_test_suite); 211 212 MODULE_AUTHOR("AMD"); 213 MODULE_LICENSE("GPL and additional rights"); 214