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