1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2009 Jerome Glisse.
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: Jerome Glisse
23254885Sdumbbell */
24254885Sdumbbell
25254885Sdumbbell#include <sys/cdefs.h>
26254885Sdumbbell__FBSDID("$FreeBSD: releng/10.2/sys/dev/drm2/radeon/radeon_benchmark.c 282199 2015-04-28 19:35:05Z dumbbell $");
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_BENCHMARK_COPY_BLIT 1
34254885Sdumbbell#define RADEON_BENCHMARK_COPY_DMA  0
35254885Sdumbbell
36254885Sdumbbell#define RADEON_BENCHMARK_ITERATIONS 1024
37254885Sdumbbell#define RADEON_BENCHMARK_COMMON_MODES_N 17
38254885Sdumbbell
39254885Sdumbbellstatic int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size,
40254885Sdumbbell				    uint64_t saddr, uint64_t daddr,
41254885Sdumbbell				    int flag, int n)
42254885Sdumbbell{
43254885Sdumbbell	unsigned long start_jiffies;
44254885Sdumbbell	unsigned long end_jiffies;
45254885Sdumbbell	struct radeon_fence *fence = NULL;
46254885Sdumbbell	int i, r;
47254885Sdumbbell
48254885Sdumbbell	start_jiffies = jiffies;
49254885Sdumbbell	for (i = 0; i < n; i++) {
50254885Sdumbbell		switch (flag) {
51254885Sdumbbell		case RADEON_BENCHMARK_COPY_DMA:
52254885Sdumbbell			r = radeon_copy_dma(rdev, saddr, daddr,
53254885Sdumbbell					    size / RADEON_GPU_PAGE_SIZE,
54254885Sdumbbell					    &fence);
55254885Sdumbbell			break;
56254885Sdumbbell		case RADEON_BENCHMARK_COPY_BLIT:
57254885Sdumbbell			r = radeon_copy_blit(rdev, saddr, daddr,
58254885Sdumbbell					     size / RADEON_GPU_PAGE_SIZE,
59254885Sdumbbell					     &fence);
60254885Sdumbbell			break;
61254885Sdumbbell		default:
62254885Sdumbbell			DRM_ERROR("Unknown copy method\n");
63254885Sdumbbell			r = -EINVAL;
64254885Sdumbbell		}
65254885Sdumbbell		if (r)
66254885Sdumbbell			goto exit_do_move;
67254885Sdumbbell		r = radeon_fence_wait(fence, false);
68254885Sdumbbell		if (r)
69254885Sdumbbell			goto exit_do_move;
70254885Sdumbbell		radeon_fence_unref(&fence);
71254885Sdumbbell	}
72254885Sdumbbell	end_jiffies = jiffies;
73254885Sdumbbell	r = jiffies_to_msecs(end_jiffies - start_jiffies);
74254885Sdumbbell
75254885Sdumbbellexit_do_move:
76254885Sdumbbell	if (fence)
77254885Sdumbbell		radeon_fence_unref(&fence);
78254885Sdumbbell	return r;
79254885Sdumbbell}
80254885Sdumbbell
81254885Sdumbbell
82254885Sdumbbellstatic void radeon_benchmark_log_results(int n, unsigned size,
83254885Sdumbbell					 unsigned int time,
84254885Sdumbbell					 unsigned sdomain, unsigned ddomain,
85254885Sdumbbell					 char *kind)
86254885Sdumbbell{
87254885Sdumbbell	unsigned int throughput = (n * (size >> 10)) / time;
88254885Sdumbbell	DRM_INFO("radeon: %s %u bo moves of %u kB from"
89254885Sdumbbell		 " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n",
90254885Sdumbbell		 kind, n, size >> 10, sdomain, ddomain, time,
91254885Sdumbbell		 throughput * 8, throughput);
92254885Sdumbbell}
93254885Sdumbbell
94254885Sdumbbellstatic void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
95254885Sdumbbell				  unsigned sdomain, unsigned ddomain)
96254885Sdumbbell{
97254885Sdumbbell	struct radeon_bo *dobj = NULL;
98254885Sdumbbell	struct radeon_bo *sobj = NULL;
99254885Sdumbbell	uint64_t saddr, daddr;
100254885Sdumbbell	int r, n;
101254885Sdumbbell	int time;
102254885Sdumbbell
103254885Sdumbbell	n = RADEON_BENCHMARK_ITERATIONS;
104254885Sdumbbell	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, NULL, &sobj);
105254885Sdumbbell	if (r) {
106254885Sdumbbell		goto out_cleanup;
107254885Sdumbbell	}
108254885Sdumbbell	r = radeon_bo_reserve(sobj, false);
109254885Sdumbbell	if (unlikely(r != 0))
110254885Sdumbbell		goto out_cleanup;
111254885Sdumbbell	r = radeon_bo_pin(sobj, sdomain, &saddr);
112254885Sdumbbell	radeon_bo_unreserve(sobj);
113254885Sdumbbell	if (r) {
114254885Sdumbbell		goto out_cleanup;
115254885Sdumbbell	}
116254885Sdumbbell	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, NULL, &dobj);
117254885Sdumbbell	if (r) {
118254885Sdumbbell		goto out_cleanup;
119254885Sdumbbell	}
120254885Sdumbbell	r = radeon_bo_reserve(dobj, false);
121254885Sdumbbell	if (unlikely(r != 0))
122254885Sdumbbell		goto out_cleanup;
123254885Sdumbbell	r = radeon_bo_pin(dobj, ddomain, &daddr);
124254885Sdumbbell	radeon_bo_unreserve(dobj);
125254885Sdumbbell	if (r) {
126254885Sdumbbell		goto out_cleanup;
127254885Sdumbbell	}
128254885Sdumbbell
129254885Sdumbbell	/* r100 doesn't have dma engine so skip the test */
130254885Sdumbbell	/* also, VRAM-to-VRAM test doesn't make much sense for DMA */
131254885Sdumbbell	/* skip it as well if domains are the same */
132254885Sdumbbell	if ((rdev->asic->copy.dma) && (sdomain != ddomain)) {
133254885Sdumbbell		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
134254885Sdumbbell						RADEON_BENCHMARK_COPY_DMA, n);
135254885Sdumbbell		if (time < 0)
136254885Sdumbbell			goto out_cleanup;
137254885Sdumbbell		if (time > 0)
138254885Sdumbbell			radeon_benchmark_log_results(n, size, time,
139254885Sdumbbell						     sdomain, ddomain, "dma");
140254885Sdumbbell	}
141254885Sdumbbell
142282199Sdumbbell	if (rdev->asic->copy.blit) {
143282199Sdumbbell		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
144282199Sdumbbell						RADEON_BENCHMARK_COPY_BLIT, n);
145282199Sdumbbell		if (time < 0)
146282199Sdumbbell			goto out_cleanup;
147282199Sdumbbell		if (time > 0)
148282199Sdumbbell			radeon_benchmark_log_results(n, size, time,
149282199Sdumbbell						     sdomain, ddomain, "blit");
150282199Sdumbbell	}
151254885Sdumbbell
152254885Sdumbbellout_cleanup:
153254885Sdumbbell	if (sobj) {
154254885Sdumbbell		r = radeon_bo_reserve(sobj, false);
155254885Sdumbbell		if (likely(r == 0)) {
156254885Sdumbbell			radeon_bo_unpin(sobj);
157254885Sdumbbell			radeon_bo_unreserve(sobj);
158254885Sdumbbell		}
159254885Sdumbbell		radeon_bo_unref(&sobj);
160254885Sdumbbell	}
161254885Sdumbbell	if (dobj) {
162254885Sdumbbell		r = radeon_bo_reserve(dobj, false);
163254885Sdumbbell		if (likely(r == 0)) {
164254885Sdumbbell			radeon_bo_unpin(dobj);
165254885Sdumbbell			radeon_bo_unreserve(dobj);
166254885Sdumbbell		}
167254885Sdumbbell		radeon_bo_unref(&dobj);
168254885Sdumbbell	}
169254885Sdumbbell
170254885Sdumbbell	if (r) {
171254885Sdumbbell		DRM_ERROR("Error while benchmarking BO move.\n");
172254885Sdumbbell	}
173254885Sdumbbell}
174254885Sdumbbell
175254885Sdumbbellvoid radeon_benchmark(struct radeon_device *rdev, int test_number)
176254885Sdumbbell{
177254885Sdumbbell	int i;
178254885Sdumbbell	int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = {
179254885Sdumbbell		640 * 480 * 4,
180254885Sdumbbell		720 * 480 * 4,
181254885Sdumbbell		800 * 600 * 4,
182254885Sdumbbell		848 * 480 * 4,
183254885Sdumbbell		1024 * 768 * 4,
184254885Sdumbbell		1152 * 768 * 4,
185254885Sdumbbell		1280 * 720 * 4,
186254885Sdumbbell		1280 * 800 * 4,
187254885Sdumbbell		1280 * 854 * 4,
188254885Sdumbbell		1280 * 960 * 4,
189254885Sdumbbell		1280 * 1024 * 4,
190254885Sdumbbell		1440 * 900 * 4,
191254885Sdumbbell		1400 * 1050 * 4,
192254885Sdumbbell		1680 * 1050 * 4,
193254885Sdumbbell		1600 * 1200 * 4,
194254885Sdumbbell		1920 * 1080 * 4,
195254885Sdumbbell		1920 * 1200 * 4
196254885Sdumbbell	};
197254885Sdumbbell
198254885Sdumbbell	switch (test_number) {
199254885Sdumbbell	case 1:
200254885Sdumbbell		/* simple test, VRAM to GTT and GTT to VRAM */
201254885Sdumbbell		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
202254885Sdumbbell				      RADEON_GEM_DOMAIN_VRAM);
203254885Sdumbbell		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
204254885Sdumbbell				      RADEON_GEM_DOMAIN_GTT);
205254885Sdumbbell		break;
206254885Sdumbbell	case 2:
207254885Sdumbbell		/* simple test, VRAM to VRAM */
208254885Sdumbbell		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
209254885Sdumbbell				      RADEON_GEM_DOMAIN_VRAM);
210254885Sdumbbell		break;
211254885Sdumbbell	case 3:
212254885Sdumbbell		/* GTT to VRAM, buffer size sweep, powers of 2 */
213254885Sdumbbell		for (i = 1; i <= 16384; i <<= 1)
214254885Sdumbbell			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
215254885Sdumbbell					      RADEON_GEM_DOMAIN_GTT,
216254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM);
217254885Sdumbbell		break;
218254885Sdumbbell	case 4:
219254885Sdumbbell		/* VRAM to GTT, buffer size sweep, powers of 2 */
220254885Sdumbbell		for (i = 1; i <= 16384; i <<= 1)
221254885Sdumbbell			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
222254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM,
223254885Sdumbbell					      RADEON_GEM_DOMAIN_GTT);
224254885Sdumbbell		break;
225254885Sdumbbell	case 5:
226254885Sdumbbell		/* VRAM to VRAM, buffer size sweep, powers of 2 */
227254885Sdumbbell		for (i = 1; i <= 16384; i <<= 1)
228254885Sdumbbell			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
229254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM,
230254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM);
231254885Sdumbbell		break;
232254885Sdumbbell	case 6:
233254885Sdumbbell		/* GTT to VRAM, buffer size sweep, common modes */
234254885Sdumbbell		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
235254885Sdumbbell			radeon_benchmark_move(rdev, common_modes[i],
236254885Sdumbbell					      RADEON_GEM_DOMAIN_GTT,
237254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM);
238254885Sdumbbell		break;
239254885Sdumbbell	case 7:
240254885Sdumbbell		/* VRAM to GTT, buffer size sweep, common modes */
241254885Sdumbbell		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
242254885Sdumbbell			radeon_benchmark_move(rdev, common_modes[i],
243254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM,
244254885Sdumbbell					      RADEON_GEM_DOMAIN_GTT);
245254885Sdumbbell		break;
246254885Sdumbbell	case 8:
247254885Sdumbbell		/* VRAM to VRAM, buffer size sweep, common modes */
248254885Sdumbbell		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
249254885Sdumbbell			radeon_benchmark_move(rdev, common_modes[i],
250254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM,
251254885Sdumbbell					      RADEON_GEM_DOMAIN_VRAM);
252254885Sdumbbell		break;
253254885Sdumbbell
254254885Sdumbbell	default:
255254885Sdumbbell		DRM_ERROR("Unknown benchmark\n");
256254885Sdumbbell	}
257254885Sdumbbell}
258