1 /* 2 * Copyright 2009 VMware, Inc. 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: Michel Dänzer 23 */ 24 #include <drm/drmP.h> 25 #include <drm/radeon_drm.h> 26 #include "radeon_reg.h" 27 #include "radeon.h" 28 29 #define RADEON_TEST_COPY_BLIT 1 30 #define RADEON_TEST_COPY_DMA 0 31 32 33 /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ 34 static void radeon_do_test_moves(struct radeon_device *rdev, int flag) 35 { 36 struct radeon_bo *vram_obj = NULL; 37 struct radeon_bo **gtt_obj = NULL; 38 struct radeon_fence *fence = NULL; 39 uint64_t gtt_addr, vram_addr; 40 unsigned i, n, size; 41 int r, ring; 42 43 switch (flag) { 44 case RADEON_TEST_COPY_DMA: 45 ring = radeon_copy_dma_ring_index(rdev); 46 break; 47 case RADEON_TEST_COPY_BLIT: 48 ring = radeon_copy_blit_ring_index(rdev); 49 break; 50 default: 51 DRM_ERROR("Unknown copy method\n"); 52 return; 53 } 54 55 size = 1024 * 1024; 56 57 /* Number of tests = 58 * (Total GTT - IB pool - writeback page - ring buffers) / test size 59 */ 60 n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024; 61 for (i = 0; i < RADEON_NUM_RINGS; ++i) 62 n -= rdev->ring[i].ring_size; 63 if (rdev->wb.wb_obj) 64 n -= RADEON_GPU_PAGE_SIZE; 65 if (rdev->ih.ring_obj) 66 n -= rdev->ih.ring_size; 67 n /= size; 68 69 gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); 70 if (!gtt_obj) { 71 DRM_ERROR("Failed to allocate %d pointers\n", n); 72 r = 1; 73 goto out_cleanup; 74 } 75 76 r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 77 NULL, &vram_obj); 78 if (r) { 79 DRM_ERROR("Failed to create VRAM object\n"); 80 goto out_cleanup; 81 } 82 r = radeon_bo_reserve(vram_obj, false); 83 if (unlikely(r != 0)) 84 goto out_cleanup; 85 r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); 86 if (r) { 87 DRM_ERROR("Failed to pin VRAM object\n"); 88 goto out_cleanup; 89 } 90 for (i = 0; i < n; i++) { 91 void *gtt_map, *vram_map; 92 void **gtt_start, **gtt_end; 93 void **vram_start, **vram_end; 94 95 r = radeon_bo_create(rdev, size, PAGE_SIZE, true, 96 RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i); 97 if (r) { 98 DRM_ERROR("Failed to create GTT object %d\n", i); 99 goto out_cleanup; 100 } 101 102 r = radeon_bo_reserve(gtt_obj[i], false); 103 if (unlikely(r != 0)) 104 goto out_cleanup; 105 r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); 106 if (r) { 107 DRM_ERROR("Failed to pin GTT object %d\n", i); 108 goto out_cleanup; 109 } 110 111 r = radeon_bo_kmap(gtt_obj[i], >t_map); 112 if (r) { 113 DRM_ERROR("Failed to map GTT object %d\n", i); 114 goto out_cleanup; 115 } 116 117 for (gtt_start = gtt_map, gtt_end = gtt_map + size; 118 gtt_start < gtt_end; 119 gtt_start++) 120 *gtt_start = gtt_start; 121 122 radeon_bo_kunmap(gtt_obj[i]); 123 124 if (ring == R600_RING_TYPE_DMA_INDEX) 125 r = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); 126 else 127 r = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); 128 if (r) { 129 DRM_ERROR("Failed GTT->VRAM copy %d\n", i); 130 goto out_cleanup; 131 } 132 133 r = radeon_fence_wait(fence, false); 134 if (r) { 135 DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); 136 goto out_cleanup; 137 } 138 139 radeon_fence_unref(&fence); 140 141 r = radeon_bo_kmap(vram_obj, &vram_map); 142 if (r) { 143 DRM_ERROR("Failed to map VRAM object after copy %d\n", i); 144 goto out_cleanup; 145 } 146 147 for (gtt_start = gtt_map, gtt_end = gtt_map + size, 148 vram_start = vram_map, vram_end = vram_map + size; 149 vram_start < vram_end; 150 gtt_start++, vram_start++) { 151 if (*vram_start != gtt_start) { 152 DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " 153 "expected 0x%p (GTT/VRAM offset " 154 "0x%16llx/0x%16llx)\n", 155 i, *vram_start, gtt_start, 156 (unsigned long long) 157 (gtt_addr - rdev->mc.gtt_start + 158 (void*)gtt_start - gtt_map), 159 (unsigned long long) 160 (vram_addr - rdev->mc.vram_start + 161 (void*)gtt_start - gtt_map)); 162 radeon_bo_kunmap(vram_obj); 163 goto out_cleanup; 164 } 165 *vram_start = vram_start; 166 } 167 168 radeon_bo_kunmap(vram_obj); 169 170 if (ring == R600_RING_TYPE_DMA_INDEX) 171 r = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); 172 else 173 r = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); 174 if (r) { 175 DRM_ERROR("Failed VRAM->GTT copy %d\n", i); 176 goto out_cleanup; 177 } 178 179 r = radeon_fence_wait(fence, false); 180 if (r) { 181 DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); 182 goto out_cleanup; 183 } 184 185 radeon_fence_unref(&fence); 186 187 r = radeon_bo_kmap(gtt_obj[i], >t_map); 188 if (r) { 189 DRM_ERROR("Failed to map GTT object after copy %d\n", i); 190 goto out_cleanup; 191 } 192 193 for (gtt_start = gtt_map, gtt_end = gtt_map + size, 194 vram_start = vram_map, vram_end = vram_map + size; 195 gtt_start < gtt_end; 196 gtt_start++, vram_start++) { 197 if (*gtt_start != vram_start) { 198 DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " 199 "expected 0x%p (VRAM/GTT offset " 200 "0x%16llx/0x%16llx)\n", 201 i, *gtt_start, vram_start, 202 (unsigned long long) 203 (vram_addr - rdev->mc.vram_start + 204 (void*)vram_start - vram_map), 205 (unsigned long long) 206 (gtt_addr - rdev->mc.gtt_start + 207 (void*)vram_start - vram_map)); 208 radeon_bo_kunmap(gtt_obj[i]); 209 goto out_cleanup; 210 } 211 } 212 213 radeon_bo_kunmap(gtt_obj[i]); 214 215 DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", 216 gtt_addr - rdev->mc.gtt_start); 217 } 218 219 out_cleanup: 220 if (vram_obj) { 221 if (radeon_bo_is_reserved(vram_obj)) { 222 radeon_bo_unpin(vram_obj); 223 radeon_bo_unreserve(vram_obj); 224 } 225 radeon_bo_unref(&vram_obj); 226 } 227 if (gtt_obj) { 228 for (i = 0; i < n; i++) { 229 if (gtt_obj[i]) { 230 if (radeon_bo_is_reserved(gtt_obj[i])) { 231 radeon_bo_unpin(gtt_obj[i]); 232 radeon_bo_unreserve(gtt_obj[i]); 233 } 234 radeon_bo_unref(>t_obj[i]); 235 } 236 } 237 kfree(gtt_obj); 238 } 239 if (fence) { 240 radeon_fence_unref(&fence); 241 } 242 if (r) { 243 printk(KERN_WARNING "Error while testing BO move.\n"); 244 } 245 } 246 247 void radeon_test_moves(struct radeon_device *rdev) 248 { 249 if (rdev->asic->copy.dma) 250 radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA); 251 if (rdev->asic->copy.blit) 252 radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); 253 } 254 255 void radeon_test_ring_sync(struct radeon_device *rdev, 256 struct radeon_ring *ringA, 257 struct radeon_ring *ringB) 258 { 259 struct radeon_fence *fence1 = NULL, *fence2 = NULL; 260 struct radeon_semaphore *semaphore = NULL; 261 int r; 262 263 r = radeon_semaphore_create(rdev, &semaphore); 264 if (r) { 265 DRM_ERROR("Failed to create semaphore\n"); 266 goto out_cleanup; 267 } 268 269 r = radeon_ring_lock(rdev, ringA, 64); 270 if (r) { 271 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 272 goto out_cleanup; 273 } 274 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 275 r = radeon_fence_emit(rdev, &fence1, ringA->idx); 276 if (r) { 277 DRM_ERROR("Failed to emit fence 1\n"); 278 radeon_ring_unlock_undo(rdev, ringA); 279 goto out_cleanup; 280 } 281 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 282 r = radeon_fence_emit(rdev, &fence2, ringA->idx); 283 if (r) { 284 DRM_ERROR("Failed to emit fence 2\n"); 285 radeon_ring_unlock_undo(rdev, ringA); 286 goto out_cleanup; 287 } 288 radeon_ring_unlock_commit(rdev, ringA); 289 290 mdelay(1000); 291 292 if (radeon_fence_signaled(fence1)) { 293 DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); 294 goto out_cleanup; 295 } 296 297 r = radeon_ring_lock(rdev, ringB, 64); 298 if (r) { 299 DRM_ERROR("Failed to lock ring B %p\n", ringB); 300 goto out_cleanup; 301 } 302 radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 303 radeon_ring_unlock_commit(rdev, ringB); 304 305 r = radeon_fence_wait(fence1, false); 306 if (r) { 307 DRM_ERROR("Failed to wait for sync fence 1\n"); 308 goto out_cleanup; 309 } 310 311 mdelay(1000); 312 313 if (radeon_fence_signaled(fence2)) { 314 DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); 315 goto out_cleanup; 316 } 317 318 r = radeon_ring_lock(rdev, ringB, 64); 319 if (r) { 320 DRM_ERROR("Failed to lock ring B %p\n", ringB); 321 goto out_cleanup; 322 } 323 radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 324 radeon_ring_unlock_commit(rdev, ringB); 325 326 r = radeon_fence_wait(fence2, false); 327 if (r) { 328 DRM_ERROR("Failed to wait for sync fence 1\n"); 329 goto out_cleanup; 330 } 331 332 out_cleanup: 333 radeon_semaphore_free(rdev, &semaphore, NULL); 334 335 if (fence1) 336 radeon_fence_unref(&fence1); 337 338 if (fence2) 339 radeon_fence_unref(&fence2); 340 341 if (r) 342 printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); 343 } 344 345 static void radeon_test_ring_sync2(struct radeon_device *rdev, 346 struct radeon_ring *ringA, 347 struct radeon_ring *ringB, 348 struct radeon_ring *ringC) 349 { 350 struct radeon_fence *fenceA = NULL, *fenceB = NULL; 351 struct radeon_semaphore *semaphore = NULL; 352 bool sigA, sigB; 353 int i, r; 354 355 r = radeon_semaphore_create(rdev, &semaphore); 356 if (r) { 357 DRM_ERROR("Failed to create semaphore\n"); 358 goto out_cleanup; 359 } 360 361 r = radeon_ring_lock(rdev, ringA, 64); 362 if (r) { 363 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 364 goto out_cleanup; 365 } 366 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 367 r = radeon_fence_emit(rdev, &fenceA, ringA->idx); 368 if (r) { 369 DRM_ERROR("Failed to emit sync fence 1\n"); 370 radeon_ring_unlock_undo(rdev, ringA); 371 goto out_cleanup; 372 } 373 radeon_ring_unlock_commit(rdev, ringA); 374 375 r = radeon_ring_lock(rdev, ringB, 64); 376 if (r) { 377 DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); 378 goto out_cleanup; 379 } 380 radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); 381 r = radeon_fence_emit(rdev, &fenceB, ringB->idx); 382 if (r) { 383 DRM_ERROR("Failed to create sync fence 2\n"); 384 radeon_ring_unlock_undo(rdev, ringB); 385 goto out_cleanup; 386 } 387 radeon_ring_unlock_commit(rdev, ringB); 388 389 mdelay(1000); 390 391 if (radeon_fence_signaled(fenceA)) { 392 DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 393 goto out_cleanup; 394 } 395 if (radeon_fence_signaled(fenceB)) { 396 DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 397 goto out_cleanup; 398 } 399 400 r = radeon_ring_lock(rdev, ringC, 64); 401 if (r) { 402 DRM_ERROR("Failed to lock ring B %p\n", ringC); 403 goto out_cleanup; 404 } 405 radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 406 radeon_ring_unlock_commit(rdev, ringC); 407 408 for (i = 0; i < 30; ++i) { 409 mdelay(100); 410 sigA = radeon_fence_signaled(fenceA); 411 sigB = radeon_fence_signaled(fenceB); 412 if (sigA || sigB) 413 break; 414 } 415 416 if (!sigA && !sigB) { 417 DRM_ERROR("Neither fence A nor B has been signaled\n"); 418 goto out_cleanup; 419 } else if (sigA && sigB) { 420 DRM_ERROR("Both fence A and B has been signaled\n"); 421 goto out_cleanup; 422 } 423 424 DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); 425 426 r = radeon_ring_lock(rdev, ringC, 64); 427 if (r) { 428 DRM_ERROR("Failed to lock ring B %p\n", ringC); 429 goto out_cleanup; 430 } 431 radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 432 radeon_ring_unlock_commit(rdev, ringC); 433 434 mdelay(1000); 435 436 r = radeon_fence_wait(fenceA, false); 437 if (r) { 438 DRM_ERROR("Failed to wait for sync fence A\n"); 439 goto out_cleanup; 440 } 441 r = radeon_fence_wait(fenceB, false); 442 if (r) { 443 DRM_ERROR("Failed to wait for sync fence B\n"); 444 goto out_cleanup; 445 } 446 447 out_cleanup: 448 radeon_semaphore_free(rdev, &semaphore, NULL); 449 450 if (fenceA) 451 radeon_fence_unref(&fenceA); 452 453 if (fenceB) 454 radeon_fence_unref(&fenceB); 455 456 if (r) 457 printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); 458 } 459 460 void radeon_test_syncing(struct radeon_device *rdev) 461 { 462 int i, j, k; 463 464 for (i = 1; i < RADEON_NUM_RINGS; ++i) { 465 struct radeon_ring *ringA = &rdev->ring[i]; 466 if (!ringA->ready) 467 continue; 468 469 for (j = 0; j < i; ++j) { 470 struct radeon_ring *ringB = &rdev->ring[j]; 471 if (!ringB->ready) 472 continue; 473 474 DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); 475 radeon_test_ring_sync(rdev, ringA, ringB); 476 477 DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); 478 radeon_test_ring_sync(rdev, ringB, ringA); 479 480 for (k = 0; k < j; ++k) { 481 struct radeon_ring *ringC = &rdev->ring[k]; 482 if (!ringC->ready) 483 continue; 484 485 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); 486 radeon_test_ring_sync2(rdev, ringA, ringB, ringC); 487 488 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); 489 radeon_test_ring_sync2(rdev, ringA, ringC, ringB); 490 491 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); 492 radeon_test_ring_sync2(rdev, ringB, ringA, ringC); 493 494 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); 495 radeon_test_ring_sync2(rdev, ringB, ringC, ringA); 496 497 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); 498 radeon_test_ring_sync2(rdev, ringC, ringA, ringB); 499 500 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); 501 radeon_test_ring_sync2(rdev, ringC, ringB, ringA); 502 } 503 } 504 } 505 } 506