1/*	$NetBSD: radeon_benchmark.c,v 1.4 2021/12/18 23:45:43 riastradh Exp $	*/
2
3/*
4 * Copyright 2009 Jerome Glisse.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Jerome Glisse
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: radeon_benchmark.c,v 1.4 2021/12/18 23:45:43 riastradh Exp $");
29
30#include <drm/radeon_drm.h>
31#include "radeon_reg.h"
32#include "radeon.h"
33
34#define RADEON_BENCHMARK_COPY_BLIT 1
35#define RADEON_BENCHMARK_COPY_DMA  0
36
37#define RADEON_BENCHMARK_ITERATIONS 1024
38#define RADEON_BENCHMARK_COMMON_MODES_N 17
39
40static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size,
41				    uint64_t saddr, uint64_t daddr,
42				    int flag, int n,
43				    struct dma_resv *resv)
44{
45	unsigned long start_jiffies;
46	unsigned long end_jiffies;
47	struct radeon_fence *fence = NULL;
48	int i, r;
49
50	start_jiffies = jiffies;
51	for (i = 0; i < n; i++) {
52		switch (flag) {
53		case RADEON_BENCHMARK_COPY_DMA:
54			fence = radeon_copy_dma(rdev, saddr, daddr,
55						size / RADEON_GPU_PAGE_SIZE,
56						resv);
57			break;
58		case RADEON_BENCHMARK_COPY_BLIT:
59			fence = radeon_copy_blit(rdev, saddr, daddr,
60						 size / RADEON_GPU_PAGE_SIZE,
61						 resv);
62			break;
63		default:
64			DRM_ERROR("Unknown copy method\n");
65			return -EINVAL;
66		}
67		if (IS_ERR(fence))
68			return PTR_ERR(fence);
69
70		r = radeon_fence_wait(fence, false);
71		radeon_fence_unref(&fence);
72		if (r)
73			return r;
74	}
75	end_jiffies = jiffies;
76	return jiffies_to_msecs(end_jiffies - start_jiffies);
77}
78
79
80static void radeon_benchmark_log_results(int n, unsigned size,
81					 unsigned int time,
82					 unsigned sdomain, unsigned ddomain,
83					 const char *kind)
84{
85	unsigned int throughput = (n * (size >> 10)) / time;
86	DRM_INFO("radeon: %s %u bo moves of %u kB from"
87		 " %d to %d in %u ms, throughput: %u Mb/s or %u MB/s\n",
88		 kind, n, size >> 10, sdomain, ddomain, time,
89		 throughput * 8, throughput);
90}
91
92static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
93				  unsigned sdomain, unsigned ddomain)
94{
95	struct radeon_bo *dobj = NULL;
96	struct radeon_bo *sobj = NULL;
97	uint64_t saddr, daddr;
98	int r, n;
99	int time;
100
101	n = RADEON_BENCHMARK_ITERATIONS;
102	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, 0, NULL, NULL, &sobj);
103	if (r) {
104		goto out_cleanup;
105	}
106	r = radeon_bo_reserve(sobj, false);
107	if (unlikely(r != 0))
108		goto out_cleanup;
109	r = radeon_bo_pin(sobj, sdomain, &saddr);
110	radeon_bo_unreserve(sobj);
111	if (r) {
112		goto out_cleanup;
113	}
114	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, 0, NULL, NULL, &dobj);
115	if (r) {
116		goto out_cleanup;
117	}
118	r = radeon_bo_reserve(dobj, false);
119	if (unlikely(r != 0))
120		goto out_cleanup;
121	r = radeon_bo_pin(dobj, ddomain, &daddr);
122	radeon_bo_unreserve(dobj);
123	if (r) {
124		goto out_cleanup;
125	}
126
127	if (rdev->asic->copy.dma) {
128		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
129						RADEON_BENCHMARK_COPY_DMA, n,
130						dobj->tbo.base.resv);
131		if (time < 0)
132			goto out_cleanup;
133		if (time > 0)
134			radeon_benchmark_log_results(n, size, time,
135						     sdomain, ddomain, "dma");
136	}
137
138	if (rdev->asic->copy.blit) {
139		time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
140						RADEON_BENCHMARK_COPY_BLIT, n,
141						dobj->tbo.base.resv);
142		if (time < 0)
143			goto out_cleanup;
144		if (time > 0)
145			radeon_benchmark_log_results(n, size, time,
146						     sdomain, ddomain, "blit");
147	}
148
149out_cleanup:
150	if (sobj) {
151		r = radeon_bo_reserve(sobj, false);
152		if (likely(r == 0)) {
153			radeon_bo_unpin(sobj);
154			radeon_bo_unreserve(sobj);
155		}
156		radeon_bo_unref(&sobj);
157	}
158	if (dobj) {
159		r = radeon_bo_reserve(dobj, false);
160		if (likely(r == 0)) {
161			radeon_bo_unpin(dobj);
162			radeon_bo_unreserve(dobj);
163		}
164		radeon_bo_unref(&dobj);
165	}
166
167	if (r) {
168		DRM_ERROR("Error while benchmarking BO move.\n");
169	}
170}
171
172void radeon_benchmark(struct radeon_device *rdev, int test_number)
173{
174	int i;
175	int common_modes[RADEON_BENCHMARK_COMMON_MODES_N] = {
176		640 * 480 * 4,
177		720 * 480 * 4,
178		800 * 600 * 4,
179		848 * 480 * 4,
180		1024 * 768 * 4,
181		1152 * 768 * 4,
182		1280 * 720 * 4,
183		1280 * 800 * 4,
184		1280 * 854 * 4,
185		1280 * 960 * 4,
186		1280 * 1024 * 4,
187		1440 * 900 * 4,
188		1400 * 1050 * 4,
189		1680 * 1050 * 4,
190		1600 * 1200 * 4,
191		1920 * 1080 * 4,
192		1920 * 1200 * 4
193	};
194
195	switch (test_number) {
196	case 1:
197		/* simple test, VRAM to GTT and GTT to VRAM */
198		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
199				      RADEON_GEM_DOMAIN_VRAM);
200		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
201				      RADEON_GEM_DOMAIN_GTT);
202		break;
203	case 2:
204		/* simple test, VRAM to VRAM */
205		radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
206				      RADEON_GEM_DOMAIN_VRAM);
207		break;
208	case 3:
209		/* GTT to VRAM, buffer size sweep, powers of 2 */
210		for (i = 1; i <= 16384; i <<= 1)
211			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
212					      RADEON_GEM_DOMAIN_GTT,
213					      RADEON_GEM_DOMAIN_VRAM);
214		break;
215	case 4:
216		/* VRAM to GTT, buffer size sweep, powers of 2 */
217		for (i = 1; i <= 16384; i <<= 1)
218			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
219					      RADEON_GEM_DOMAIN_VRAM,
220					      RADEON_GEM_DOMAIN_GTT);
221		break;
222	case 5:
223		/* VRAM to VRAM, buffer size sweep, powers of 2 */
224		for (i = 1; i <= 16384; i <<= 1)
225			radeon_benchmark_move(rdev, i * RADEON_GPU_PAGE_SIZE,
226					      RADEON_GEM_DOMAIN_VRAM,
227					      RADEON_GEM_DOMAIN_VRAM);
228		break;
229	case 6:
230		/* GTT to VRAM, buffer size sweep, common modes */
231		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
232			radeon_benchmark_move(rdev, common_modes[i],
233					      RADEON_GEM_DOMAIN_GTT,
234					      RADEON_GEM_DOMAIN_VRAM);
235		break;
236	case 7:
237		/* VRAM to GTT, buffer size sweep, common modes */
238		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
239			radeon_benchmark_move(rdev, common_modes[i],
240					      RADEON_GEM_DOMAIN_VRAM,
241					      RADEON_GEM_DOMAIN_GTT);
242		break;
243	case 8:
244		/* VRAM to VRAM, buffer size sweep, common modes */
245		for (i = 0; i < RADEON_BENCHMARK_COMMON_MODES_N; i++)
246			radeon_benchmark_move(rdev, common_modes[i],
247					      RADEON_GEM_DOMAIN_VRAM,
248					      RADEON_GEM_DOMAIN_VRAM);
249		break;
250
251	default:
252		DRM_ERROR("Unknown benchmark\n");
253	}
254}
255