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 static int radeon_test_create_and_emit_fence(struct radeon_device *rdev, 256 struct radeon_ring *ring, 257 struct radeon_fence **fence) 258 { 259 int r; 260 261 if (ring->idx == R600_RING_TYPE_UVD_INDEX) { 262 r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL); 263 if (r) { 264 DRM_ERROR("Failed to get dummy create msg\n"); 265 return r; 266 } 267 268 r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence); 269 if (r) { 270 DRM_ERROR("Failed to get dummy destroy msg\n"); 271 return r; 272 } 273 } else { 274 r = radeon_ring_lock(rdev, ring, 64); 275 if (r) { 276 DRM_ERROR("Failed to lock ring A %d\n", ring->idx); 277 return r; 278 } 279 radeon_fence_emit(rdev, fence, ring->idx); 280 radeon_ring_unlock_commit(rdev, ring); 281 } 282 return 0; 283 } 284 285 void radeon_test_ring_sync(struct radeon_device *rdev, 286 struct radeon_ring *ringA, 287 struct radeon_ring *ringB) 288 { 289 struct radeon_fence *fence1 = NULL, *fence2 = NULL; 290 struct radeon_semaphore *semaphore = NULL; 291 int r; 292 293 r = radeon_semaphore_create(rdev, &semaphore); 294 if (r) { 295 DRM_ERROR("Failed to create semaphore\n"); 296 goto out_cleanup; 297 } 298 299 r = radeon_ring_lock(rdev, ringA, 64); 300 if (r) { 301 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 302 goto out_cleanup; 303 } 304 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 305 radeon_ring_unlock_commit(rdev, ringA); 306 307 r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1); 308 if (r) 309 goto out_cleanup; 310 311 r = radeon_ring_lock(rdev, ringA, 64); 312 if (r) { 313 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 314 goto out_cleanup; 315 } 316 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 317 radeon_ring_unlock_commit(rdev, ringA); 318 319 r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2); 320 if (r) 321 goto out_cleanup; 322 323 mdelay(1000); 324 325 if (radeon_fence_signaled(fence1)) { 326 DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); 327 goto out_cleanup; 328 } 329 330 r = radeon_ring_lock(rdev, ringB, 64); 331 if (r) { 332 DRM_ERROR("Failed to lock ring B %p\n", ringB); 333 goto out_cleanup; 334 } 335 radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 336 radeon_ring_unlock_commit(rdev, ringB); 337 338 r = radeon_fence_wait(fence1, false); 339 if (r) { 340 DRM_ERROR("Failed to wait for sync fence 1\n"); 341 goto out_cleanup; 342 } 343 344 mdelay(1000); 345 346 if (radeon_fence_signaled(fence2)) { 347 DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); 348 goto out_cleanup; 349 } 350 351 r = radeon_ring_lock(rdev, ringB, 64); 352 if (r) { 353 DRM_ERROR("Failed to lock ring B %p\n", ringB); 354 goto out_cleanup; 355 } 356 radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 357 radeon_ring_unlock_commit(rdev, ringB); 358 359 r = radeon_fence_wait(fence2, false); 360 if (r) { 361 DRM_ERROR("Failed to wait for sync fence 1\n"); 362 goto out_cleanup; 363 } 364 365 out_cleanup: 366 radeon_semaphore_free(rdev, &semaphore, NULL); 367 368 if (fence1) 369 radeon_fence_unref(&fence1); 370 371 if (fence2) 372 radeon_fence_unref(&fence2); 373 374 if (r) 375 printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); 376 } 377 378 static void radeon_test_ring_sync2(struct radeon_device *rdev, 379 struct radeon_ring *ringA, 380 struct radeon_ring *ringB, 381 struct radeon_ring *ringC) 382 { 383 struct radeon_fence *fenceA = NULL, *fenceB = NULL; 384 struct radeon_semaphore *semaphore = NULL; 385 bool sigA, sigB; 386 int i, r; 387 388 r = radeon_semaphore_create(rdev, &semaphore); 389 if (r) { 390 DRM_ERROR("Failed to create semaphore\n"); 391 goto out_cleanup; 392 } 393 394 r = radeon_ring_lock(rdev, ringA, 64); 395 if (r) { 396 DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 397 goto out_cleanup; 398 } 399 radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 400 radeon_ring_unlock_commit(rdev, ringA); 401 402 r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA); 403 if (r) 404 goto out_cleanup; 405 406 r = radeon_ring_lock(rdev, ringB, 64); 407 if (r) { 408 DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); 409 goto out_cleanup; 410 } 411 radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); 412 radeon_ring_unlock_commit(rdev, ringB); 413 r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB); 414 if (r) 415 goto out_cleanup; 416 417 mdelay(1000); 418 419 if (radeon_fence_signaled(fenceA)) { 420 DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 421 goto out_cleanup; 422 } 423 if (radeon_fence_signaled(fenceB)) { 424 DRM_ERROR("Fence B signaled without waiting for semaphore.\n"); 425 goto out_cleanup; 426 } 427 428 r = radeon_ring_lock(rdev, ringC, 64); 429 if (r) { 430 DRM_ERROR("Failed to lock ring B %p\n", ringC); 431 goto out_cleanup; 432 } 433 radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 434 radeon_ring_unlock_commit(rdev, ringC); 435 436 for (i = 0; i < 30; ++i) { 437 mdelay(100); 438 sigA = radeon_fence_signaled(fenceA); 439 sigB = radeon_fence_signaled(fenceB); 440 if (sigA || sigB) 441 break; 442 } 443 444 if (!sigA && !sigB) { 445 DRM_ERROR("Neither fence A nor B has been signaled\n"); 446 goto out_cleanup; 447 } else if (sigA && sigB) { 448 DRM_ERROR("Both fence A and B has been signaled\n"); 449 goto out_cleanup; 450 } 451 452 DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); 453 454 r = radeon_ring_lock(rdev, ringC, 64); 455 if (r) { 456 DRM_ERROR("Failed to lock ring B %p\n", ringC); 457 goto out_cleanup; 458 } 459 radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 460 radeon_ring_unlock_commit(rdev, ringC); 461 462 mdelay(1000); 463 464 r = radeon_fence_wait(fenceA, false); 465 if (r) { 466 DRM_ERROR("Failed to wait for sync fence A\n"); 467 goto out_cleanup; 468 } 469 r = radeon_fence_wait(fenceB, false); 470 if (r) { 471 DRM_ERROR("Failed to wait for sync fence B\n"); 472 goto out_cleanup; 473 } 474 475 out_cleanup: 476 radeon_semaphore_free(rdev, &semaphore, NULL); 477 478 if (fenceA) 479 radeon_fence_unref(&fenceA); 480 481 if (fenceB) 482 radeon_fence_unref(&fenceB); 483 484 if (r) 485 printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); 486 } 487 488 void radeon_test_syncing(struct radeon_device *rdev) 489 { 490 int i, j, k; 491 492 for (i = 1; i < RADEON_NUM_RINGS; ++i) { 493 struct radeon_ring *ringA = &rdev->ring[i]; 494 if (!ringA->ready) 495 continue; 496 497 for (j = 0; j < i; ++j) { 498 struct radeon_ring *ringB = &rdev->ring[j]; 499 if (!ringB->ready) 500 continue; 501 502 DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); 503 radeon_test_ring_sync(rdev, ringA, ringB); 504 505 DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); 506 radeon_test_ring_sync(rdev, ringB, ringA); 507 508 for (k = 0; k < j; ++k) { 509 struct radeon_ring *ringC = &rdev->ring[k]; 510 if (!ringC->ready) 511 continue; 512 513 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); 514 radeon_test_ring_sync2(rdev, ringA, ringB, ringC); 515 516 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); 517 radeon_test_ring_sync2(rdev, ringA, ringC, ringB); 518 519 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); 520 radeon_test_ring_sync2(rdev, ringB, ringA, ringC); 521 522 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); 523 radeon_test_ring_sync2(rdev, ringB, ringC, ringA); 524 525 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); 526 radeon_test_ring_sync2(rdev, ringC, ringA, ringB); 527 528 DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); 529 radeon_test_ring_sync2(rdev, ringC, ringB, ringA); 530 } 531 } 532 } 533 } 534