projects/linux·blob master · refs

262 lines · 7.0 KiB

1/*
2 * Copyright 2009 Jerome Glisse.
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: Jerome Glisse
23 */
24
25#include <drm/amdgpu_drm.h>
26#include "amdgpu.h"
27
28#define AMDGPU_BENCHMARK_ITERATIONS 1024
29#define AMDGPU_BENCHMARK_COMMON_MODES_N 17
30
31static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
32 uint64_t saddr, uint64_t daddr, int n, s64 *time_ms)
33{
34 ktime_t stime, etime;
35 struct dma_fence *fence;
36 int i, r;
37
38 mutex_lock(&adev->mman.default_entity.lock);
39 stime = ktime_get();
40 for (i = 0; i < n; i++) {
41 r = amdgpu_copy_buffer(adev, &adev->mman.default_entity,
42 saddr, daddr, size, NULL, &fence,
43 false, 0);
44 if (r)
45 goto exit_do_move;
46 r = dma_fence_wait(fence, false);
47 dma_fence_put(fence);
48 if (r)
49 goto exit_do_move;
50 }
51
52exit_do_move:
53 mutex_unlock(&adev->mman.default_entity.lock);
54 etime = ktime_get();
55 *time_ms = ktime_ms_delta(etime, stime);
56
57 return r;
58}
59
60
61static void amdgpu_benchmark_log_results(struct amdgpu_device *adev,
62 int n, unsigned size,
63 s64 time_ms,
64 unsigned sdomain, unsigned ddomain,
65 char *kind)
66{
67 s64 throughput = (n * (size >> 10));
68
69 throughput = div64_s64(throughput, time_ms);
70
71 dev_info(adev->dev, " %s %u bo moves of %u kB from"
72 " %d to %d in %lld ms, throughput: %lld Mb/s or %lld MB/s\n",
73 kind, n, size >> 10, sdomain, ddomain, time_ms,
74 throughput * 8, throughput);
75}
76
77static int amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,
78 unsigned sdomain, unsigned ddomain)
79{
80 struct amdgpu_bo *dobj = NULL;
81 struct amdgpu_bo *sobj = NULL;
82 uint64_t saddr, daddr;
83 s64 time_ms;
84 int r, n;
85
86 n = AMDGPU_BENCHMARK_ITERATIONS;
87
88 r = amdgpu_bo_create_kernel(adev, size,
89 PAGE_SIZE, sdomain,
90 &sobj,
91 &saddr,
92 NULL);
93 if (r)
94 goto out_cleanup;
95 r = amdgpu_bo_create_kernel(adev, size,
96 PAGE_SIZE, ddomain,
97 &dobj,
98 &daddr,
99 NULL);
100 if (r)
101 goto out_cleanup;
102
103 if (adev->mman.buffer_funcs) {
104 r = amdgpu_benchmark_do_move(adev, size, saddr, daddr, n, &time_ms);
105 if (r)
106 goto out_cleanup;
107 else
108 amdgpu_benchmark_log_results(adev, n, size, time_ms,
109 sdomain, ddomain, "dma");
110 }
111
112out_cleanup:
113 /* Check error value now. The value can be overwritten when clean up.*/
114 if (r < 0)
115 dev_info(adev->dev, "Error while benchmarking BO move.\n");
116
117 if (sobj)
118 amdgpu_bo_free_kernel(&sobj, &saddr, NULL);
119 if (dobj)
120 amdgpu_bo_free_kernel(&dobj, &daddr, NULL);
121 return r;
122}
123
124int amdgpu_benchmark(struct amdgpu_device *adev, int test_number)
125{
126 int i, r;
127 static const int common_modes[AMDGPU_BENCHMARK_COMMON_MODES_N] = {
128 640 * 480 * 4,
129 720 * 480 * 4,
130 800 * 600 * 4,
131 848 * 480 * 4,
132 1024 * 768 * 4,
133 1152 * 768 * 4,
134 1280 * 720 * 4,
135 1280 * 800 * 4,
136 1280 * 854 * 4,
137 1280 * 960 * 4,
138 1280 * 1024 * 4,
139 1440 * 900 * 4,
140 1400 * 1050 * 4,
141 1680 * 1050 * 4,
142 1600 * 1200 * 4,
143 1920 * 1080 * 4,
144 1920 * 1200 * 4
145 };
146
147 mutex_lock(&adev->benchmark_mutex);
148 switch (test_number) {
149 case 1:
150 dev_info(adev->dev,
151 "benchmark test: %d (simple test, VRAM to GTT and GTT to VRAM)\n",
152 test_number);
153 /* simple test, VRAM to GTT and GTT to VRAM */
154 r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_GTT,
155 AMDGPU_GEM_DOMAIN_VRAM);
156 if (r)
157 goto done;
158 r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_VRAM,
159 AMDGPU_GEM_DOMAIN_GTT);
160 if (r)
161 goto done;
162 break;
163 case 2:
164 dev_info(adev->dev,
165 "benchmark test: %d (simple test, VRAM to VRAM)\n",
166 test_number);
167 /* simple test, VRAM to VRAM */
168 r = amdgpu_benchmark_move(adev, 1024*1024, AMDGPU_GEM_DOMAIN_VRAM,
169 AMDGPU_GEM_DOMAIN_VRAM);
170 if (r)
171 goto done;
172 break;
173 case 3:
174 dev_info(adev->dev,
175 "benchmark test: %d (GTT to VRAM, buffer size sweep, powers of 2)\n",
176 test_number);
177 /* GTT to VRAM, buffer size sweep, powers of 2 */
178 for (i = 1; i <= 16384; i <<= 1) {
179 r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,
180 AMDGPU_GEM_DOMAIN_GTT,
181 AMDGPU_GEM_DOMAIN_VRAM);
182 if (r)
183 goto done;
184 }
185 break;
186 case 4:
187 dev_info(adev->dev,
188 "benchmark test: %d (VRAM to GTT, buffer size sweep, powers of 2)\n",
189 test_number);
190 /* VRAM to GTT, buffer size sweep, powers of 2 */
191 for (i = 1; i <= 16384; i <<= 1) {
192 r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,
193 AMDGPU_GEM_DOMAIN_VRAM,
194 AMDGPU_GEM_DOMAIN_GTT);
195 if (r)
196 goto done;
197 }
198 break;
199 case 5:
200 dev_info(adev->dev,
201 "benchmark test: %d (VRAM to VRAM, buffer size sweep, powers of 2)\n",
202 test_number);
203 /* VRAM to VRAM, buffer size sweep, powers of 2 */
204 for (i = 1; i <= 16384; i <<= 1) {
205 r = amdgpu_benchmark_move(adev, i * AMDGPU_GPU_PAGE_SIZE,
206 AMDGPU_GEM_DOMAIN_VRAM,
207 AMDGPU_GEM_DOMAIN_VRAM);
208 if (r)
209 goto done;
210 }
211 break;
212 case 6:
213 dev_info(adev->dev,
214 "benchmark test: %d (GTT to VRAM, buffer size sweep, common modes)\n",
215 test_number);
216 /* GTT to VRAM, buffer size sweep, common modes */
217 for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {
218 r = amdgpu_benchmark_move(adev, common_modes[i],
219 AMDGPU_GEM_DOMAIN_GTT,
220 AMDGPU_GEM_DOMAIN_VRAM);
221 if (r)
222 goto done;
223 }
224 break;
225 case 7:
226 dev_info(adev->dev,
227 "benchmark test: %d (VRAM to GTT, buffer size sweep, common modes)\n",
228 test_number);
229 /* VRAM to GTT, buffer size sweep, common modes */
230 for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {
231 r = amdgpu_benchmark_move(adev, common_modes[i],
232 AMDGPU_GEM_DOMAIN_VRAM,
233 AMDGPU_GEM_DOMAIN_GTT);
234 if (r)
235 goto done;
236 }
237 break;
238 case 8:
239 dev_info(adev->dev,
240 "benchmark test: %d (VRAM to VRAM, buffer size sweep, common modes)\n",
241 test_number);
242 /* VRAM to VRAM, buffer size sweep, common modes */
243 for (i = 0; i < AMDGPU_BENCHMARK_COMMON_MODES_N; i++) {
244 r = amdgpu_benchmark_move(adev, common_modes[i],
245 AMDGPU_GEM_DOMAIN_VRAM,
246 AMDGPU_GEM_DOMAIN_VRAM);
247 if (r)
248 goto done;
249 }
250 break;
251
252 default:
253 dev_info(adev->dev, "Unknown benchmark %d\n", test_number);
254 r = -EINVAL;
255 break;
256 }
257
258done:
259 mutex_unlock(&adev->benchmark_mutex);
260
261 return r;
262}