xref: /linux/drivers/gpu/drm/ttm/tests/ttm_resource_test.c (revision 3f1c07fc21c68bd3bd2df9d2c9441f6485e934d9)
1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 #include <drm/ttm/ttm_resource.h>
6 
7 #include "ttm_kunit_helpers.h"
8 
9 #define RES_SIZE		SZ_4K
10 #define TTM_PRIV_DUMMY_REG	(TTM_NUM_MEM_TYPES - 1)
11 
12 struct ttm_resource_test_case {
13 	const char *description;
14 	u32 mem_type;
15 	u32 flags;
16 };
17 
18 struct ttm_resource_test_priv {
19 	struct ttm_test_devices *devs;
20 	struct ttm_buffer_object *bo;
21 	struct ttm_place *place;
22 };
23 
24 static const struct ttm_resource_manager_func ttm_resource_manager_mock_funcs = { };
25 
ttm_resource_test_init(struct kunit * test)26 static int ttm_resource_test_init(struct kunit *test)
27 {
28 	struct ttm_resource_test_priv *priv;
29 
30 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
31 	KUNIT_ASSERT_NOT_NULL(test, priv);
32 
33 	priv->devs = ttm_test_devices_all(test);
34 	KUNIT_ASSERT_NOT_NULL(test, priv->devs);
35 
36 	test->priv = priv;
37 
38 	return 0;
39 }
40 
ttm_resource_test_fini(struct kunit * test)41 static void ttm_resource_test_fini(struct kunit *test)
42 {
43 	struct ttm_resource_test_priv *priv = test->priv;
44 
45 	ttm_test_devices_put(test, priv->devs);
46 }
47 
ttm_init_test_mocks(struct kunit * test,struct ttm_resource_test_priv * priv,u32 mem_type,u32 flags)48 static void ttm_init_test_mocks(struct kunit *test,
49 				struct ttm_resource_test_priv *priv,
50 				u32 mem_type, u32 flags)
51 {
52 	size_t size = RES_SIZE;
53 
54 	/* Make sure we have what we need for a good BO mock */
55 	KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev);
56 
57 	priv->bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
58 	priv->place = ttm_place_kunit_init(test, mem_type, flags);
59 }
60 
ttm_init_test_manager(struct kunit * test,struct ttm_resource_test_priv * priv,u32 mem_type)61 static void ttm_init_test_manager(struct kunit *test,
62 				  struct ttm_resource_test_priv *priv,
63 				  u32 mem_type)
64 {
65 	struct ttm_device *ttm_dev = priv->devs->ttm_dev;
66 	struct ttm_resource_manager *man;
67 	size_t size = SZ_16K;
68 
69 	man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
70 	KUNIT_ASSERT_NOT_NULL(test, man);
71 
72 	man->use_tt = false;
73 	man->func = &ttm_resource_manager_mock_funcs;
74 
75 	ttm_resource_manager_init(man, ttm_dev, size);
76 	ttm_set_driver_manager(ttm_dev, mem_type, man);
77 	ttm_resource_manager_set_used(man, true);
78 }
79 
80 static const struct ttm_resource_test_case ttm_resource_cases[] = {
81 	{
82 		.description = "Init resource in TTM_PL_SYSTEM",
83 		.mem_type = TTM_PL_SYSTEM,
84 	},
85 	{
86 		.description = "Init resource in TTM_PL_VRAM",
87 		.mem_type = TTM_PL_VRAM,
88 	},
89 	{
90 		.description = "Init resource in a private placement",
91 		.mem_type = TTM_PRIV_DUMMY_REG,
92 	},
93 	{
94 		.description = "Init resource in TTM_PL_SYSTEM, set placement flags",
95 		.mem_type = TTM_PL_SYSTEM,
96 		.flags = TTM_PL_FLAG_TOPDOWN,
97 	},
98 };
99 
ttm_resource_case_desc(const struct ttm_resource_test_case * t,char * desc)100 static void ttm_resource_case_desc(const struct ttm_resource_test_case *t, char *desc)
101 {
102 	strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
103 }
104 
105 KUNIT_ARRAY_PARAM(ttm_resource, ttm_resource_cases, ttm_resource_case_desc);
106 
ttm_resource_init_basic(struct kunit * test)107 static void ttm_resource_init_basic(struct kunit *test)
108 {
109 	const struct ttm_resource_test_case *params = test->param_value;
110 	struct ttm_resource_test_priv *priv = test->priv;
111 	struct ttm_resource *res;
112 	struct ttm_buffer_object *bo;
113 	struct ttm_place *place;
114 	struct ttm_resource_manager *man;
115 	u64 expected_usage;
116 
117 	ttm_init_test_mocks(test, priv, params->mem_type, params->flags);
118 	bo = priv->bo;
119 	place = priv->place;
120 
121 	if (params->mem_type > TTM_PL_SYSTEM)
122 		ttm_init_test_manager(test, priv, params->mem_type);
123 
124 	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
125 	KUNIT_ASSERT_NOT_NULL(test, res);
126 
127 	man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
128 	expected_usage = man->usage + RES_SIZE;
129 
130 	KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
131 
132 	ttm_resource_init(bo, place, res);
133 
134 	KUNIT_ASSERT_EQ(test, res->start, 0);
135 	KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
136 	KUNIT_ASSERT_EQ(test, res->mem_type, place->mem_type);
137 	KUNIT_ASSERT_EQ(test, res->placement, place->flags);
138 	KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
139 
140 	KUNIT_ASSERT_NULL(test, res->bus.addr);
141 	KUNIT_ASSERT_EQ(test, res->bus.offset, 0);
142 	KUNIT_ASSERT_FALSE(test, res->bus.is_iomem);
143 	KUNIT_ASSERT_EQ(test, res->bus.caching, ttm_cached);
144 	KUNIT_ASSERT_EQ(test, man->usage, expected_usage);
145 
146 	KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
147 
148 	ttm_resource_fini(man, res);
149 }
150 
ttm_resource_init_pinned(struct kunit * test)151 static void ttm_resource_init_pinned(struct kunit *test)
152 {
153 	struct ttm_resource_test_priv *priv = test->priv;
154 	struct ttm_resource *res;
155 	struct ttm_buffer_object *bo;
156 	struct ttm_place *place;
157 	struct ttm_resource_manager *man;
158 
159 	ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
160 	bo = priv->bo;
161 	place = priv->place;
162 
163 	man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
164 
165 	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
166 	KUNIT_ASSERT_NOT_NULL(test, res);
167 	KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->unevictable));
168 
169 	dma_resv_lock(bo->base.resv, NULL);
170 	ttm_bo_pin(bo);
171 	ttm_resource_init(bo, place, res);
172 	KUNIT_ASSERT_TRUE(test, list_is_singular(&bo->bdev->unevictable));
173 
174 	ttm_bo_unpin(bo);
175 	ttm_resource_fini(man, res);
176 	dma_resv_unlock(bo->base.resv);
177 
178 	KUNIT_ASSERT_TRUE(test, list_empty(&bo->bdev->unevictable));
179 }
180 
ttm_resource_fini_basic(struct kunit * test)181 static void ttm_resource_fini_basic(struct kunit *test)
182 {
183 	struct ttm_resource_test_priv *priv = test->priv;
184 	struct ttm_resource *res;
185 	struct ttm_buffer_object *bo;
186 	struct ttm_place *place;
187 	struct ttm_resource_manager *man;
188 
189 	ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, 0);
190 	bo = priv->bo;
191 	place = priv->place;
192 
193 	man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
194 
195 	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
196 	KUNIT_ASSERT_NOT_NULL(test, res);
197 
198 	ttm_resource_init(bo, place, res);
199 	ttm_resource_fini(man, res);
200 
201 	KUNIT_ASSERT_TRUE(test, list_empty(&res->lru.link));
202 	KUNIT_ASSERT_EQ(test, man->usage, 0);
203 }
204 
ttm_resource_manager_init_basic(struct kunit * test)205 static void ttm_resource_manager_init_basic(struct kunit *test)
206 {
207 	struct ttm_resource_test_priv *priv = test->priv;
208 	struct ttm_resource_manager *man;
209 	size_t size = SZ_16K;
210 	int i;
211 
212 	man = kunit_kzalloc(test, sizeof(*man), GFP_KERNEL);
213 	KUNIT_ASSERT_NOT_NULL(test, man);
214 
215 	ttm_resource_manager_init(man, priv->devs->ttm_dev, size);
216 
217 	KUNIT_ASSERT_PTR_EQ(test, man->bdev, priv->devs->ttm_dev);
218 	KUNIT_ASSERT_EQ(test, man->size, size);
219 	KUNIT_ASSERT_EQ(test, man->usage, 0);
220 	for (i = 0; i < TTM_NUM_MOVE_FENCES; i++)
221 		KUNIT_ASSERT_NULL(test, man->eviction_fences[i]);
222 
223 	for (int i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
224 		KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[i]));
225 }
226 
ttm_resource_manager_usage_basic(struct kunit * test)227 static void ttm_resource_manager_usage_basic(struct kunit *test)
228 {
229 	struct ttm_resource_test_priv *priv = test->priv;
230 	struct ttm_resource *res;
231 	struct ttm_buffer_object *bo;
232 	struct ttm_place *place;
233 	struct ttm_resource_manager *man;
234 	u64 actual_usage;
235 
236 	ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
237 	bo = priv->bo;
238 	place = priv->place;
239 
240 	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
241 	KUNIT_ASSERT_NOT_NULL(test, res);
242 
243 	man = ttm_manager_type(priv->devs->ttm_dev, place->mem_type);
244 
245 	ttm_resource_init(bo, place, res);
246 	actual_usage = ttm_resource_manager_usage(man);
247 
248 	KUNIT_ASSERT_EQ(test, actual_usage, RES_SIZE);
249 
250 	ttm_resource_fini(man, res);
251 }
252 
ttm_resource_manager_set_used_basic(struct kunit * test)253 static void ttm_resource_manager_set_used_basic(struct kunit *test)
254 {
255 	struct ttm_resource_test_priv *priv = test->priv;
256 	struct ttm_resource_manager *man;
257 
258 	man = ttm_manager_type(priv->devs->ttm_dev, TTM_PL_SYSTEM);
259 	KUNIT_ASSERT_TRUE(test, man->use_type);
260 
261 	ttm_resource_manager_set_used(man, false);
262 	KUNIT_ASSERT_FALSE(test, man->use_type);
263 }
264 
ttm_sys_man_alloc_basic(struct kunit * test)265 static void ttm_sys_man_alloc_basic(struct kunit *test)
266 {
267 	struct ttm_resource_test_priv *priv = test->priv;
268 	struct ttm_resource_manager *man;
269 	struct ttm_buffer_object *bo;
270 	struct ttm_place *place;
271 	struct ttm_resource *res;
272 	u32 mem_type = TTM_PL_SYSTEM;
273 	int ret;
274 
275 	ttm_init_test_mocks(test, priv, mem_type, 0);
276 	bo = priv->bo;
277 	place = priv->place;
278 
279 	man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
280 	ret = man->func->alloc(man, bo, place, &res);
281 
282 	KUNIT_ASSERT_EQ(test, ret, 0);
283 	KUNIT_ASSERT_EQ(test, res->size, RES_SIZE);
284 	KUNIT_ASSERT_EQ(test, res->mem_type, mem_type);
285 	KUNIT_ASSERT_PTR_EQ(test, res->bo, bo);
286 
287 	ttm_resource_fini(man, res);
288 }
289 
ttm_sys_man_free_basic(struct kunit * test)290 static void ttm_sys_man_free_basic(struct kunit *test)
291 {
292 	struct ttm_resource_test_priv *priv = test->priv;
293 	struct ttm_resource_manager *man;
294 	struct ttm_buffer_object *bo;
295 	struct ttm_place *place;
296 	struct ttm_resource *res;
297 	u32 mem_type = TTM_PL_SYSTEM;
298 
299 	ttm_init_test_mocks(test, priv, mem_type, 0);
300 	bo = priv->bo;
301 	place = priv->place;
302 
303 	res = kunit_kzalloc(test, sizeof(*res), GFP_KERNEL);
304 	KUNIT_ASSERT_NOT_NULL(test, res);
305 
306 	ttm_resource_alloc(bo, place, &res, NULL);
307 
308 	man = ttm_manager_type(priv->devs->ttm_dev, mem_type);
309 	man->func->free(man, res);
310 
311 	KUNIT_ASSERT_TRUE(test, list_empty(&man->lru[bo->priority]));
312 	KUNIT_ASSERT_EQ(test, man->usage, 0);
313 }
314 
315 static struct kunit_case ttm_resource_test_cases[] = {
316 	KUNIT_CASE_PARAM(ttm_resource_init_basic, ttm_resource_gen_params),
317 	KUNIT_CASE(ttm_resource_init_pinned),
318 	KUNIT_CASE(ttm_resource_fini_basic),
319 	KUNIT_CASE(ttm_resource_manager_init_basic),
320 	KUNIT_CASE(ttm_resource_manager_usage_basic),
321 	KUNIT_CASE(ttm_resource_manager_set_used_basic),
322 	KUNIT_CASE(ttm_sys_man_alloc_basic),
323 	KUNIT_CASE(ttm_sys_man_free_basic),
324 	{}
325 };
326 
327 static struct kunit_suite ttm_resource_test_suite = {
328 	.name = "ttm_resource",
329 	.init = ttm_resource_test_init,
330 	.exit = ttm_resource_test_fini,
331 	.test_cases = ttm_resource_test_cases,
332 };
333 
334 kunit_test_suites(&ttm_resource_test_suite);
335 
336 MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs");
337 MODULE_LICENSE("GPL and additional rights");
338