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, 0); 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, 0); 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, 0); 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, 0); 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, 0); 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[] = { 156 (gobj1 = kunit_kzalloc(test, sizeof(*gobj1), GFP_KERNEL)), 157 (gobj2 = kunit_kzalloc(test, sizeof(*gobj2), GFP_KERNEL)), 158 }; 159 struct drm_exec exec; 160 int ret; 161 162 if (!gobj1 || !gobj2) { 163 KUNIT_FAIL(test, "Failed to allocate GEM objects.\n"); 164 return; 165 } 166 167 drm_gem_private_object_init(priv->drm, gobj1, PAGE_SIZE); 168 drm_gem_private_object_init(priv->drm, gobj2, PAGE_SIZE); 169 170 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 171 drm_exec_until_all_locked(&exec) 172 ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), 173 1); 174 KUNIT_EXPECT_EQ(test, ret, 0); 175 drm_exec_fini(&exec); 176 177 drm_gem_private_object_fini(gobj1); 178 drm_gem_private_object_fini(gobj2); 179 } 180 181 static void test_multiple_loops(struct kunit *test) 182 { 183 struct drm_exec exec; 184 185 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 186 drm_exec_until_all_locked(&exec) 187 { 188 break; 189 } 190 drm_exec_fini(&exec); 191 192 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); 193 drm_exec_until_all_locked(&exec) 194 { 195 break; 196 } 197 drm_exec_fini(&exec); 198 KUNIT_SUCCEED(test); 199 } 200 201 static struct kunit_case drm_exec_tests[] = { 202 KUNIT_CASE(sanitycheck), 203 KUNIT_CASE(test_lock), 204 KUNIT_CASE(test_lock_unlock), 205 KUNIT_CASE(test_duplicates), 206 KUNIT_CASE(test_prepare), 207 KUNIT_CASE(test_prepare_array), 208 KUNIT_CASE(test_multiple_loops), 209 {} 210 }; 211 212 static struct kunit_suite drm_exec_test_suite = { 213 .name = "drm_exec", 214 .init = drm_exec_test_init, 215 .test_cases = drm_exec_tests, 216 }; 217 218 kunit_test_suite(drm_exec_test_suite); 219 220 MODULE_AUTHOR("AMD"); 221 MODULE_DESCRIPTION("Kunit test for drm_exec functions"); 222 MODULE_LICENSE("GPL and additional rights"); 223