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 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 52 exit_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 61 static 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 77 static 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 112 out_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 124 int 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 258 done: 259 mutex_unlock(&adev->benchmark_mutex); 260 261 return r; 262 } 263