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 129 130 static void test_prepare(struct kunit *test) 131 { 132 struct drm_exec_priv *priv = test->priv; 133 struct drm_gem_object gobj = { }; 134 struct drm_exec exec; 135 int ret; 136 137 drm_gem_private_object_init(priv->drm, &gobj, PAGE_SIZE); 138 139 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); 140 drm_exec_until_all_locked(&exec) { 141 ret = drm_exec_prepare_obj(&exec, &gobj, 1); 142 drm_exec_retry_on_contention(&exec); 143 KUNIT_EXPECT_EQ(test, ret, 0); 144 if (ret) 145 break; 146 } 147 drm_exec_fini(&exec); 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 170 static struct kunit_case drm_exec_tests[] = { 171 KUNIT_CASE(sanitycheck), 172 KUNIT_CASE(test_lock), 173 KUNIT_CASE(test_lock_unlock), 174 KUNIT_CASE(test_duplicates), 175 KUNIT_CASE(test_prepare), 176 KUNIT_CASE(test_prepare_array), 177 {} 178 }; 179 180 static struct kunit_suite drm_exec_test_suite = { 181 .name = "drm_exec", 182 .init = drm_exec_test_init, 183 .test_cases = drm_exec_tests, 184 }; 185 186 kunit_test_suite(drm_exec_test_suite); 187 188 MODULE_AUTHOR("AMD"); 189 MODULE_LICENSE("GPL and additional rights"); 190