1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2009 VMware, Inc.
3254885Sdumbbell *
4254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
5254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
6254885Sdumbbell * to deal in the Software without restriction, including without limitation
7254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
9254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
10254885Sdumbbell *
11254885Sdumbbell * The above copyright notice and this permission notice shall be included in
12254885Sdumbbell * all copies or substantial portions of the Software.
13254885Sdumbbell *
14254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
21254885Sdumbbell *
22254885Sdumbbell * Authors: Michel D��nzer
23254885Sdumbbell */
24254885Sdumbbell
25254885Sdumbbell#include <sys/cdefs.h>
26254885Sdumbbell__FBSDID("$FreeBSD$");
27254885Sdumbbell
28254885Sdumbbell#include <dev/drm2/drmP.h>
29254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
30254885Sdumbbell#include "radeon_reg.h"
31254885Sdumbbell#include "radeon.h"
32254885Sdumbbell
33254885Sdumbbell#define RADEON_TEST_COPY_BLIT 1
34254885Sdumbbell#define RADEON_TEST_COPY_DMA  0
35254885Sdumbbell
36254885Sdumbbell
37254885Sdumbbell/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
38254885Sdumbbellstatic void radeon_do_test_moves(struct radeon_device *rdev, int flag)
39254885Sdumbbell{
40254885Sdumbbell	struct radeon_bo *vram_obj = NULL;
41254885Sdumbbell	struct radeon_bo **gtt_obj = NULL;
42254885Sdumbbell	struct radeon_fence *fence = NULL;
43254885Sdumbbell	uint64_t gtt_addr, vram_addr;
44254885Sdumbbell	unsigned i, n, size;
45254885Sdumbbell	int r, ring;
46254885Sdumbbell
47254885Sdumbbell	switch (flag) {
48254885Sdumbbell	case RADEON_TEST_COPY_DMA:
49254885Sdumbbell		ring = radeon_copy_dma_ring_index(rdev);
50254885Sdumbbell		break;
51254885Sdumbbell	case RADEON_TEST_COPY_BLIT:
52254885Sdumbbell		ring = radeon_copy_blit_ring_index(rdev);
53254885Sdumbbell		break;
54254885Sdumbbell	default:
55254885Sdumbbell		DRM_ERROR("Unknown copy method\n");
56254885Sdumbbell		return;
57254885Sdumbbell	}
58254885Sdumbbell
59254885Sdumbbell	size = 1024 * 1024;
60254885Sdumbbell
61254885Sdumbbell	/* Number of tests =
62254885Sdumbbell	 * (Total GTT - IB pool - writeback page - ring buffers) / test size
63254885Sdumbbell	 */
64254885Sdumbbell	n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024;
65254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i)
66254885Sdumbbell		n -= rdev->ring[i].ring_size;
67254885Sdumbbell	if (rdev->wb.wb_obj)
68254885Sdumbbell		n -= RADEON_GPU_PAGE_SIZE;
69254885Sdumbbell	if (rdev->ih.ring_obj)
70254885Sdumbbell		n -= rdev->ih.ring_size;
71254885Sdumbbell	n /= size;
72254885Sdumbbell
73280183Sdumbbell	gtt_obj = malloc(n * sizeof(*gtt_obj), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
74254885Sdumbbell	if (!gtt_obj) {
75254885Sdumbbell		DRM_ERROR("Failed to allocate %d pointers\n", n);
76254885Sdumbbell		r = 1;
77254885Sdumbbell		goto out_cleanup;
78254885Sdumbbell	}
79254885Sdumbbell
80254885Sdumbbell	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
81254885Sdumbbell			     NULL, &vram_obj);
82254885Sdumbbell	if (r) {
83254885Sdumbbell		DRM_ERROR("Failed to create VRAM object\n");
84254885Sdumbbell		goto out_cleanup;
85254885Sdumbbell	}
86254885Sdumbbell	r = radeon_bo_reserve(vram_obj, false);
87254885Sdumbbell	if (unlikely(r != 0))
88254885Sdumbbell		goto out_cleanup;
89254885Sdumbbell	r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
90254885Sdumbbell	if (r) {
91254885Sdumbbell		DRM_ERROR("Failed to pin VRAM object\n");
92254885Sdumbbell		goto out_cleanup;
93254885Sdumbbell	}
94254885Sdumbbell	for (i = 0; i < n; i++) {
95254885Sdumbbell		void *gtt_map, *vram_map;
96254885Sdumbbell		void **gtt_start, **gtt_end;
97254885Sdumbbell		void **vram_start, **vram_end;
98254885Sdumbbell
99254885Sdumbbell		r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
100254885Sdumbbell				     RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i);
101254885Sdumbbell		if (r) {
102254885Sdumbbell			DRM_ERROR("Failed to create GTT object %d\n", i);
103254885Sdumbbell			goto out_cleanup;
104254885Sdumbbell		}
105254885Sdumbbell
106254885Sdumbbell		r = radeon_bo_reserve(gtt_obj[i], false);
107254885Sdumbbell		if (unlikely(r != 0))
108254885Sdumbbell			goto out_cleanup;
109254885Sdumbbell		r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
110254885Sdumbbell		if (r) {
111254885Sdumbbell			DRM_ERROR("Failed to pin GTT object %d\n", i);
112254885Sdumbbell			goto out_cleanup;
113254885Sdumbbell		}
114254885Sdumbbell
115254885Sdumbbell		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
116254885Sdumbbell		if (r) {
117254885Sdumbbell			DRM_ERROR("Failed to map GTT object %d\n", i);
118254885Sdumbbell			goto out_cleanup;
119254885Sdumbbell		}
120254885Sdumbbell
121254885Sdumbbell		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size);
122254885Sdumbbell		     gtt_start < gtt_end;
123254885Sdumbbell		     gtt_start++)
124254885Sdumbbell			*gtt_start = gtt_start;
125254885Sdumbbell
126254885Sdumbbell		radeon_bo_kunmap(gtt_obj[i]);
127254885Sdumbbell
128254885Sdumbbell		if (ring == R600_RING_TYPE_DMA_INDEX)
129254885Sdumbbell			r = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
130254885Sdumbbell		else
131254885Sdumbbell			r = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
132254885Sdumbbell		if (r) {
133254885Sdumbbell			DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
134254885Sdumbbell			goto out_cleanup;
135254885Sdumbbell		}
136254885Sdumbbell
137254885Sdumbbell		r = radeon_fence_wait(fence, false);
138254885Sdumbbell		if (r) {
139254885Sdumbbell			DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
140254885Sdumbbell			goto out_cleanup;
141254885Sdumbbell		}
142254885Sdumbbell
143254885Sdumbbell		radeon_fence_unref(&fence);
144254885Sdumbbell
145254885Sdumbbell		r = radeon_bo_kmap(vram_obj, &vram_map);
146254885Sdumbbell		if (r) {
147254885Sdumbbell			DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
148254885Sdumbbell			goto out_cleanup;
149254885Sdumbbell		}
150254885Sdumbbell
151254885Sdumbbell		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size),
152254885Sdumbbell		     vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size);
153254885Sdumbbell		     vram_start < vram_end;
154254885Sdumbbell		     gtt_start++, vram_start++) {
155254885Sdumbbell			if (*vram_start != gtt_start) {
156254885Sdumbbell				DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
157254885Sdumbbell					  "expected 0x%p (GTT/VRAM offset "
158254885Sdumbbell					  "0x%16llx/0x%16llx)\n",
159254885Sdumbbell					  i, *vram_start, gtt_start,
160254885Sdumbbell					  (unsigned long long)
161254885Sdumbbell					  ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start +
162254885Sdumbbell					   (uintptr_t)gtt_start - (uintptr_t)gtt_map),
163254885Sdumbbell					  (unsigned long long)
164254885Sdumbbell					  ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start +
165254885Sdumbbell					   (uintptr_t)gtt_start - (uintptr_t)gtt_map));
166254885Sdumbbell				radeon_bo_kunmap(vram_obj);
167254885Sdumbbell				goto out_cleanup;
168254885Sdumbbell			}
169254885Sdumbbell			*vram_start = vram_start;
170254885Sdumbbell		}
171254885Sdumbbell
172254885Sdumbbell		radeon_bo_kunmap(vram_obj);
173254885Sdumbbell
174254885Sdumbbell		if (ring == R600_RING_TYPE_DMA_INDEX)
175254885Sdumbbell			r = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
176254885Sdumbbell		else
177254885Sdumbbell			r = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence);
178254885Sdumbbell		if (r) {
179254885Sdumbbell			DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
180254885Sdumbbell			goto out_cleanup;
181254885Sdumbbell		}
182254885Sdumbbell
183254885Sdumbbell		r = radeon_fence_wait(fence, false);
184254885Sdumbbell		if (r) {
185254885Sdumbbell			DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
186254885Sdumbbell			goto out_cleanup;
187254885Sdumbbell		}
188254885Sdumbbell
189254885Sdumbbell		radeon_fence_unref(&fence);
190254885Sdumbbell
191254885Sdumbbell		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
192254885Sdumbbell		if (r) {
193254885Sdumbbell			DRM_ERROR("Failed to map GTT object after copy %d\n", i);
194254885Sdumbbell			goto out_cleanup;
195254885Sdumbbell		}
196254885Sdumbbell
197254885Sdumbbell		for (gtt_start = gtt_map, gtt_end = (void *)((uintptr_t)gtt_map + size),
198254885Sdumbbell		     vram_start = vram_map, vram_end = (void *)((uintptr_t)vram_map + size);
199254885Sdumbbell		     gtt_start < gtt_end;
200254885Sdumbbell		     gtt_start++, vram_start++) {
201254885Sdumbbell			if (*gtt_start != vram_start) {
202254885Sdumbbell				DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
203254885Sdumbbell					  "expected 0x%p (VRAM/GTT offset "
204254885Sdumbbell					  "0x%16llx/0x%16llx)\n",
205254885Sdumbbell					  i, *gtt_start, vram_start,
206254885Sdumbbell					  (unsigned long long)
207254885Sdumbbell					  ((uintptr_t)vram_addr - (uintptr_t)rdev->mc.vram_start +
208254885Sdumbbell					   (uintptr_t)vram_start - (uintptr_t)vram_map),
209254885Sdumbbell					  (unsigned long long)
210254885Sdumbbell					  ((uintptr_t)gtt_addr - (uintptr_t)rdev->mc.gtt_start +
211254885Sdumbbell					   (uintptr_t)vram_start - (uintptr_t)vram_map));
212254885Sdumbbell				radeon_bo_kunmap(gtt_obj[i]);
213254885Sdumbbell				goto out_cleanup;
214254885Sdumbbell			}
215254885Sdumbbell		}
216254885Sdumbbell
217254885Sdumbbell		radeon_bo_kunmap(gtt_obj[i]);
218254885Sdumbbell
219254885Sdumbbell		DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%jx\n",
220254885Sdumbbell			 (uintmax_t)gtt_addr - rdev->mc.gtt_start);
221254885Sdumbbell	}
222254885Sdumbbell
223254885Sdumbbellout_cleanup:
224254885Sdumbbell	if (vram_obj) {
225254885Sdumbbell		if (radeon_bo_is_reserved(vram_obj)) {
226254885Sdumbbell			radeon_bo_unpin(vram_obj);
227254885Sdumbbell			radeon_bo_unreserve(vram_obj);
228254885Sdumbbell		}
229254885Sdumbbell		radeon_bo_unref(&vram_obj);
230254885Sdumbbell	}
231254885Sdumbbell	if (gtt_obj) {
232254885Sdumbbell		for (i = 0; i < n; i++) {
233254885Sdumbbell			if (gtt_obj[i]) {
234254885Sdumbbell				if (radeon_bo_is_reserved(gtt_obj[i])) {
235254885Sdumbbell					radeon_bo_unpin(gtt_obj[i]);
236254885Sdumbbell					radeon_bo_unreserve(gtt_obj[i]);
237254885Sdumbbell				}
238254885Sdumbbell				radeon_bo_unref(&gtt_obj[i]);
239254885Sdumbbell			}
240254885Sdumbbell		}
241254885Sdumbbell		free(gtt_obj, DRM_MEM_DRIVER);
242254885Sdumbbell	}
243254885Sdumbbell	if (fence) {
244254885Sdumbbell		radeon_fence_unref(&fence);
245254885Sdumbbell	}
246254885Sdumbbell	if (r) {
247254885Sdumbbell		DRM_ERROR("Error while testing BO move.\n");
248254885Sdumbbell	}
249254885Sdumbbell}
250254885Sdumbbell
251254885Sdumbbellvoid radeon_test_moves(struct radeon_device *rdev)
252254885Sdumbbell{
253254885Sdumbbell	if (rdev->asic->copy.dma)
254254885Sdumbbell		radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA);
255254885Sdumbbell	if (rdev->asic->copy.blit)
256254885Sdumbbell		radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT);
257254885Sdumbbell}
258254885Sdumbbell
259254885Sdumbbellvoid radeon_test_ring_sync(struct radeon_device *rdev,
260254885Sdumbbell			   struct radeon_ring *ringA,
261254885Sdumbbell			   struct radeon_ring *ringB)
262254885Sdumbbell{
263254885Sdumbbell	struct radeon_fence *fence1 = NULL, *fence2 = NULL;
264254885Sdumbbell	struct radeon_semaphore *semaphore = NULL;
265254885Sdumbbell	int r;
266254885Sdumbbell
267254885Sdumbbell	r = radeon_semaphore_create(rdev, &semaphore);
268254885Sdumbbell	if (r) {
269254885Sdumbbell		DRM_ERROR("Failed to create semaphore\n");
270254885Sdumbbell		goto out_cleanup;
271254885Sdumbbell	}
272254885Sdumbbell
273254885Sdumbbell	r = radeon_ring_lock(rdev, ringA, 64);
274254885Sdumbbell	if (r) {
275254885Sdumbbell		DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
276254885Sdumbbell		goto out_cleanup;
277254885Sdumbbell	}
278254885Sdumbbell	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
279254885Sdumbbell	r = radeon_fence_emit(rdev, &fence1, ringA->idx);
280254885Sdumbbell	if (r) {
281254885Sdumbbell		DRM_ERROR("Failed to emit fence 1\n");
282254885Sdumbbell		radeon_ring_unlock_undo(rdev, ringA);
283254885Sdumbbell		goto out_cleanup;
284254885Sdumbbell	}
285254885Sdumbbell	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
286254885Sdumbbell	r = radeon_fence_emit(rdev, &fence2, ringA->idx);
287254885Sdumbbell	if (r) {
288254885Sdumbbell		DRM_ERROR("Failed to emit fence 2\n");
289254885Sdumbbell		radeon_ring_unlock_undo(rdev, ringA);
290254885Sdumbbell		goto out_cleanup;
291254885Sdumbbell	}
292254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringA);
293254885Sdumbbell
294280183Sdumbbell	mdelay(1000);
295254885Sdumbbell
296254885Sdumbbell	if (radeon_fence_signaled(fence1)) {
297254885Sdumbbell		DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n");
298254885Sdumbbell		goto out_cleanup;
299254885Sdumbbell	}
300254885Sdumbbell
301254885Sdumbbell	r = radeon_ring_lock(rdev, ringB, 64);
302254885Sdumbbell	if (r) {
303254885Sdumbbell		DRM_ERROR("Failed to lock ring B %p\n", ringB);
304254885Sdumbbell		goto out_cleanup;
305254885Sdumbbell	}
306254885Sdumbbell	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
307254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringB);
308254885Sdumbbell
309254885Sdumbbell	r = radeon_fence_wait(fence1, false);
310254885Sdumbbell	if (r) {
311254885Sdumbbell		DRM_ERROR("Failed to wait for sync fence 1\n");
312254885Sdumbbell		goto out_cleanup;
313254885Sdumbbell	}
314254885Sdumbbell
315280183Sdumbbell	mdelay(1000);
316254885Sdumbbell
317254885Sdumbbell	if (radeon_fence_signaled(fence2)) {
318254885Sdumbbell		DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n");
319254885Sdumbbell		goto out_cleanup;
320254885Sdumbbell	}
321254885Sdumbbell
322254885Sdumbbell	r = radeon_ring_lock(rdev, ringB, 64);
323254885Sdumbbell	if (r) {
324254885Sdumbbell		DRM_ERROR("Failed to lock ring B %p\n", ringB);
325254885Sdumbbell		goto out_cleanup;
326254885Sdumbbell	}
327254885Sdumbbell	radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
328254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringB);
329254885Sdumbbell
330254885Sdumbbell	r = radeon_fence_wait(fence2, false);
331254885Sdumbbell	if (r) {
332254885Sdumbbell		DRM_ERROR("Failed to wait for sync fence 1\n");
333254885Sdumbbell		goto out_cleanup;
334254885Sdumbbell	}
335254885Sdumbbell
336254885Sdumbbellout_cleanup:
337254885Sdumbbell	radeon_semaphore_free(rdev, &semaphore, NULL);
338254885Sdumbbell
339254885Sdumbbell	if (fence1)
340254885Sdumbbell		radeon_fence_unref(&fence1);
341254885Sdumbbell
342254885Sdumbbell	if (fence2)
343254885Sdumbbell		radeon_fence_unref(&fence2);
344254885Sdumbbell
345254885Sdumbbell	if (r)
346254885Sdumbbell		DRM_ERROR("Error while testing ring sync (%d).\n", r);
347254885Sdumbbell}
348254885Sdumbbell
349254885Sdumbbellstatic void radeon_test_ring_sync2(struct radeon_device *rdev,
350254885Sdumbbell			    struct radeon_ring *ringA,
351254885Sdumbbell			    struct radeon_ring *ringB,
352254885Sdumbbell			    struct radeon_ring *ringC)
353254885Sdumbbell{
354254885Sdumbbell	struct radeon_fence *fenceA = NULL, *fenceB = NULL;
355254885Sdumbbell	struct radeon_semaphore *semaphore = NULL;
356254885Sdumbbell	bool sigA, sigB;
357254885Sdumbbell	int i, r;
358254885Sdumbbell
359254885Sdumbbell	r = radeon_semaphore_create(rdev, &semaphore);
360254885Sdumbbell	if (r) {
361254885Sdumbbell		DRM_ERROR("Failed to create semaphore\n");
362254885Sdumbbell		goto out_cleanup;
363254885Sdumbbell	}
364254885Sdumbbell
365254885Sdumbbell	r = radeon_ring_lock(rdev, ringA, 64);
366254885Sdumbbell	if (r) {
367254885Sdumbbell		DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
368254885Sdumbbell		goto out_cleanup;
369254885Sdumbbell	}
370254885Sdumbbell	radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
371254885Sdumbbell	r = radeon_fence_emit(rdev, &fenceA, ringA->idx);
372254885Sdumbbell	if (r) {
373254885Sdumbbell		DRM_ERROR("Failed to emit sync fence 1\n");
374254885Sdumbbell		radeon_ring_unlock_undo(rdev, ringA);
375254885Sdumbbell		goto out_cleanup;
376254885Sdumbbell	}
377254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringA);
378254885Sdumbbell
379254885Sdumbbell	r = radeon_ring_lock(rdev, ringB, 64);
380254885Sdumbbell	if (r) {
381254885Sdumbbell		DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
382254885Sdumbbell		goto out_cleanup;
383254885Sdumbbell	}
384254885Sdumbbell	radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
385254885Sdumbbell	r = radeon_fence_emit(rdev, &fenceB, ringB->idx);
386254885Sdumbbell	if (r) {
387254885Sdumbbell		DRM_ERROR("Failed to create sync fence 2\n");
388254885Sdumbbell		radeon_ring_unlock_undo(rdev, ringB);
389254885Sdumbbell		goto out_cleanup;
390254885Sdumbbell	}
391254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringB);
392254885Sdumbbell
393280183Sdumbbell	mdelay(1000);
394254885Sdumbbell
395254885Sdumbbell	if (radeon_fence_signaled(fenceA)) {
396254885Sdumbbell		DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
397254885Sdumbbell		goto out_cleanup;
398254885Sdumbbell	}
399254885Sdumbbell	if (radeon_fence_signaled(fenceB)) {
400254885Sdumbbell		DRM_ERROR("Fence A signaled without waiting for semaphore.\n");
401254885Sdumbbell		goto out_cleanup;
402254885Sdumbbell	}
403254885Sdumbbell
404254885Sdumbbell	r = radeon_ring_lock(rdev, ringC, 64);
405254885Sdumbbell	if (r) {
406254885Sdumbbell		DRM_ERROR("Failed to lock ring B %p\n", ringC);
407254885Sdumbbell		goto out_cleanup;
408254885Sdumbbell	}
409254885Sdumbbell	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
410254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringC);
411254885Sdumbbell
412254885Sdumbbell	for (i = 0; i < 30; ++i) {
413280183Sdumbbell		mdelay(100);
414254885Sdumbbell		sigA = radeon_fence_signaled(fenceA);
415254885Sdumbbell		sigB = radeon_fence_signaled(fenceB);
416254885Sdumbbell		if (sigA || sigB)
417254885Sdumbbell			break;
418254885Sdumbbell	}
419254885Sdumbbell
420254885Sdumbbell	if (!sigA && !sigB) {
421254885Sdumbbell		DRM_ERROR("Neither fence A nor B has been signaled\n");
422254885Sdumbbell		goto out_cleanup;
423254885Sdumbbell	} else if (sigA && sigB) {
424254885Sdumbbell		DRM_ERROR("Both fence A and B has been signaled\n");
425254885Sdumbbell		goto out_cleanup;
426254885Sdumbbell	}
427254885Sdumbbell
428254885Sdumbbell	DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B');
429254885Sdumbbell
430254885Sdumbbell	r = radeon_ring_lock(rdev, ringC, 64);
431254885Sdumbbell	if (r) {
432254885Sdumbbell		DRM_ERROR("Failed to lock ring B %p\n", ringC);
433254885Sdumbbell		goto out_cleanup;
434254885Sdumbbell	}
435254885Sdumbbell	radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
436254885Sdumbbell	radeon_ring_unlock_commit(rdev, ringC);
437254885Sdumbbell
438280183Sdumbbell	mdelay(1000);
439254885Sdumbbell
440254885Sdumbbell	r = radeon_fence_wait(fenceA, false);
441254885Sdumbbell	if (r) {
442254885Sdumbbell		DRM_ERROR("Failed to wait for sync fence A\n");
443254885Sdumbbell		goto out_cleanup;
444254885Sdumbbell	}
445254885Sdumbbell	r = radeon_fence_wait(fenceB, false);
446254885Sdumbbell	if (r) {
447254885Sdumbbell		DRM_ERROR("Failed to wait for sync fence B\n");
448254885Sdumbbell		goto out_cleanup;
449254885Sdumbbell	}
450254885Sdumbbell
451254885Sdumbbellout_cleanup:
452254885Sdumbbell	radeon_semaphore_free(rdev, &semaphore, NULL);
453254885Sdumbbell
454254885Sdumbbell	if (fenceA)
455254885Sdumbbell		radeon_fence_unref(&fenceA);
456254885Sdumbbell
457254885Sdumbbell	if (fenceB)
458254885Sdumbbell		radeon_fence_unref(&fenceB);
459254885Sdumbbell
460254885Sdumbbell	if (r)
461254885Sdumbbell		DRM_ERROR("Error while testing ring sync (%d).\n", r);
462254885Sdumbbell}
463254885Sdumbbell
464254885Sdumbbellvoid radeon_test_syncing(struct radeon_device *rdev)
465254885Sdumbbell{
466254885Sdumbbell	int i, j, k;
467254885Sdumbbell
468254885Sdumbbell	for (i = 1; i < RADEON_NUM_RINGS; ++i) {
469254885Sdumbbell		struct radeon_ring *ringA = &rdev->ring[i];
470254885Sdumbbell		if (!ringA->ready)
471254885Sdumbbell			continue;
472254885Sdumbbell
473254885Sdumbbell		for (j = 0; j < i; ++j) {
474254885Sdumbbell			struct radeon_ring *ringB = &rdev->ring[j];
475254885Sdumbbell			if (!ringB->ready)
476254885Sdumbbell				continue;
477254885Sdumbbell
478254885Sdumbbell			DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
479254885Sdumbbell			radeon_test_ring_sync(rdev, ringA, ringB);
480254885Sdumbbell
481254885Sdumbbell			DRM_INFO("Testing syncing between rings %d and %d...\n", j, i);
482254885Sdumbbell			radeon_test_ring_sync(rdev, ringB, ringA);
483254885Sdumbbell
484254885Sdumbbell			for (k = 0; k < j; ++k) {
485254885Sdumbbell				struct radeon_ring *ringC = &rdev->ring[k];
486254885Sdumbbell				if (!ringC->ready)
487254885Sdumbbell					continue;
488254885Sdumbbell
489254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
490254885Sdumbbell				radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
491254885Sdumbbell
492254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j);
493254885Sdumbbell				radeon_test_ring_sync2(rdev, ringA, ringC, ringB);
494254885Sdumbbell
495254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k);
496254885Sdumbbell				radeon_test_ring_sync2(rdev, ringB, ringA, ringC);
497254885Sdumbbell
498254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i);
499254885Sdumbbell				radeon_test_ring_sync2(rdev, ringB, ringC, ringA);
500254885Sdumbbell
501254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j);
502254885Sdumbbell				radeon_test_ring_sync2(rdev, ringC, ringA, ringB);
503254885Sdumbbell
504254885Sdumbbell				DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i);
505254885Sdumbbell				radeon_test_ring_sync2(rdev, ringC, ringB, ringA);
506254885Sdumbbell			}
507254885Sdumbbell		}
508254885Sdumbbell	}
509254885Sdumbbell}
510