xref: /linux/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 #include <linux/delay.h>
6 #include <linux/kthread.h>
7 
8 #include <drm/ttm/ttm_resource.h>
9 #include <drm/ttm/ttm_placement.h>
10 #include <drm/ttm/ttm_tt.h>
11 
12 #include "ttm_kunit_helpers.h"
13 #include "ttm_mock_manager.h"
14 
15 #define BO_SIZE		SZ_4K
16 #define MANAGER_SIZE	SZ_1M
17 
18 static struct spinlock fence_lock;
19 
20 struct ttm_bo_validate_test_case {
21 	const char *description;
22 	enum ttm_bo_type bo_type;
23 	u32 mem_type;
24 	bool with_ttm;
25 	bool no_gpu_wait;
26 };
27 
ttm_placement_kunit_init(struct kunit * test,struct ttm_place * places,unsigned int num_places)28 static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test,
29 						      struct ttm_place *places,
30 						      unsigned int num_places)
31 {
32 	struct ttm_placement *placement;
33 
34 	placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
35 	KUNIT_ASSERT_NOT_NULL(test, placement);
36 
37 	placement->num_placement = num_places;
38 	placement->placement = places;
39 
40 	return placement;
41 }
42 
fence_name(struct dma_fence * f)43 static const char *fence_name(struct dma_fence *f)
44 {
45 	return "ttm-bo-validate-fence";
46 }
47 
48 static const struct dma_fence_ops fence_ops = {
49 	.get_driver_name = fence_name,
50 	.get_timeline_name = fence_name,
51 };
52 
alloc_mock_fence(struct kunit * test)53 static struct dma_fence *alloc_mock_fence(struct kunit *test)
54 {
55 	struct dma_fence *fence;
56 
57 	fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL);
58 	KUNIT_ASSERT_NOT_NULL(test, fence);
59 
60 	dma_fence_init(fence, &fence_ops, &fence_lock, 0, 0);
61 
62 	return fence;
63 }
64 
dma_resv_kunit_active_fence_init(struct kunit * test,struct dma_resv * resv,enum dma_resv_usage usage)65 static void dma_resv_kunit_active_fence_init(struct kunit *test,
66 					     struct dma_resv *resv,
67 					     enum dma_resv_usage usage)
68 {
69 	struct dma_fence *fence;
70 
71 	fence = alloc_mock_fence(test);
72 	dma_fence_enable_sw_signaling(fence);
73 
74 	dma_resv_lock(resv, NULL);
75 	dma_resv_reserve_fences(resv, 1);
76 	dma_resv_add_fence(resv, fence, usage);
77 	dma_resv_unlock(resv);
78 }
79 
ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case * t,char * desc)80 static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t,
81 				      char *desc)
82 {
83 	strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE);
84 }
85 
86 static const struct ttm_bo_validate_test_case ttm_bo_type_cases[] = {
87 	{
88 		.description = "Buffer object for userspace",
89 		.bo_type = ttm_bo_type_device,
90 	},
91 	{
92 		.description = "Kernel buffer object",
93 		.bo_type = ttm_bo_type_kernel,
94 	},
95 	{
96 		.description = "Shared buffer object",
97 		.bo_type = ttm_bo_type_sg,
98 	},
99 };
100 
101 KUNIT_ARRAY_PARAM(ttm_bo_types, ttm_bo_type_cases,
102 		  ttm_bo_validate_case_desc);
103 
ttm_bo_init_reserved_sys_man(struct kunit * test)104 static void ttm_bo_init_reserved_sys_man(struct kunit *test)
105 {
106 	const struct ttm_bo_validate_test_case *params = test->param_value;
107 	struct ttm_test_devices *priv = test->priv;
108 	enum ttm_bo_type bo_type = params->bo_type;
109 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
110 	struct ttm_operation_ctx ctx = { };
111 	struct ttm_placement *placement;
112 	struct ttm_buffer_object *bo;
113 	struct ttm_place *place;
114 	int err;
115 
116 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
117 	KUNIT_ASSERT_NOT_NULL(test, bo);
118 
119 	place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
120 	placement = ttm_placement_kunit_init(test, place, 1);
121 
122 	drm_gem_private_object_init(priv->drm, &bo->base, size);
123 
124 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
125 				   PAGE_SIZE, &ctx, NULL, NULL,
126 				   &dummy_ttm_bo_destroy);
127 	dma_resv_unlock(bo->base.resv);
128 
129 	KUNIT_EXPECT_EQ(test, err, 0);
130 	KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
131 	KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
132 	KUNIT_EXPECT_EQ(test, bo->type, bo_type);
133 	KUNIT_EXPECT_EQ(test, bo->page_alignment, PAGE_SIZE);
134 	KUNIT_EXPECT_PTR_EQ(test, bo->destroy, &dummy_ttm_bo_destroy);
135 	KUNIT_EXPECT_EQ(test, bo->pin_count, 0);
136 	KUNIT_EXPECT_NULL(test, bo->bulk_move);
137 	KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
138 	KUNIT_EXPECT_FALSE(test, ttm_tt_is_populated(bo->ttm));
139 	KUNIT_EXPECT_NOT_NULL(test, (void *)bo->base.resv->fences);
140 	KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
141 
142 	if (bo_type != ttm_bo_type_kernel)
143 		KUNIT_EXPECT_TRUE(test,
144 				  drm_mm_node_allocated(&bo->base.vma_node.vm_node));
145 
146 	ttm_resource_free(bo, &bo->resource);
147 	ttm_bo_put(bo);
148 }
149 
ttm_bo_init_reserved_mock_man(struct kunit * test)150 static void ttm_bo_init_reserved_mock_man(struct kunit *test)
151 {
152 	const struct ttm_bo_validate_test_case *params = test->param_value;
153 	enum ttm_bo_type bo_type = params->bo_type;
154 	struct ttm_test_devices *priv = test->priv;
155 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
156 	struct ttm_operation_ctx ctx = { };
157 	struct ttm_placement *placement;
158 	u32 mem_type = TTM_PL_VRAM;
159 	struct ttm_buffer_object *bo;
160 	struct ttm_place *place;
161 	int err;
162 
163 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
164 
165 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
166 	KUNIT_ASSERT_NOT_NULL(test, bo);
167 
168 	place = ttm_place_kunit_init(test, mem_type, 0);
169 	placement = ttm_placement_kunit_init(test, place, 1);
170 
171 	drm_gem_private_object_init(priv->drm, &bo->base, size);
172 
173 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
174 				   PAGE_SIZE, &ctx, NULL, NULL,
175 				   &dummy_ttm_bo_destroy);
176 	dma_resv_unlock(bo->base.resv);
177 
178 	KUNIT_EXPECT_EQ(test, err, 0);
179 	KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1);
180 	KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev);
181 	KUNIT_EXPECT_EQ(test, bo->type, bo_type);
182 	KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
183 
184 	if (bo_type != ttm_bo_type_kernel)
185 		KUNIT_EXPECT_TRUE(test,
186 				  drm_mm_node_allocated(&bo->base.vma_node.vm_node));
187 
188 	ttm_resource_free(bo, &bo->resource);
189 	ttm_bo_put(bo);
190 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
191 }
192 
ttm_bo_init_reserved_resv(struct kunit * test)193 static void ttm_bo_init_reserved_resv(struct kunit *test)
194 {
195 	enum ttm_bo_type bo_type = ttm_bo_type_device;
196 	struct ttm_test_devices *priv = test->priv;
197 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
198 	struct ttm_operation_ctx ctx = { };
199 	struct ttm_placement *placement;
200 	struct ttm_buffer_object *bo;
201 	struct ttm_place *place;
202 	struct dma_resv resv;
203 	int err;
204 
205 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
206 	KUNIT_ASSERT_NOT_NULL(test, bo);
207 
208 	place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
209 	placement = ttm_placement_kunit_init(test, place, 1);
210 
211 	drm_gem_private_object_init(priv->drm, &bo->base, size);
212 	dma_resv_init(&resv);
213 	dma_resv_lock(&resv, NULL);
214 
215 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement,
216 				   PAGE_SIZE, &ctx, NULL, &resv,
217 				   &dummy_ttm_bo_destroy);
218 	dma_resv_unlock(bo->base.resv);
219 
220 	KUNIT_EXPECT_EQ(test, err, 0);
221 	KUNIT_EXPECT_PTR_EQ(test, bo->base.resv, &resv);
222 
223 	ttm_resource_free(bo, &bo->resource);
224 	ttm_bo_put(bo);
225 }
226 
ttm_bo_validate_basic(struct kunit * test)227 static void ttm_bo_validate_basic(struct kunit *test)
228 {
229 	const struct ttm_bo_validate_test_case *params = test->param_value;
230 	u32 fst_mem = TTM_PL_SYSTEM, snd_mem = TTM_PL_VRAM;
231 	struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
232 	struct ttm_placement *fst_placement, *snd_placement;
233 	struct ttm_test_devices *priv = test->priv;
234 	struct ttm_place *fst_place, *snd_place;
235 	u32 size = ALIGN(SZ_8K, PAGE_SIZE);
236 	struct ttm_buffer_object *bo;
237 	int err;
238 
239 	ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
240 
241 	fst_place = ttm_place_kunit_init(test, fst_mem, 0);
242 	fst_placement = ttm_placement_kunit_init(test, fst_place, 1);
243 
244 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
245 	KUNIT_ASSERT_NOT_NULL(test, bo);
246 
247 	drm_gem_private_object_init(priv->drm, &bo->base, size);
248 
249 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
250 				   fst_placement, PAGE_SIZE, &ctx_init, NULL,
251 				   NULL, &dummy_ttm_bo_destroy);
252 	KUNIT_EXPECT_EQ(test, err, 0);
253 
254 	snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION);
255 	snd_placement = ttm_placement_kunit_init(test, snd_place, 1);
256 
257 	err = ttm_bo_validate(bo, snd_placement, &ctx_val);
258 	dma_resv_unlock(bo->base.resv);
259 
260 	KUNIT_EXPECT_EQ(test, err, 0);
261 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
262 	KUNIT_EXPECT_NOT_NULL(test, bo->ttm);
263 	KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm));
264 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
265 	KUNIT_EXPECT_EQ(test, bo->resource->placement,
266 			DRM_BUDDY_TOPDOWN_ALLOCATION);
267 
268 	ttm_bo_put(bo);
269 	ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
270 }
271 
ttm_bo_validate_invalid_placement(struct kunit * test)272 static void ttm_bo_validate_invalid_placement(struct kunit *test)
273 {
274 	enum ttm_bo_type bo_type = ttm_bo_type_device;
275 	u32 unknown_mem_type = TTM_PL_PRIV + 1;
276 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
277 	struct ttm_operation_ctx ctx = { };
278 	struct ttm_placement *placement;
279 	struct ttm_buffer_object *bo;
280 	struct ttm_place *place;
281 	int err;
282 
283 	place = ttm_place_kunit_init(test, unknown_mem_type, 0);
284 	placement = ttm_placement_kunit_init(test, place, 1);
285 
286 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
287 	bo->type = bo_type;
288 
289 	ttm_bo_reserve(bo, false, false, NULL);
290 	err = ttm_bo_validate(bo, placement, &ctx);
291 	dma_resv_unlock(bo->base.resv);
292 
293 	KUNIT_EXPECT_EQ(test, err, -ENOMEM);
294 
295 	ttm_bo_put(bo);
296 }
297 
ttm_bo_validate_failed_alloc(struct kunit * test)298 static void ttm_bo_validate_failed_alloc(struct kunit *test)
299 {
300 	enum ttm_bo_type bo_type = ttm_bo_type_device;
301 	struct ttm_test_devices *priv = test->priv;
302 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
303 	struct ttm_operation_ctx ctx = { };
304 	struct ttm_placement *placement;
305 	u32 mem_type = TTM_PL_VRAM;
306 	struct ttm_buffer_object *bo;
307 	struct ttm_place *place;
308 	int err;
309 
310 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
311 	bo->type = bo_type;
312 
313 	ttm_bad_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
314 
315 	place = ttm_place_kunit_init(test, mem_type, 0);
316 	placement = ttm_placement_kunit_init(test, place, 1);
317 
318 	ttm_bo_reserve(bo, false, false, NULL);
319 	err = ttm_bo_validate(bo, placement, &ctx);
320 	dma_resv_unlock(bo->base.resv);
321 
322 	KUNIT_EXPECT_EQ(test, err, -ENOMEM);
323 
324 	ttm_bo_put(bo);
325 	ttm_bad_manager_fini(priv->ttm_dev, mem_type);
326 }
327 
ttm_bo_validate_pinned(struct kunit * test)328 static void ttm_bo_validate_pinned(struct kunit *test)
329 {
330 	enum ttm_bo_type bo_type = ttm_bo_type_device;
331 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
332 	struct ttm_operation_ctx ctx = { };
333 	u32 mem_type = TTM_PL_SYSTEM;
334 	struct ttm_placement *placement;
335 	struct ttm_buffer_object *bo;
336 	struct ttm_place *place;
337 	int err;
338 
339 	place = ttm_place_kunit_init(test, mem_type, 0);
340 	placement = ttm_placement_kunit_init(test, place, 1);
341 
342 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
343 	bo->type = bo_type;
344 
345 	ttm_bo_reserve(bo, false, false, NULL);
346 	ttm_bo_pin(bo);
347 	err = ttm_bo_validate(bo, placement, &ctx);
348 	dma_resv_unlock(bo->base.resv);
349 
350 	KUNIT_EXPECT_EQ(test, err, -EINVAL);
351 
352 	ttm_bo_reserve(bo, false, false, NULL);
353 	ttm_bo_unpin(bo);
354 	dma_resv_unlock(bo->base.resv);
355 
356 	ttm_bo_put(bo);
357 }
358 
359 static const struct ttm_bo_validate_test_case ttm_mem_type_cases[] = {
360 	{
361 		.description = "System manager",
362 		.mem_type = TTM_PL_SYSTEM,
363 	},
364 	{
365 		.description = "VRAM manager",
366 		.mem_type = TTM_PL_VRAM,
367 	},
368 };
369 
370 KUNIT_ARRAY_PARAM(ttm_bo_validate_mem, ttm_mem_type_cases,
371 		  ttm_bo_validate_case_desc);
372 
ttm_bo_validate_same_placement(struct kunit * test)373 static void ttm_bo_validate_same_placement(struct kunit *test)
374 {
375 	const struct ttm_bo_validate_test_case *params = test->param_value;
376 	struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
377 	struct ttm_test_devices *priv = test->priv;
378 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
379 	struct ttm_placement *placement;
380 	struct ttm_buffer_object *bo;
381 	struct ttm_place *place;
382 	int err;
383 
384 	place = ttm_place_kunit_init(test, params->mem_type, 0);
385 	placement = ttm_placement_kunit_init(test, place, 1);
386 
387 	if (params->mem_type != TTM_PL_SYSTEM)
388 		ttm_mock_manager_init(priv->ttm_dev, params->mem_type, MANAGER_SIZE);
389 
390 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
391 	KUNIT_ASSERT_NOT_NULL(test, bo);
392 
393 	drm_gem_private_object_init(priv->drm, &bo->base, size);
394 
395 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
396 				   placement, PAGE_SIZE, &ctx_init, NULL,
397 				   NULL, &dummy_ttm_bo_destroy);
398 	KUNIT_EXPECT_EQ(test, err, 0);
399 
400 	err = ttm_bo_validate(bo, placement, &ctx_val);
401 	dma_resv_unlock(bo->base.resv);
402 
403 	KUNIT_EXPECT_EQ(test, err, 0);
404 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, 0);
405 
406 	ttm_bo_put(bo);
407 
408 	if (params->mem_type != TTM_PL_SYSTEM)
409 		ttm_mock_manager_fini(priv->ttm_dev, params->mem_type);
410 }
411 
ttm_bo_validate_busy_placement(struct kunit * test)412 static void ttm_bo_validate_busy_placement(struct kunit *test)
413 {
414 	u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
415 	struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
416 	struct ttm_placement *placement_init, *placement_val;
417 	enum ttm_bo_type bo_type = ttm_bo_type_device;
418 	struct ttm_test_devices *priv = test->priv;
419 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
420 	struct ttm_place *init_place, places[2];
421 	struct ttm_resource_manager *man;
422 	struct ttm_buffer_object *bo;
423 	int err;
424 
425 	ttm_bad_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
426 	ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
427 
428 	init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
429 	placement_init = ttm_placement_kunit_init(test, init_place, 1);
430 
431 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
432 	KUNIT_ASSERT_NOT_NULL(test, bo);
433 
434 	drm_gem_private_object_init(priv->drm, &bo->base, size);
435 
436 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
437 				   PAGE_SIZE, &ctx_init, NULL, NULL,
438 				   &dummy_ttm_bo_destroy);
439 	KUNIT_EXPECT_EQ(test, err, 0);
440 
441 	places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED };
442 	places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK };
443 	placement_val = ttm_placement_kunit_init(test, places, 2);
444 
445 	err = ttm_bo_validate(bo, placement_val, &ctx_val);
446 	dma_resv_unlock(bo->base.resv);
447 
448 	man = ttm_manager_type(priv->ttm_dev, snd_mem);
449 
450 	KUNIT_EXPECT_EQ(test, err, 0);
451 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size);
452 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
453 	KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority]));
454 
455 	ttm_bo_put(bo);
456 	ttm_bad_manager_fini(priv->ttm_dev, fst_mem);
457 	ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
458 }
459 
ttm_bo_validate_multihop(struct kunit * test)460 static void ttm_bo_validate_multihop(struct kunit *test)
461 {
462 	const struct ttm_bo_validate_test_case *params = test->param_value;
463 	struct ttm_operation_ctx ctx_init = { }, ctx_val = { };
464 	struct ttm_placement *placement_init, *placement_val;
465 	u32 fst_mem = TTM_PL_VRAM, tmp_mem = TTM_PL_TT, final_mem = TTM_PL_SYSTEM;
466 	struct ttm_test_devices *priv = test->priv;
467 	struct ttm_place *fst_place, *final_place;
468 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
469 	struct ttm_buffer_object *bo;
470 	int err;
471 
472 	ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
473 	ttm_mock_manager_init(priv->ttm_dev, tmp_mem, MANAGER_SIZE);
474 
475 	fst_place = ttm_place_kunit_init(test, fst_mem, 0);
476 	placement_init = ttm_placement_kunit_init(test, fst_place, 1);
477 
478 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
479 	KUNIT_ASSERT_NOT_NULL(test, bo);
480 
481 	drm_gem_private_object_init(priv->drm, &bo->base, size);
482 
483 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type,
484 				   placement_init, PAGE_SIZE, &ctx_init, NULL,
485 				   NULL, &dummy_ttm_bo_destroy);
486 	KUNIT_EXPECT_EQ(test, err, 0);
487 
488 	final_place = ttm_place_kunit_init(test, final_mem, 0);
489 	placement_val = ttm_placement_kunit_init(test, final_place, 1);
490 
491 	err = ttm_bo_validate(bo, placement_val, &ctx_val);
492 	dma_resv_unlock(bo->base.resv);
493 
494 	KUNIT_EXPECT_EQ(test, err, 0);
495 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2);
496 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, final_mem);
497 
498 	ttm_bo_put(bo);
499 
500 	ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
501 	ttm_mock_manager_fini(priv->ttm_dev, tmp_mem);
502 }
503 
504 static const struct ttm_bo_validate_test_case ttm_bo_no_placement_cases[] = {
505 	{
506 		.description = "Buffer object in system domain, no page vector",
507 	},
508 	{
509 		.description = "Buffer object in system domain with an existing page vector",
510 		.with_ttm = true,
511 	},
512 };
513 
514 KUNIT_ARRAY_PARAM(ttm_bo_no_placement, ttm_bo_no_placement_cases,
515 		  ttm_bo_validate_case_desc);
516 
ttm_bo_validate_no_placement_signaled(struct kunit * test)517 static void ttm_bo_validate_no_placement_signaled(struct kunit *test)
518 {
519 	const struct ttm_bo_validate_test_case *params = test->param_value;
520 	enum ttm_bo_type bo_type = ttm_bo_type_device;
521 	struct ttm_test_devices *priv = test->priv;
522 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
523 	struct ttm_operation_ctx ctx = { };
524 	u32 mem_type = TTM_PL_SYSTEM;
525 	struct ttm_resource_manager *man;
526 	struct ttm_placement *placement;
527 	struct ttm_buffer_object *bo;
528 	struct ttm_place *place;
529 	struct ttm_tt *old_tt;
530 	u32 flags;
531 	int err;
532 
533 	place = ttm_place_kunit_init(test, mem_type, 0);
534 	man = ttm_manager_type(priv->ttm_dev, mem_type);
535 
536 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
537 	bo->type = bo_type;
538 
539 	if (params->with_ttm) {
540 		old_tt = priv->ttm_dev->funcs->ttm_tt_create(bo, 0);
541 		ttm_pool_alloc(&priv->ttm_dev->pool, old_tt, &ctx);
542 		bo->ttm = old_tt;
543 	}
544 
545 	err = ttm_resource_alloc(bo, place, &bo->resource);
546 	KUNIT_EXPECT_EQ(test, err, 0);
547 	KUNIT_ASSERT_EQ(test, man->usage, size);
548 
549 	placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
550 	KUNIT_ASSERT_NOT_NULL(test, placement);
551 
552 	ttm_bo_reserve(bo, false, false, NULL);
553 	err = ttm_bo_validate(bo, placement, &ctx);
554 	ttm_bo_unreserve(bo);
555 
556 	KUNIT_EXPECT_EQ(test, err, 0);
557 	KUNIT_ASSERT_EQ(test, man->usage, 0);
558 	KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
559 	KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
560 
561 	if (params->with_ttm) {
562 		flags = bo->ttm->page_flags;
563 
564 		KUNIT_ASSERT_PTR_EQ(test, bo->ttm, old_tt);
565 		KUNIT_ASSERT_FALSE(test, flags & TTM_TT_FLAG_PRIV_POPULATED);
566 		KUNIT_ASSERT_TRUE(test, flags & TTM_TT_FLAG_ZERO_ALLOC);
567 	}
568 
569 	ttm_bo_put(bo);
570 }
571 
threaded_dma_resv_signal(void * arg)572 static int threaded_dma_resv_signal(void *arg)
573 {
574 	struct ttm_buffer_object *bo = arg;
575 	struct dma_resv *resv = bo->base.resv;
576 	struct dma_resv_iter cursor;
577 	struct dma_fence *fence;
578 
579 	dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP);
580 	dma_resv_for_each_fence_unlocked(&cursor, fence) {
581 		dma_fence_signal(fence);
582 	}
583 	dma_resv_iter_end(&cursor);
584 
585 	return 0;
586 }
587 
ttm_bo_validate_no_placement_not_signaled(struct kunit * test)588 static void ttm_bo_validate_no_placement_not_signaled(struct kunit *test)
589 {
590 	const struct ttm_bo_validate_test_case *params = test->param_value;
591 	enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP;
592 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
593 	struct ttm_operation_ctx ctx = { };
594 	u32 mem_type = TTM_PL_SYSTEM;
595 	struct ttm_placement *placement;
596 	struct ttm_buffer_object *bo;
597 	struct task_struct *task;
598 	struct ttm_place *place;
599 	int err;
600 
601 	place = ttm_place_kunit_init(test, mem_type, 0);
602 
603 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
604 	bo->type = params->bo_type;
605 
606 	err = ttm_resource_alloc(bo, place, &bo->resource);
607 	KUNIT_EXPECT_EQ(test, err, 0);
608 
609 	placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL);
610 	KUNIT_ASSERT_NOT_NULL(test, placement);
611 
612 	/* Create an active fence to simulate a non-idle resv object */
613 	spin_lock_init(&fence_lock);
614 	dma_resv_kunit_active_fence_init(test, bo->base.resv, usage);
615 
616 	task = kthread_create(threaded_dma_resv_signal, bo, "dma-resv-signal");
617 	if (IS_ERR(task))
618 		KUNIT_FAIL(test, "Couldn't create dma resv signal task\n");
619 
620 	wake_up_process(task);
621 	ttm_bo_reserve(bo, false, false, NULL);
622 	err = ttm_bo_validate(bo, placement, &ctx);
623 	ttm_bo_unreserve(bo);
624 
625 	KUNIT_EXPECT_EQ(test, err, 0);
626 	KUNIT_ASSERT_NOT_NULL(test, bo->ttm);
627 	KUNIT_ASSERT_NULL(test, bo->resource);
628 	KUNIT_ASSERT_NULL(test, bo->bulk_move);
629 	KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0);
630 
631 	if (bo->type != ttm_bo_type_sg)
632 		KUNIT_ASSERT_PTR_EQ(test, bo->base.resv, &bo->base._resv);
633 
634 	/* Make sure we have an idle object at this point */
635 	dma_resv_wait_timeout(bo->base.resv, usage, false, MAX_SCHEDULE_TIMEOUT);
636 
637 	ttm_bo_put(bo);
638 }
639 
ttm_bo_validate_move_fence_signaled(struct kunit * test)640 static void ttm_bo_validate_move_fence_signaled(struct kunit *test)
641 {
642 	enum ttm_bo_type bo_type = ttm_bo_type_device;
643 	struct ttm_test_devices *priv = test->priv;
644 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
645 	struct ttm_operation_ctx ctx = { };
646 	u32 mem_type = TTM_PL_SYSTEM;
647 	struct ttm_resource_manager *man;
648 	struct ttm_placement *placement;
649 	struct ttm_buffer_object *bo;
650 	struct ttm_place *place;
651 	int err;
652 
653 	man = ttm_manager_type(priv->ttm_dev, mem_type);
654 	man->move = dma_fence_get_stub();
655 
656 	bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
657 	bo->type = bo_type;
658 
659 	place = ttm_place_kunit_init(test, mem_type, 0);
660 	placement = ttm_placement_kunit_init(test, place, 1);
661 
662 	ttm_bo_reserve(bo, false, false, NULL);
663 	err = ttm_bo_validate(bo, placement, &ctx);
664 	ttm_bo_unreserve(bo);
665 
666 	KUNIT_EXPECT_EQ(test, err, 0);
667 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
668 	KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size);
669 
670 	ttm_bo_put(bo);
671 	dma_fence_put(man->move);
672 }
673 
674 static const struct ttm_bo_validate_test_case ttm_bo_validate_wait_cases[] = {
675 	{
676 		.description = "Waits for GPU",
677 		.no_gpu_wait = false,
678 	},
679 	{
680 		.description = "Tries to lock straight away",
681 		.no_gpu_wait = true,
682 	},
683 };
684 
685 KUNIT_ARRAY_PARAM(ttm_bo_validate_wait, ttm_bo_validate_wait_cases,
686 		  ttm_bo_validate_case_desc);
687 
threaded_fence_signal(void * arg)688 static int threaded_fence_signal(void *arg)
689 {
690 	struct dma_fence *fence = arg;
691 
692 	msleep(20);
693 
694 	return dma_fence_signal(fence);
695 }
696 
ttm_bo_validate_move_fence_not_signaled(struct kunit * test)697 static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
698 {
699 	const struct ttm_bo_validate_test_case *params = test->param_value;
700 	struct ttm_operation_ctx ctx_init = { },
701 				 ctx_val  = { .no_wait_gpu = params->no_gpu_wait };
702 	u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1;
703 	struct ttm_placement *placement_init, *placement_val;
704 	enum ttm_bo_type bo_type = ttm_bo_type_device;
705 	struct ttm_test_devices *priv = test->priv;
706 	u32 size = ALIGN(BO_SIZE, PAGE_SIZE);
707 	struct ttm_place *init_place, places[2];
708 	struct ttm_resource_manager *man;
709 	struct ttm_buffer_object *bo;
710 	struct task_struct *task;
711 	int err;
712 
713 	init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0);
714 	placement_init = ttm_placement_kunit_init(test, init_place, 1);
715 
716 	bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL);
717 	KUNIT_ASSERT_NOT_NULL(test, bo);
718 
719 	drm_gem_private_object_init(priv->drm, &bo->base, size);
720 
721 	err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init,
722 				   PAGE_SIZE, &ctx_init, NULL, NULL,
723 				   &dummy_ttm_bo_destroy);
724 	KUNIT_EXPECT_EQ(test, err, 0);
725 
726 	ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE);
727 	ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE);
728 
729 	places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED };
730 	places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK };
731 	placement_val = ttm_placement_kunit_init(test, places, 2);
732 
733 	spin_lock_init(&fence_lock);
734 	man = ttm_manager_type(priv->ttm_dev, fst_mem);
735 	man->move = alloc_mock_fence(test);
736 
737 	task = kthread_create(threaded_fence_signal, man->move, "move-fence-signal");
738 	if (IS_ERR(task))
739 		KUNIT_FAIL(test, "Couldn't create move fence signal task\n");
740 
741 	wake_up_process(task);
742 	err = ttm_bo_validate(bo, placement_val, &ctx_val);
743 	dma_resv_unlock(bo->base.resv);
744 
745 	dma_fence_wait_timeout(man->move, false, MAX_SCHEDULE_TIMEOUT);
746 
747 	KUNIT_EXPECT_EQ(test, err, 0);
748 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size);
749 
750 	if (params->no_gpu_wait)
751 		KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
752 	else
753 		KUNIT_EXPECT_EQ(test, bo->resource->mem_type, fst_mem);
754 
755 	ttm_bo_put(bo);
756 	ttm_mock_manager_fini(priv->ttm_dev, fst_mem);
757 	ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
758 }
759 
ttm_bo_validate_swapout(struct kunit * test)760 static void ttm_bo_validate_swapout(struct kunit *test)
761 {
762 	unsigned long size_big, size = ALIGN(BO_SIZE, PAGE_SIZE);
763 	enum ttm_bo_type bo_type = ttm_bo_type_device;
764 	struct ttm_buffer_object *bo_small, *bo_big;
765 	struct ttm_test_devices *priv = test->priv;
766 	struct ttm_operation_ctx ctx = { };
767 	struct ttm_placement *placement;
768 	u32 mem_type = TTM_PL_TT;
769 	struct ttm_place *place;
770 	struct sysinfo si;
771 	int err;
772 
773 	si_meminfo(&si);
774 	size_big = ALIGN(((u64)si.totalram * si.mem_unit / 2), PAGE_SIZE);
775 
776 	ttm_mock_manager_init(priv->ttm_dev, mem_type, size_big + size);
777 
778 	place = ttm_place_kunit_init(test, mem_type, 0);
779 	placement = ttm_placement_kunit_init(test, place, 1);
780 
781 	bo_small = kunit_kzalloc(test, sizeof(*bo_small), GFP_KERNEL);
782 	KUNIT_ASSERT_NOT_NULL(test, bo_small);
783 
784 	drm_gem_private_object_init(priv->drm, &bo_small->base, size);
785 
786 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_small, bo_type, placement,
787 				   PAGE_SIZE, &ctx, NULL, NULL,
788 				   &dummy_ttm_bo_destroy);
789 	KUNIT_EXPECT_EQ(test, err, 0);
790 	dma_resv_unlock(bo_small->base.resv);
791 
792 	bo_big = ttm_bo_kunit_init(test, priv, size_big, NULL);
793 
794 	dma_resv_lock(bo_big->base.resv, NULL);
795 	err = ttm_bo_validate(bo_big, placement, &ctx);
796 	dma_resv_unlock(bo_big->base.resv);
797 
798 	KUNIT_EXPECT_EQ(test, err, 0);
799 	KUNIT_EXPECT_NOT_NULL(test, bo_big->resource);
800 	KUNIT_EXPECT_EQ(test, bo_big->resource->mem_type, mem_type);
801 	KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, TTM_PL_SYSTEM);
802 	KUNIT_EXPECT_TRUE(test, bo_small->ttm->page_flags & TTM_TT_FLAG_SWAPPED);
803 
804 	ttm_bo_put(bo_big);
805 	ttm_bo_put(bo_small);
806 
807 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
808 }
809 
ttm_bo_validate_happy_evict(struct kunit * test)810 static void ttm_bo_validate_happy_evict(struct kunit *test)
811 {
812 	u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT,
813 	    mem_type_evict = TTM_PL_SYSTEM;
814 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
815 	enum ttm_bo_type bo_type = ttm_bo_type_device;
816 	u32 small = SZ_8K, medium = SZ_512K,
817 	    big = MANAGER_SIZE - (small + medium);
818 	u32 bo_sizes[] = { small, medium, big };
819 	struct ttm_test_devices *priv = test->priv;
820 	struct ttm_buffer_object *bos, *bo_val;
821 	struct ttm_placement *placement;
822 	struct ttm_place *place;
823 	u32 bo_no = 3;
824 	int i, err;
825 
826 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
827 	ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
828 
829 	place = ttm_place_kunit_init(test, mem_type, 0);
830 	placement = ttm_placement_kunit_init(test, place, 1);
831 
832 	bos = kunit_kmalloc_array(test, bo_no, sizeof(*bos), GFP_KERNEL);
833 	KUNIT_ASSERT_NOT_NULL(test, bos);
834 
835 	memset(bos, 0, sizeof(*bos) * bo_no);
836 	for (i = 0; i < bo_no; i++) {
837 		drm_gem_private_object_init(priv->drm, &bos[i].base, bo_sizes[i]);
838 		err = ttm_bo_init_reserved(priv->ttm_dev, &bos[i], bo_type, placement,
839 					   PAGE_SIZE, &ctx_init, NULL, NULL,
840 					   &dummy_ttm_bo_destroy);
841 		dma_resv_unlock(bos[i].base.resv);
842 	}
843 
844 	bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
845 	bo_val->type = bo_type;
846 
847 	ttm_bo_reserve(bo_val, false, false, NULL);
848 	err = ttm_bo_validate(bo_val, placement, &ctx_val);
849 	ttm_bo_unreserve(bo_val);
850 
851 	KUNIT_EXPECT_EQ(test, err, 0);
852 	KUNIT_EXPECT_EQ(test, bos[0].resource->mem_type, mem_type_evict);
853 	KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
854 	KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_PRIV_POPULATED);
855 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, small * 2 + BO_SIZE);
856 	KUNIT_EXPECT_EQ(test, bos[1].resource->mem_type, mem_type);
857 
858 	for (i = 0; i < bo_no; i++)
859 		ttm_bo_put(&bos[i]);
860 	ttm_bo_put(bo_val);
861 
862 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
863 	ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
864 }
865 
ttm_bo_validate_all_pinned_evict(struct kunit * test)866 static void ttm_bo_validate_all_pinned_evict(struct kunit *test)
867 {
868 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
869 	enum ttm_bo_type bo_type = ttm_bo_type_device;
870 	struct ttm_buffer_object *bo_big, *bo_small;
871 	struct ttm_test_devices *priv = test->priv;
872 	struct ttm_placement *placement;
873 	u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT;
874 	struct ttm_place *place;
875 	int err;
876 
877 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
878 	ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
879 
880 	place = ttm_place_kunit_init(test, mem_type, 0);
881 	placement = ttm_placement_kunit_init(test, place, 1);
882 
883 	bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
884 	KUNIT_ASSERT_NOT_NULL(test, bo_big);
885 
886 	drm_gem_private_object_init(priv->drm, &bo_big->base, MANAGER_SIZE);
887 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
888 				   PAGE_SIZE, &ctx_init, NULL, NULL,
889 				   &dummy_ttm_bo_destroy);
890 	KUNIT_EXPECT_EQ(test, err, 0);
891 
892 	ttm_bo_pin(bo_big);
893 	dma_resv_unlock(bo_big->base.resv);
894 
895 	bo_small = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
896 	bo_small->type = bo_type;
897 
898 	ttm_bo_reserve(bo_small, false, false, NULL);
899 	err = ttm_bo_validate(bo_small, placement, &ctx_val);
900 	ttm_bo_unreserve(bo_small);
901 
902 	KUNIT_EXPECT_EQ(test, err, -ENOMEM);
903 
904 	ttm_bo_put(bo_small);
905 
906 	ttm_bo_reserve(bo_big, false, false, NULL);
907 	ttm_bo_unpin(bo_big);
908 	dma_resv_unlock(bo_big->base.resv);
909 	ttm_bo_put(bo_big);
910 
911 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
912 	ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
913 }
914 
ttm_bo_validate_allowed_only_evict(struct kunit * test)915 static void ttm_bo_validate_allowed_only_evict(struct kunit *test)
916 {
917 	u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT,
918 	    mem_type_evict = TTM_PL_SYSTEM;
919 	struct ttm_buffer_object *bo, *bo_evictable, *bo_pinned;
920 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
921 	enum ttm_bo_type bo_type = ttm_bo_type_device;
922 	struct ttm_test_devices *priv = test->priv;
923 	struct ttm_placement *placement;
924 	struct ttm_place *place;
925 	u32 size = SZ_512K;
926 	int err;
927 
928 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
929 	ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE);
930 
931 	place = ttm_place_kunit_init(test, mem_type, 0);
932 	placement = ttm_placement_kunit_init(test, place, 1);
933 
934 	bo_pinned = kunit_kzalloc(test, sizeof(*bo_pinned), GFP_KERNEL);
935 	KUNIT_ASSERT_NOT_NULL(test, bo_pinned);
936 
937 	drm_gem_private_object_init(priv->drm, &bo_pinned->base, size);
938 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_pinned, bo_type, placement,
939 				   PAGE_SIZE, &ctx_init, NULL, NULL,
940 				   &dummy_ttm_bo_destroy);
941 	KUNIT_EXPECT_EQ(test, err, 0);
942 	ttm_bo_pin(bo_pinned);
943 	dma_resv_unlock(bo_pinned->base.resv);
944 
945 	bo_evictable = kunit_kzalloc(test, sizeof(*bo_evictable), GFP_KERNEL);
946 	KUNIT_ASSERT_NOT_NULL(test, bo_evictable);
947 
948 	drm_gem_private_object_init(priv->drm, &bo_evictable->base, size);
949 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_evictable, bo_type, placement,
950 				   PAGE_SIZE, &ctx_init, NULL, NULL,
951 				   &dummy_ttm_bo_destroy);
952 	KUNIT_EXPECT_EQ(test, err, 0);
953 	dma_resv_unlock(bo_evictable->base.resv);
954 
955 	bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
956 	bo->type = bo_type;
957 
958 	ttm_bo_reserve(bo, false, false, NULL);
959 	err = ttm_bo_validate(bo, placement, &ctx_val);
960 	ttm_bo_unreserve(bo);
961 
962 	KUNIT_EXPECT_EQ(test, err, 0);
963 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
964 	KUNIT_EXPECT_EQ(test, bo_pinned->resource->mem_type, mem_type);
965 	KUNIT_EXPECT_EQ(test, bo_evictable->resource->mem_type, mem_type_evict);
966 	KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2 + BO_SIZE);
967 
968 	ttm_bo_put(bo);
969 	ttm_bo_put(bo_evictable);
970 
971 	ttm_bo_reserve(bo_pinned, false, false, NULL);
972 	ttm_bo_unpin(bo_pinned);
973 	dma_resv_unlock(bo_pinned->base.resv);
974 	ttm_bo_put(bo_pinned);
975 
976 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
977 	ttm_mock_manager_fini(priv->ttm_dev, mem_multihop);
978 }
979 
ttm_bo_validate_deleted_evict(struct kunit * test)980 static void ttm_bo_validate_deleted_evict(struct kunit *test)
981 {
982 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
983 	u32 small = SZ_8K, big = MANAGER_SIZE - BO_SIZE;
984 	enum ttm_bo_type bo_type = ttm_bo_type_device;
985 	struct ttm_buffer_object *bo_big, *bo_small;
986 	struct ttm_test_devices *priv = test->priv;
987 	struct ttm_resource_manager *man;
988 	u32 mem_type = TTM_PL_VRAM;
989 	struct ttm_placement *placement;
990 	struct ttm_place *place;
991 	int err;
992 
993 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
994 	man = ttm_manager_type(priv->ttm_dev, mem_type);
995 
996 	place = ttm_place_kunit_init(test, mem_type, 0);
997 	placement = ttm_placement_kunit_init(test, place, 1);
998 
999 	bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL);
1000 	KUNIT_ASSERT_NOT_NULL(test, bo_big);
1001 
1002 	drm_gem_private_object_init(priv->drm, &bo_big->base, big);
1003 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement,
1004 				   PAGE_SIZE, &ctx_init, NULL, NULL,
1005 				   &dummy_ttm_bo_destroy);
1006 	KUNIT_EXPECT_EQ(test, err, 0);
1007 	KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), big);
1008 
1009 	dma_resv_unlock(bo_big->base.resv);
1010 	bo_big->deleted = true;
1011 
1012 	bo_small = ttm_bo_kunit_init(test, test->priv, small, NULL);
1013 	bo_small->type = bo_type;
1014 
1015 	ttm_bo_reserve(bo_small, false, false, NULL);
1016 	err = ttm_bo_validate(bo_small, placement, &ctx_val);
1017 	ttm_bo_unreserve(bo_small);
1018 
1019 	KUNIT_EXPECT_EQ(test, err, 0);
1020 	KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, mem_type);
1021 	KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), small);
1022 	KUNIT_EXPECT_NULL(test, bo_big->ttm);
1023 	KUNIT_EXPECT_NULL(test, bo_big->resource);
1024 
1025 	ttm_bo_put(bo_small);
1026 	ttm_bo_put(bo_big);
1027 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
1028 }
1029 
ttm_bo_validate_busy_domain_evict(struct kunit * test)1030 static void ttm_bo_validate_busy_domain_evict(struct kunit *test)
1031 {
1032 	u32 mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_MOCK1;
1033 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
1034 	enum ttm_bo_type bo_type = ttm_bo_type_device;
1035 	struct ttm_test_devices *priv = test->priv;
1036 	struct ttm_buffer_object *bo_init, *bo_val;
1037 	struct ttm_placement *placement;
1038 	struct ttm_place *place;
1039 	int err;
1040 
1041 	/*
1042 	 * Drop the default device and setup a new one that points to busy
1043 	 * thus unsuitable eviction domain
1044 	 */
1045 	ttm_device_fini(priv->ttm_dev);
1046 
1047 	err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev, false, false);
1048 	KUNIT_ASSERT_EQ(test, err, 0);
1049 
1050 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
1051 	ttm_busy_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
1052 
1053 	place = ttm_place_kunit_init(test, mem_type, 0);
1054 	placement = ttm_placement_kunit_init(test, place, 1);
1055 
1056 	bo_init = kunit_kzalloc(test, sizeof(*bo_init), GFP_KERNEL);
1057 	KUNIT_ASSERT_NOT_NULL(test, bo_init);
1058 
1059 	drm_gem_private_object_init(priv->drm, &bo_init->base, MANAGER_SIZE);
1060 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_init, bo_type, placement,
1061 				   PAGE_SIZE, &ctx_init, NULL, NULL,
1062 				   &dummy_ttm_bo_destroy);
1063 	KUNIT_EXPECT_EQ(test, err, 0);
1064 	dma_resv_unlock(bo_init->base.resv);
1065 
1066 	bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
1067 	bo_val->type = bo_type;
1068 
1069 	ttm_bo_reserve(bo_val, false, false, NULL);
1070 	err = ttm_bo_validate(bo_val, placement, &ctx_val);
1071 	ttm_bo_unreserve(bo_val);
1072 
1073 	KUNIT_EXPECT_EQ(test, err, -ENOMEM);
1074 	KUNIT_EXPECT_EQ(test, bo_init->resource->mem_type, mem_type);
1075 	KUNIT_EXPECT_NULL(test, bo_val->resource);
1076 
1077 	ttm_bo_put(bo_init);
1078 	ttm_bo_put(bo_val);
1079 
1080 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
1081 	ttm_bad_manager_fini(priv->ttm_dev, mem_type_evict);
1082 }
1083 
ttm_bo_validate_evict_gutting(struct kunit * test)1084 static void ttm_bo_validate_evict_gutting(struct kunit *test)
1085 {
1086 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
1087 	enum ttm_bo_type bo_type = ttm_bo_type_device;
1088 	struct ttm_test_devices *priv = test->priv;
1089 	struct ttm_buffer_object *bo, *bo_evict;
1090 	u32 mem_type = TTM_PL_MOCK1;
1091 	struct ttm_placement *placement;
1092 	struct ttm_place *place;
1093 	int err;
1094 
1095 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
1096 
1097 	place = ttm_place_kunit_init(test, mem_type, 0);
1098 	placement = ttm_placement_kunit_init(test, place, 1);
1099 
1100 	bo_evict = kunit_kzalloc(test, sizeof(*bo_evict), GFP_KERNEL);
1101 	KUNIT_ASSERT_NOT_NULL(test, bo_evict);
1102 
1103 	drm_gem_private_object_init(priv->drm, &bo_evict->base, MANAGER_SIZE);
1104 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_evict, bo_type, placement,
1105 				   PAGE_SIZE, &ctx_init, NULL, NULL,
1106 				   &dummy_ttm_bo_destroy);
1107 	KUNIT_EXPECT_EQ(test, err, 0);
1108 	dma_resv_unlock(bo_evict->base.resv);
1109 
1110 	bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
1111 	bo->type = bo_type;
1112 
1113 	ttm_bo_reserve(bo, false, false, NULL);
1114 	err = ttm_bo_validate(bo, placement, &ctx_val);
1115 	ttm_bo_unreserve(bo);
1116 
1117 	KUNIT_EXPECT_EQ(test, err, 0);
1118 	KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type);
1119 	KUNIT_ASSERT_NULL(test, bo_evict->resource);
1120 	KUNIT_ASSERT_TRUE(test, bo_evict->ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC);
1121 
1122 	ttm_bo_put(bo_evict);
1123 	ttm_bo_put(bo);
1124 
1125 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
1126 }
1127 
ttm_bo_validate_recrusive_evict(struct kunit * test)1128 static void ttm_bo_validate_recrusive_evict(struct kunit *test)
1129 {
1130 	u32 mem_type = TTM_PL_TT, mem_type_evict = TTM_PL_MOCK2;
1131 	struct ttm_operation_ctx ctx_init = { }, ctx_val  = { };
1132 	struct ttm_placement *placement_tt, *placement_mock;
1133 	struct ttm_buffer_object *bo_tt, *bo_mock, *bo_val;
1134 	enum ttm_bo_type bo_type = ttm_bo_type_device;
1135 	struct ttm_test_devices *priv = test->priv;
1136 	struct ttm_place *place_tt, *place_mock;
1137 	int err;
1138 
1139 	ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE);
1140 	ttm_mock_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE);
1141 
1142 	place_tt = ttm_place_kunit_init(test, mem_type, 0);
1143 	place_mock = ttm_place_kunit_init(test, mem_type_evict, 0);
1144 
1145 	placement_tt = ttm_placement_kunit_init(test, place_tt, 1);
1146 	placement_mock = ttm_placement_kunit_init(test, place_mock, 1);
1147 
1148 	bo_tt = kunit_kzalloc(test, sizeof(*bo_tt), GFP_KERNEL);
1149 	KUNIT_ASSERT_NOT_NULL(test, bo_tt);
1150 
1151 	bo_mock = kunit_kzalloc(test, sizeof(*bo_mock), GFP_KERNEL);
1152 	KUNIT_ASSERT_NOT_NULL(test, bo_mock);
1153 
1154 	drm_gem_private_object_init(priv->drm, &bo_tt->base, MANAGER_SIZE);
1155 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_tt, bo_type, placement_tt,
1156 				   PAGE_SIZE, &ctx_init, NULL, NULL,
1157 				   &dummy_ttm_bo_destroy);
1158 	KUNIT_EXPECT_EQ(test, err, 0);
1159 	dma_resv_unlock(bo_tt->base.resv);
1160 
1161 	drm_gem_private_object_init(priv->drm, &bo_mock->base, MANAGER_SIZE);
1162 	err = ttm_bo_init_reserved(priv->ttm_dev, bo_mock, bo_type, placement_mock,
1163 				   PAGE_SIZE, &ctx_init, NULL, NULL,
1164 				   &dummy_ttm_bo_destroy);
1165 	KUNIT_EXPECT_EQ(test, err, 0);
1166 	dma_resv_unlock(bo_mock->base.resv);
1167 
1168 	bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
1169 	bo_val->type = bo_type;
1170 
1171 	ttm_bo_reserve(bo_val, false, false, NULL);
1172 	err = ttm_bo_validate(bo_val, placement_tt, &ctx_val);
1173 	ttm_bo_unreserve(bo_val);
1174 
1175 	KUNIT_EXPECT_EQ(test, err, 0);
1176 
1177 	ttm_mock_manager_fini(priv->ttm_dev, mem_type);
1178 	ttm_mock_manager_fini(priv->ttm_dev, mem_type_evict);
1179 
1180 	ttm_bo_put(bo_val);
1181 	ttm_bo_put(bo_tt);
1182 	ttm_bo_put(bo_mock);
1183 }
1184 
1185 static struct kunit_case ttm_bo_validate_test_cases[] = {
1186 	KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params),
1187 	KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params),
1188 	KUNIT_CASE(ttm_bo_init_reserved_resv),
1189 	KUNIT_CASE_PARAM(ttm_bo_validate_basic, ttm_bo_types_gen_params),
1190 	KUNIT_CASE(ttm_bo_validate_invalid_placement),
1191 	KUNIT_CASE_PARAM(ttm_bo_validate_same_placement,
1192 			 ttm_bo_validate_mem_gen_params),
1193 	KUNIT_CASE(ttm_bo_validate_failed_alloc),
1194 	KUNIT_CASE(ttm_bo_validate_pinned),
1195 	KUNIT_CASE(ttm_bo_validate_busy_placement),
1196 	KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params),
1197 	KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_signaled,
1198 			 ttm_bo_no_placement_gen_params),
1199 	KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_not_signaled,
1200 			 ttm_bo_types_gen_params),
1201 	KUNIT_CASE(ttm_bo_validate_move_fence_signaled),
1202 	KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled,
1203 			 ttm_bo_validate_wait_gen_params),
1204 	KUNIT_CASE(ttm_bo_validate_swapout),
1205 	KUNIT_CASE(ttm_bo_validate_happy_evict),
1206 	KUNIT_CASE(ttm_bo_validate_all_pinned_evict),
1207 	KUNIT_CASE(ttm_bo_validate_allowed_only_evict),
1208 	KUNIT_CASE(ttm_bo_validate_deleted_evict),
1209 	KUNIT_CASE(ttm_bo_validate_busy_domain_evict),
1210 	KUNIT_CASE(ttm_bo_validate_evict_gutting),
1211 	KUNIT_CASE(ttm_bo_validate_recrusive_evict),
1212 	{}
1213 };
1214 
1215 static struct kunit_suite ttm_bo_validate_test_suite = {
1216 	.name = "ttm_bo_validate",
1217 	.init = ttm_test_devices_all_init,
1218 	.exit = ttm_test_devices_fini,
1219 	.test_cases = ttm_bo_validate_test_cases,
1220 };
1221 
1222 kunit_test_suites(&ttm_bo_validate_test_suite);
1223 
1224 MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs");
1225 MODULE_LICENSE("GPL and additional rights");
1226