xref: /dragonfly/sys/dev/drm/radeon/radeon_test.c (revision 79dee9e9)
1 /*
2  * Copyright 2009 VMware, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Michel Dänzer
23  */
24 #include <drm/drmP.h>
25 #include <drm/radeon_drm.h>
26 #include "radeon_reg.h"
27 #include "radeon.h"
28 
29 #define RADEON_TEST_COPY_BLIT 1
30 #define RADEON_TEST_COPY_DMA  0
31 
32 
33 /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
34 static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
35 {
36 	struct radeon_bo *vram_obj = NULL;
37 	struct radeon_bo **gtt_obj = NULL;
38 	struct radeon_fence *fence = NULL;
39 	u64 gtt_addr, vram_addr;
40 	unsigned n, size;
41 	int i, r, ring;
42 
43 	switch (flag) {
44 	case RADEON_TEST_COPY_DMA:
45 		ring = radeon_copy_dma_ring_index(rdev);
46 		break;
47 	case RADEON_TEST_COPY_BLIT:
48 		ring = radeon_copy_blit_ring_index(rdev);
49 		break;
50 	default:
51 		DRM_ERROR("Unknown copy method\n");
52 		return;
53 	}
54 
55 	size = 1024 * 1024;
56 
57 	/* Number of tests =
58 	 * (Total GTT - IB pool - writeback page - ring buffers) / test size
59 	 */
60 	n = rdev->mc.gtt_size - rdev->gart_pin_size;
61 	n /= size;
62 
63 	gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
64 	if (!gtt_obj) {
65 		DRM_ERROR("Failed to allocate %d pointers\n", n);
66 		r = 1;
67 		goto out_cleanup;
68 	}
69 
70 	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
71 			     0, NULL, &vram_obj);
72 	if (r) {
73 		DRM_ERROR("Failed to create VRAM object\n");
74 		goto out_cleanup;
75 	}
76 	r = radeon_bo_reserve(vram_obj, false);
77 	if (unlikely(r != 0))
78 		goto out_unref;
79 	r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
80 	if (r) {
81 		DRM_ERROR("Failed to pin VRAM object\n");
82 		goto out_unres;
83 	}
84 	for (i = 0; i < n; i++) {
85 		void *gtt_map, *vram_map;
86 		void **gtt_start, **gtt_end;
87 		void **vram_start, **vram_end;
88 
89 		r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
90 				     RADEON_GEM_DOMAIN_GTT, 0, NULL, gtt_obj + i);
91 		if (r) {
92 			DRM_ERROR("Failed to create GTT object %d\n", i);
93 			goto out_lclean;
94 		}
95 
96 		r = radeon_bo_reserve(gtt_obj[i], false);
97 		if (unlikely(r != 0))
98 			goto out_lclean_unref;
99 		r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
100 		if (r) {
101 			DRM_ERROR("Failed to pin GTT object %d\n", i);
102 			goto out_lclean_unres;
103 		}
104 
105 		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
106 		if (r) {
107 			DRM_ERROR("Failed to map GTT object %d\n", i);
108 			goto out_lclean_unpin;
109 		}
110 
111 		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size);
112 		     gtt_start < gtt_end;
113 		     gtt_start++)
114 			*gtt_start = gtt_start;
115 
116 		radeon_bo_kunmap(gtt_obj[i]);
117 
118 		if (ring == R600_RING_TYPE_DMA_INDEX)
119 			r = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
120 		else
121 			r = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
122 		if (r) {
123 			DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
124 			goto out_lclean_unpin;
125 		}
126 
127 		r = radeon_fence_wait(fence, false);
128 		if (r) {
129 			DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
130 			goto out_lclean_unpin;
131 		}
132 
133 		radeon_fence_unref(&fence);
134 
135 		r = radeon_bo_kmap(vram_obj, &vram_map);
136 		if (r) {
137 			DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
138 			goto out_lclean_unpin;
139 		}
140 
141 		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size),
142 		     vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size);
143 		     vram_start < vram_end;
144 		     gtt_start++, vram_start++) {
145 			if (*vram_start != gtt_start) {
146 				DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
147 					  "expected 0x%p (GTT/VRAM offset "
148 					  "0x%16llx/0x%16llx)\n",
149 					  i, *vram_start, gtt_start,
150 					  (unsigned long long)
151 					  ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start +
152 					   (uintptr_t)gtt_start - (uintptr_t)gtt_map),
153 					  (unsigned long long)
154 					  ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start +
155 					   (uintptr_t)gtt_start - (uintptr_t)gtt_map));
156 				radeon_bo_kunmap(vram_obj);
157 				goto out_lclean_unpin;
158 			}
159 			*vram_start = vram_start;
160 		}
161 
162 		radeon_bo_kunmap(vram_obj);
163 
164 		if (ring == R600_RING_TYPE_DMA_INDEX)
165 			r = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
166 		else
167 			r = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
168 		if (r) {
169 			DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
170 			goto out_lclean_unpin;
171 		}
172 
173 		r = radeon_fence_wait(fence, false);
174 		if (r) {
175 			DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
176 			goto out_lclean_unpin;
177 		}
178 
179 		radeon_fence_unref(&fence);
180 
181 		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
182 		if (r) {
183 			DRM_ERROR("Failed to map GTT object after copy %d\n", i);
184 			goto out_lclean_unpin;
185 		}
186 
187 		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size),
188 		     vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size);
189 		     gtt_start < gtt_end;
190 		     gtt_start++, vram_start++) {
191 			if (*gtt_start != vram_start) {
192 				DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
193 					  "expected 0x%p (VRAM/GTT offset "
194 					  "0x%16llx/0x%16llx)\n",
195 					  i, *gtt_start, vram_start,
196 					  (unsigned long long)
197 					  ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start +
198 					   (uintptr_t)vram_start - (uintptr_t)vram_map),
199 					  (unsigned long long)
200 					  ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start +
201 					   (uintptr_t)vram_start - (uintptr_t)vram_map));
202 				radeon_bo_kunmap(gtt_obj[i]);
203 				goto out_lclean_unpin;
204 			}
205 		}
206 
207 		radeon_bo_kunmap(gtt_obj[i]);
208 
209 		DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
210 			 (uintmax_t)gtt_addr - rdev->mc.gtt_start);
211 		continue;
212 
213 out_lclean_unpin:
214 		radeon_bo_unpin(gtt_obj[i]);
215 out_lclean_unres:
216 		radeon_bo_unreserve(gtt_obj[i]);
217 out_lclean_unref:
218 		radeon_bo_unref(&gtt_obj[i]);
219 out_lclean:
220 		for (--i; i >= 0; --i) {
221 			radeon_bo_unpin(gtt_obj[i]);
222 			radeon_bo_unreserve(gtt_obj[i]);
223 			radeon_bo_unref(&gtt_obj[i]);
224 		}
225 		if (fence && !IS_ERR(fence))
226 			radeon_fence_unref(&fence);
227 		break;
228 	}
229 
230 	radeon_bo_unpin(vram_obj);
231 out_unres:
232 	radeon_bo_unreserve(vram_obj);
233 out_unref:
234 	radeon_bo_unref(&vram_obj);
235 out_cleanup:
236 	if (gtt_obj)
237 		kfree(gtt_obj);
238 	if (fence) {
239 		radeon_fence_unref(&fence);
240 	}
241 	if (r) {
242 		printk(KERN_WARNING "Error while testing BO move.\n");
243 	}
244 }
245 
246 void radeon_test_moves(struct radeon_device *rdev)
247 {
248 	if (rdev->asic->copy.dma)
249 		radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA);
250 	if (rdev->asic->copy.blit)
251 		radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT);
252 }
253 
254 static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
255 					     struct radeon_ring *ring,
256 					     struct radeon_fence **fence)
257 {
258 	uint32_t handle = ring->idx ^ 0xdeafbeef;
259 	int r;
260 
261 	if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
262 		r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL);
263 		if (r) {
264 			DRM_ERROR("Failed to get dummy create msg\n");
265 			return r;
266 		}
267 
268 		r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence);
269 		if (r) {
270 			DRM_ERROR("Failed to get dummy destroy msg\n");
271 			return r;
272 		}
273 
274 	} else if (ring->idx == TN_RING_TYPE_VCE1_INDEX ||
275 		   ring->idx == TN_RING_TYPE_VCE2_INDEX) {
276 		r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL);
277 		if (r) {
278 			DRM_ERROR("Failed to get dummy create msg\n");
279 			return r;
280 		}
281 
282 		r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence);
283 		if (r) {
284 			DRM_ERROR("Failed to get dummy destroy msg\n");
285 			return r;
286 		}
287 
288 	} else {
289 		r = radeon_ring_lock(rdev, ring, 64);
290 		if (r) {
291 			DRM_ERROR("Failed to lock ring A %d\n", ring->idx);
292 			return r;
293 		}
294 		radeon_fence_emit(rdev, fence, ring->idx);
295 		radeon_ring_unlock_commit(rdev, ring, false);
296 	}
297 	return 0;
298 }
299 
300 void radeon_test_ring_sync(struct radeon_device *rdev,
301 			   struct radeon_ring *ringA,
302 			   struct radeon_ring *ringB)
303 {
304 	struct radeon_fence *fence1 = NULL, *fence2 = NULL;
305 	struct radeon_semaphore *semaphore = NULL;
306 	int r;
307 
308 	r = radeon_semaphore_create(rdev, &semaphore);
309 	if (r) {
310 		DRM_ERROR("Failed to create semaphore\n");
311 		goto out_cleanup;
312 	}
313 
314 	r = radeon_ring_lock(rdev, ringA, 64);
315 	if (r) {
316 		DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
317 		goto out_cleanup;
318 	}
319 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
320 	radeon_ring_unlock_commit(rdev, ringA, false);
321 
322 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1);
323 	if (r)
324 		goto out_cleanup;
325 
326 	r = radeon_ring_lock(rdev, ringA, 64);
327 	if (r) {
328 		DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
329 		goto out_cleanup;
330 	}
331 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
332 	radeon_ring_unlock_commit(rdev, ringA, false);
333 
334 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2);
335 	if (r)
336 		goto out_cleanup;
337 
338 	mdelay(1000);
339 
340 	if (radeon_fence_signaled(fence1)) {
341 		DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n");
342 		goto out_cleanup;
343 	}
344 
345 	r = radeon_ring_lock(rdev, ringB, 64);
346 	if (r) {
347 		DRM_ERROR("Failed to lock ring B %p\n", ringB);
348 		goto out_cleanup;
349 	}
350 	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
351 	radeon_ring_unlock_commit(rdev, ringB, false);
352 
353 	r = radeon_fence_wait(fence1, false);
354 	if (r) {
355 		DRM_ERROR("Failed to wait for sync fence 1\n");
356 		goto out_cleanup;
357 	}
358 
359 	mdelay(1000);
360 
361 	if (radeon_fence_signaled(fence2)) {
362 		DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n");
363 		goto out_cleanup;
364 	}
365 
366 	r = radeon_ring_lock(rdev, ringB, 64);
367 	if (r) {
368 		DRM_ERROR("Failed to lock ring B %p\n", ringB);
369 		goto out_cleanup;
370 	}
371 	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
372 	radeon_ring_unlock_commit(rdev, ringB, false);
373 
374 	r = radeon_fence_wait(fence2, false);
375 	if (r) {
376 		DRM_ERROR("Failed to wait for sync fence 1\n");
377 		goto out_cleanup;
378 	}
379 
380 out_cleanup:
381 	radeon_semaphore_free(rdev, &semaphore, NULL);
382 
383 	if (fence1)
384 		radeon_fence_unref(&fence1);
385 
386 	if (fence2)
387 		radeon_fence_unref(&fence2);
388 
389 	if (r)
390 		printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
391 }
392 
393 static void radeon_test_ring_sync2(struct radeon_device *rdev,
394 			    struct radeon_ring *ringA,
395 			    struct radeon_ring *ringB,
396 			    struct radeon_ring *ringC)
397 {
398 	struct radeon_fence *fenceA = NULL, *fenceB = NULL;
399 	struct radeon_semaphore *semaphore = NULL;
400 	bool sigA, sigB;
401 	int i, r;
402 
403 	r = radeon_semaphore_create(rdev, &semaphore);
404 	if (r) {
405 		DRM_ERROR("Failed to create semaphore\n");
406 		goto out_cleanup;
407 	}
408 
409 	r = radeon_ring_lock(rdev, ringA, 64);
410 	if (r) {
411 		DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
412 		goto out_cleanup;
413 	}
414 	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
415 	radeon_ring_unlock_commit(rdev, ringA, false);
416 
417 	r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA);
418 	if (r)
419 		goto out_cleanup;
420 
421 	r = radeon_ring_lock(rdev, ringB, 64);
422 	if (r) {
423 		DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
424 		goto out_cleanup;
425 	}
426 	radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
427 	radeon_ring_unlock_commit(rdev, ringB, false);
428 	r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB);
429 	if (r)
430 		goto out_cleanup;
431 
432 	mdelay(1000);
433 
434 	if (radeon_fence_signaled(fenceA)) {
435 		DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
436 		goto out_cleanup;
437 	}
438 	if (radeon_fence_signaled(fenceB)) {
439 		DRM_ERROR("Fence B signaled without waiting for semaphore.\n");
440 		goto out_cleanup;
441 	}
442 
443 	r = radeon_ring_lock(rdev, ringC, 64);
444 	if (r) {
445 		DRM_ERROR("Failed to lock ring B %p\n", ringC);
446 		goto out_cleanup;
447 	}
448 	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
449 	radeon_ring_unlock_commit(rdev, ringC, false);
450 
451 	for (i = 0; i < 30; ++i) {
452 		mdelay(100);
453 		sigA = radeon_fence_signaled(fenceA);
454 		sigB = radeon_fence_signaled(fenceB);
455 		if (sigA || sigB)
456 			break;
457 	}
458 
459 	if (!sigA && !sigB) {
460 		DRM_ERROR("Neither fence A nor B has been signaled\n");
461 		goto out_cleanup;
462 	} else if (sigA && sigB) {
463 		DRM_ERROR("Both fence A and B has been signaled\n");
464 		goto out_cleanup;
465 	}
466 
467 	DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B');
468 
469 	r = radeon_ring_lock(rdev, ringC, 64);
470 	if (r) {
471 		DRM_ERROR("Failed to lock ring B %p\n", ringC);
472 		goto out_cleanup;
473 	}
474 	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
475 	radeon_ring_unlock_commit(rdev, ringC, false);
476 
477 	mdelay(1000);
478 
479 	r = radeon_fence_wait(fenceA, false);
480 	if (r) {
481 		DRM_ERROR("Failed to wait for sync fence A\n");
482 		goto out_cleanup;
483 	}
484 	r = radeon_fence_wait(fenceB, false);
485 	if (r) {
486 		DRM_ERROR("Failed to wait for sync fence B\n");
487 		goto out_cleanup;
488 	}
489 
490 out_cleanup:
491 	radeon_semaphore_free(rdev, &semaphore, NULL);
492 
493 	if (fenceA)
494 		radeon_fence_unref(&fenceA);
495 
496 	if (fenceB)
497 		radeon_fence_unref(&fenceB);
498 
499 	if (r)
500 		printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
501 }
502 
503 static bool radeon_test_sync_possible(struct radeon_ring *ringA,
504 				      struct radeon_ring *ringB)
505 {
506 	if (ringA->idx == TN_RING_TYPE_VCE2_INDEX &&
507 	    ringB->idx == TN_RING_TYPE_VCE1_INDEX)
508 		return false;
509 
510 	return true;
511 }
512 
513 void radeon_test_syncing(struct radeon_device *rdev)
514 {
515 	int i, j, k;
516 
517 	for (i = 1; i < RADEON_NUM_RINGS; ++i) {
518 		struct radeon_ring *ringA = &rdev->ring[i];
519 		if (!ringA->ready)
520 			continue;
521 
522 		for (j = 0; j < i; ++j) {
523 			struct radeon_ring *ringB = &rdev->ring[j];
524 			if (!ringB->ready)
525 				continue;
526 
527 			if (!radeon_test_sync_possible(ringA, ringB))
528 				continue;
529 
530 			DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
531 			radeon_test_ring_sync(rdev, ringA, ringB);
532 
533 			DRM_INFO("Testing syncing between rings %d and %d...\n", j, i);
534 			radeon_test_ring_sync(rdev, ringB, ringA);
535 
536 			for (k = 0; k < j; ++k) {
537 				struct radeon_ring *ringC = &rdev->ring[k];
538 				if (!ringC->ready)
539 					continue;
540 
541 				if (!radeon_test_sync_possible(ringA, ringC))
542 					continue;
543 
544 				if (!radeon_test_sync_possible(ringB, ringC))
545 					continue;
546 
547 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
548 				radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
549 
550 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j);
551 				radeon_test_ring_sync2(rdev, ringA, ringC, ringB);
552 
553 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k);
554 				radeon_test_ring_sync2(rdev, ringB, ringA, ringC);
555 
556 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i);
557 				radeon_test_ring_sync2(rdev, ringB, ringC, ringA);
558 
559 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j);
560 				radeon_test_ring_sync2(rdev, ringC, ringA, ringB);
561 
562 				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i);
563 				radeon_test_ring_sync2(rdev, ringC, ringB, ringA);
564 			}
565 		}
566 	}
567 }
568