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