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