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