1*da5fd66cSDirk Hohndel (VMware) // SPDX-License-Identifier: GPL-2.0 OR MIT 2ecc0b326SMichel Dänzer /* 3ecc0b326SMichel Dänzer * Copyright 2009 VMware, Inc. 4ecc0b326SMichel Dänzer * 5ecc0b326SMichel Dänzer * Permission is hereby granted, free of charge, to any person obtaining a 6ecc0b326SMichel Dänzer * copy of this software and associated documentation files (the "Software"), 7ecc0b326SMichel Dänzer * to deal in the Software without restriction, including without limitation 8ecc0b326SMichel Dänzer * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9ecc0b326SMichel Dänzer * and/or sell copies of the Software, and to permit persons to whom the 10ecc0b326SMichel Dänzer * Software is furnished to do so, subject to the following conditions: 11ecc0b326SMichel Dänzer * 12ecc0b326SMichel Dänzer * The above copyright notice and this permission notice shall be included in 13ecc0b326SMichel Dänzer * all copies or substantial portions of the Software. 14ecc0b326SMichel Dänzer * 15ecc0b326SMichel Dänzer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16ecc0b326SMichel Dänzer * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17ecc0b326SMichel Dänzer * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18ecc0b326SMichel Dänzer * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19ecc0b326SMichel Dänzer * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20ecc0b326SMichel Dänzer * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21ecc0b326SMichel Dänzer * OTHER DEALINGS IN THE SOFTWARE. 22ecc0b326SMichel Dänzer * 23ecc0b326SMichel Dänzer * Authors: Michel Dänzer 24ecc0b326SMichel Dänzer */ 25ecc0b326SMichel Dänzer #include <drm/drmP.h> 26ecc0b326SMichel Dänzer #include <drm/radeon_drm.h> 27ecc0b326SMichel Dänzer #include "radeon_reg.h" 28ecc0b326SMichel Dänzer #include "radeon.h" 29ecc0b326SMichel Dänzer 30009ee7a0SAlex Deucher #define RADEON_TEST_COPY_BLIT 1 31009ee7a0SAlex Deucher #define RADEON_TEST_COPY_DMA 0 32009ee7a0SAlex Deucher 33ecc0b326SMichel Dänzer 34ecc0b326SMichel Dänzer /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ 35009ee7a0SAlex Deucher static void radeon_do_test_moves(struct radeon_device *rdev, int flag) 36ecc0b326SMichel Dänzer { 374c788679SJerome Glisse struct radeon_bo *vram_obj = NULL; 384c788679SJerome Glisse struct radeon_bo **gtt_obj = NULL; 39ecc0b326SMichel Dänzer uint64_t gtt_addr, vram_addr; 4089cd67b3SDan Carpenter unsigned n, size; 4189cd67b3SDan Carpenter int i, r, ring; 42009ee7a0SAlex Deucher 43009ee7a0SAlex Deucher switch (flag) { 44009ee7a0SAlex Deucher case RADEON_TEST_COPY_DMA: 45009ee7a0SAlex Deucher ring = radeon_copy_dma_ring_index(rdev); 46009ee7a0SAlex Deucher break; 47009ee7a0SAlex Deucher case RADEON_TEST_COPY_BLIT: 48009ee7a0SAlex Deucher ring = radeon_copy_blit_ring_index(rdev); 49009ee7a0SAlex Deucher break; 50009ee7a0SAlex Deucher default: 51009ee7a0SAlex Deucher DRM_ERROR("Unknown copy method\n"); 52009ee7a0SAlex Deucher return; 53009ee7a0SAlex Deucher } 54ecc0b326SMichel Dänzer 55ecc0b326SMichel Dänzer size = 1024 * 1024; 56ecc0b326SMichel Dänzer 57ecc0b326SMichel Dänzer /* Number of tests = 5824cae9e7SMichel Dänzer * (Total GTT - IB pool - writeback page - ring buffers) / test size 59ecc0b326SMichel Dänzer */ 602c6316cbSAlex Deucher n = rdev->mc.gtt_size - rdev->gart_pin_size; 6124cae9e7SMichel Dänzer n /= size; 62ecc0b326SMichel Dänzer 636396bb22SKees Cook gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL); 64ecc0b326SMichel Dänzer if (!gtt_obj) { 65ecc0b326SMichel Dänzer DRM_ERROR("Failed to allocate %d pointers\n", n); 66ecc0b326SMichel Dänzer r = 1; 67ecc0b326SMichel Dänzer goto out_cleanup; 68ecc0b326SMichel Dänzer } 69ecc0b326SMichel Dänzer 70441921d5SDaniel Vetter r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 71831b6966SMaarten Lankhorst 0, NULL, NULL, &vram_obj); 72ecc0b326SMichel Dänzer if (r) { 73ecc0b326SMichel Dänzer DRM_ERROR("Failed to create VRAM object\n"); 74ecc0b326SMichel Dänzer goto out_cleanup; 75ecc0b326SMichel Dänzer } 764c788679SJerome Glisse r = radeon_bo_reserve(vram_obj, false); 774c788679SJerome Glisse if (unlikely(r != 0)) 78977c38d5SMaarten Lankhorst goto out_unref; 794c788679SJerome Glisse r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); 80ecc0b326SMichel Dänzer if (r) { 81ecc0b326SMichel Dänzer DRM_ERROR("Failed to pin VRAM object\n"); 82977c38d5SMaarten Lankhorst goto out_unres; 83ecc0b326SMichel Dänzer } 84ecc0b326SMichel Dänzer for (i = 0; i < n; i++) { 85ecc0b326SMichel Dänzer void *gtt_map, *vram_map; 86ecc0b326SMichel Dänzer void **gtt_start, **gtt_end; 87ecc0b326SMichel Dänzer void **vram_start, **vram_end; 88977c38d5SMaarten Lankhorst struct radeon_fence *fence = NULL; 89ecc0b326SMichel Dänzer 90441921d5SDaniel Vetter r = radeon_bo_create(rdev, size, PAGE_SIZE, true, 91831b6966SMaarten Lankhorst RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, 92831b6966SMaarten Lankhorst gtt_obj + i); 93ecc0b326SMichel Dänzer if (r) { 94ecc0b326SMichel Dänzer DRM_ERROR("Failed to create GTT object %d\n", i); 95977c38d5SMaarten Lankhorst goto out_lclean; 96ecc0b326SMichel Dänzer } 97ecc0b326SMichel Dänzer 984c788679SJerome Glisse r = radeon_bo_reserve(gtt_obj[i], false); 994c788679SJerome Glisse if (unlikely(r != 0)) 100977c38d5SMaarten Lankhorst goto out_lclean_unref; 1014c788679SJerome Glisse r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); 102ecc0b326SMichel Dänzer if (r) { 103ecc0b326SMichel Dänzer DRM_ERROR("Failed to pin GTT object %d\n", i); 104977c38d5SMaarten Lankhorst goto out_lclean_unres; 105ecc0b326SMichel Dänzer } 106ecc0b326SMichel Dänzer 1074c788679SJerome Glisse r = radeon_bo_kmap(gtt_obj[i], >t_map); 108ecc0b326SMichel Dänzer if (r) { 109ecc0b326SMichel Dänzer DRM_ERROR("Failed to map GTT object %d\n", i); 110977c38d5SMaarten Lankhorst goto out_lclean_unpin; 111ecc0b326SMichel Dänzer } 112ecc0b326SMichel Dänzer 113ecc0b326SMichel Dänzer for (gtt_start = gtt_map, gtt_end = gtt_map + size; 114ecc0b326SMichel Dänzer gtt_start < gtt_end; 115ecc0b326SMichel Dänzer gtt_start++) 116ecc0b326SMichel Dänzer *gtt_start = gtt_start; 117ecc0b326SMichel Dänzer 1184c788679SJerome Glisse radeon_bo_kunmap(gtt_obj[i]); 119ecc0b326SMichel Dänzer 120009ee7a0SAlex Deucher if (ring == R600_RING_TYPE_DMA_INDEX) 12157d20a43SChristian König fence = radeon_copy_dma(rdev, gtt_addr, vram_addr, 12257d20a43SChristian König size / RADEON_GPU_PAGE_SIZE, 12392b712b7SIlija Hadzic vram_obj->tbo.resv); 124009ee7a0SAlex Deucher else 12557d20a43SChristian König fence = radeon_copy_blit(rdev, gtt_addr, vram_addr, 12657d20a43SChristian König size / RADEON_GPU_PAGE_SIZE, 12792b712b7SIlija Hadzic vram_obj->tbo.resv); 12857d20a43SChristian König if (IS_ERR(fence)) { 129ecc0b326SMichel Dänzer DRM_ERROR("Failed GTT->VRAM copy %d\n", i); 13057d20a43SChristian König r = PTR_ERR(fence); 131977c38d5SMaarten Lankhorst goto out_lclean_unpin; 132ecc0b326SMichel Dänzer } 133ecc0b326SMichel Dänzer 134ecc0b326SMichel Dänzer r = radeon_fence_wait(fence, false); 135ecc0b326SMichel Dänzer if (r) { 136ecc0b326SMichel Dänzer DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); 137977c38d5SMaarten Lankhorst goto out_lclean_unpin; 138ecc0b326SMichel Dänzer } 139ecc0b326SMichel Dänzer 140ecc0b326SMichel Dänzer radeon_fence_unref(&fence); 141ecc0b326SMichel Dänzer 1424c788679SJerome Glisse r = radeon_bo_kmap(vram_obj, &vram_map); 143ecc0b326SMichel Dänzer if (r) { 144ecc0b326SMichel Dänzer DRM_ERROR("Failed to map VRAM object after copy %d\n", i); 145977c38d5SMaarten Lankhorst goto out_lclean_unpin; 146ecc0b326SMichel Dänzer } 147ecc0b326SMichel Dänzer 148ecc0b326SMichel Dänzer for (gtt_start = gtt_map, gtt_end = gtt_map + size, 149ecc0b326SMichel Dänzer vram_start = vram_map, vram_end = vram_map + size; 150ecc0b326SMichel Dänzer vram_start < vram_end; 151ecc0b326SMichel Dänzer gtt_start++, vram_start++) { 152ecc0b326SMichel Dänzer if (*vram_start != gtt_start) { 153ecc0b326SMichel Dänzer DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " 1544fb1a35cSMichel Dänzer "expected 0x%p (GTT/VRAM offset " 1554fb1a35cSMichel Dänzer "0x%16llx/0x%16llx)\n", 1564fb1a35cSMichel Dänzer i, *vram_start, gtt_start, 1574fb1a35cSMichel Dänzer (unsigned long long) 1584fb1a35cSMichel Dänzer (gtt_addr - rdev->mc.gtt_start + 1594fb1a35cSMichel Dänzer (void*)gtt_start - gtt_map), 1604fb1a35cSMichel Dänzer (unsigned long long) 1614fb1a35cSMichel Dänzer (vram_addr - rdev->mc.vram_start + 1624fb1a35cSMichel Dänzer (void*)gtt_start - gtt_map)); 1634c788679SJerome Glisse radeon_bo_kunmap(vram_obj); 164977c38d5SMaarten Lankhorst goto out_lclean_unpin; 165ecc0b326SMichel Dänzer } 166ecc0b326SMichel Dänzer *vram_start = vram_start; 167ecc0b326SMichel Dänzer } 168ecc0b326SMichel Dänzer 1694c788679SJerome Glisse radeon_bo_kunmap(vram_obj); 170ecc0b326SMichel Dänzer 171009ee7a0SAlex Deucher if (ring == R600_RING_TYPE_DMA_INDEX) 17257d20a43SChristian König fence = radeon_copy_dma(rdev, vram_addr, gtt_addr, 17357d20a43SChristian König size / RADEON_GPU_PAGE_SIZE, 17492b712b7SIlija Hadzic vram_obj->tbo.resv); 175009ee7a0SAlex Deucher else 17657d20a43SChristian König fence = radeon_copy_blit(rdev, vram_addr, gtt_addr, 17757d20a43SChristian König size / RADEON_GPU_PAGE_SIZE, 17892b712b7SIlija Hadzic vram_obj->tbo.resv); 17957d20a43SChristian König if (IS_ERR(fence)) { 180ecc0b326SMichel Dänzer DRM_ERROR("Failed VRAM->GTT copy %d\n", i); 18157d20a43SChristian König r = PTR_ERR(fence); 182977c38d5SMaarten Lankhorst goto out_lclean_unpin; 183ecc0b326SMichel Dänzer } 184ecc0b326SMichel Dänzer 185ecc0b326SMichel Dänzer r = radeon_fence_wait(fence, false); 186ecc0b326SMichel Dänzer if (r) { 187ecc0b326SMichel Dänzer DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); 188977c38d5SMaarten Lankhorst goto out_lclean_unpin; 189ecc0b326SMichel Dänzer } 190ecc0b326SMichel Dänzer 191ecc0b326SMichel Dänzer radeon_fence_unref(&fence); 192ecc0b326SMichel Dänzer 1934c788679SJerome Glisse r = radeon_bo_kmap(gtt_obj[i], >t_map); 194ecc0b326SMichel Dänzer if (r) { 195ecc0b326SMichel Dänzer DRM_ERROR("Failed to map GTT object after copy %d\n", i); 196977c38d5SMaarten Lankhorst goto out_lclean_unpin; 197ecc0b326SMichel Dänzer } 198ecc0b326SMichel Dänzer 199ecc0b326SMichel Dänzer for (gtt_start = gtt_map, gtt_end = gtt_map + size, 200ecc0b326SMichel Dänzer vram_start = vram_map, vram_end = vram_map + size; 201ecc0b326SMichel Dänzer gtt_start < gtt_end; 202ecc0b326SMichel Dänzer gtt_start++, vram_start++) { 203ecc0b326SMichel Dänzer if (*gtt_start != vram_start) { 204ecc0b326SMichel Dänzer DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " 2054fb1a35cSMichel Dänzer "expected 0x%p (VRAM/GTT offset " 2064fb1a35cSMichel Dänzer "0x%16llx/0x%16llx)\n", 2074fb1a35cSMichel Dänzer i, *gtt_start, vram_start, 2084fb1a35cSMichel Dänzer (unsigned long long) 2094fb1a35cSMichel Dänzer (vram_addr - rdev->mc.vram_start + 2104fb1a35cSMichel Dänzer (void*)vram_start - vram_map), 2114fb1a35cSMichel Dänzer (unsigned long long) 2124fb1a35cSMichel Dänzer (gtt_addr - rdev->mc.gtt_start + 2134fb1a35cSMichel Dänzer (void*)vram_start - vram_map)); 2144c788679SJerome Glisse radeon_bo_kunmap(gtt_obj[i]); 215977c38d5SMaarten Lankhorst goto out_lclean_unpin; 216ecc0b326SMichel Dänzer } 217ecc0b326SMichel Dänzer } 218ecc0b326SMichel Dänzer 2194c788679SJerome Glisse radeon_bo_kunmap(gtt_obj[i]); 220ecc0b326SMichel Dänzer 221ecc0b326SMichel Dänzer DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", 222d594e46aSJerome Glisse gtt_addr - rdev->mc.gtt_start); 223977c38d5SMaarten Lankhorst continue; 224ecc0b326SMichel Dänzer 225977c38d5SMaarten Lankhorst out_lclean_unpin: 226977c38d5SMaarten Lankhorst radeon_bo_unpin(gtt_obj[i]); 227977c38d5SMaarten Lankhorst out_lclean_unres: 228977c38d5SMaarten Lankhorst radeon_bo_unreserve(gtt_obj[i]); 229977c38d5SMaarten Lankhorst out_lclean_unref: 230977c38d5SMaarten Lankhorst radeon_bo_unref(>t_obj[i]); 231977c38d5SMaarten Lankhorst out_lclean: 232977c38d5SMaarten Lankhorst for (--i; i >= 0; --i) { 2334c788679SJerome Glisse radeon_bo_unpin(gtt_obj[i]); 2344c788679SJerome Glisse radeon_bo_unreserve(gtt_obj[i]); 2354c788679SJerome Glisse radeon_bo_unref(>t_obj[i]); 236ecc0b326SMichel Dänzer } 23757d20a43SChristian König if (fence && !IS_ERR(fence)) 238ecc0b326SMichel Dänzer radeon_fence_unref(&fence); 239977c38d5SMaarten Lankhorst break; 240ecc0b326SMichel Dänzer } 241977c38d5SMaarten Lankhorst 242977c38d5SMaarten Lankhorst radeon_bo_unpin(vram_obj); 243977c38d5SMaarten Lankhorst out_unres: 244977c38d5SMaarten Lankhorst radeon_bo_unreserve(vram_obj); 245977c38d5SMaarten Lankhorst out_unref: 246977c38d5SMaarten Lankhorst radeon_bo_unref(&vram_obj); 247977c38d5SMaarten Lankhorst out_cleanup: 248977c38d5SMaarten Lankhorst kfree(gtt_obj); 249ecc0b326SMichel Dänzer if (r) { 2507ca85295SJoe Perches pr_warn("Error while testing BO move\n"); 251ecc0b326SMichel Dänzer } 252ecc0b326SMichel Dänzer } 25360a7e396SChristian König 254009ee7a0SAlex Deucher void radeon_test_moves(struct radeon_device *rdev) 255009ee7a0SAlex Deucher { 256009ee7a0SAlex Deucher if (rdev->asic->copy.dma) 257009ee7a0SAlex Deucher radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA); 258009ee7a0SAlex Deucher if (rdev->asic->copy.blit) 259009ee7a0SAlex Deucher radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); 260009ee7a0SAlex Deucher } 261009ee7a0SAlex Deucher 262f2ba57b5SChristian König static int radeon_test_create_and_emit_fence(struct radeon_device *rdev, 263f2ba57b5SChristian König struct radeon_ring *ring, 264f2ba57b5SChristian König struct radeon_fence **fence) 265f2ba57b5SChristian König { 266d93f7937SChristian König uint32_t handle = ring->idx ^ 0xdeafbeef; 267f2ba57b5SChristian König int r; 268f2ba57b5SChristian König 269f2ba57b5SChristian König if (ring->idx == R600_RING_TYPE_UVD_INDEX) { 270d93f7937SChristian König r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL); 271f2ba57b5SChristian König if (r) { 272f2ba57b5SChristian König DRM_ERROR("Failed to get dummy create msg\n"); 273f2ba57b5SChristian König return r; 274f2ba57b5SChristian König } 275f2ba57b5SChristian König 276d93f7937SChristian König r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence); 277f2ba57b5SChristian König if (r) { 278f2ba57b5SChristian König DRM_ERROR("Failed to get dummy destroy msg\n"); 279f2ba57b5SChristian König return r; 280f2ba57b5SChristian König } 281d93f7937SChristian König 282d93f7937SChristian König } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX || 283d93f7937SChristian König ring->idx == TN_RING_TYPE_VCE2_INDEX) { 284d93f7937SChristian König r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL); 285d93f7937SChristian König if (r) { 286d93f7937SChristian König DRM_ERROR("Failed to get dummy create msg\n"); 287d93f7937SChristian König return r; 288d93f7937SChristian König } 289d93f7937SChristian König 290d93f7937SChristian König r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence); 291d93f7937SChristian König if (r) { 292d93f7937SChristian König DRM_ERROR("Failed to get dummy destroy msg\n"); 293d93f7937SChristian König return r; 294d93f7937SChristian König } 295d93f7937SChristian König 296f2ba57b5SChristian König } else { 297f2ba57b5SChristian König r = radeon_ring_lock(rdev, ring, 64); 298f2ba57b5SChristian König if (r) { 299f2ba57b5SChristian König DRM_ERROR("Failed to lock ring A %d\n", ring->idx); 300f2ba57b5SChristian König return r; 301f2ba57b5SChristian König } 3022f2429c3SPan Bian r = radeon_fence_emit(rdev, fence, ring->idx); 3032f2429c3SPan Bian if (r) { 3042f2429c3SPan Bian DRM_ERROR("Failed to emit fence\n"); 3052f2429c3SPan Bian radeon_ring_unlock_undo(rdev, ring); 3062f2429c3SPan Bian return r; 3072f2429c3SPan Bian } 3081538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ring, false); 309f2ba57b5SChristian König } 310f2ba57b5SChristian König return 0; 311f2ba57b5SChristian König } 312f2ba57b5SChristian König 31360a7e396SChristian König void radeon_test_ring_sync(struct radeon_device *rdev, 314e32eb50dSChristian König struct radeon_ring *ringA, 315e32eb50dSChristian König struct radeon_ring *ringB) 31660a7e396SChristian König { 317ce954884SChristian König struct radeon_fence *fence1 = NULL, *fence2 = NULL; 31860a7e396SChristian König struct radeon_semaphore *semaphore = NULL; 31960a7e396SChristian König int r; 32060a7e396SChristian König 32160a7e396SChristian König r = radeon_semaphore_create(rdev, &semaphore); 32260a7e396SChristian König if (r) { 32360a7e396SChristian König DRM_ERROR("Failed to create semaphore\n"); 32460a7e396SChristian König goto out_cleanup; 32560a7e396SChristian König } 32660a7e396SChristian König 327e32eb50dSChristian König r = radeon_ring_lock(rdev, ringA, 64); 32860a7e396SChristian König if (r) { 3298b25ed34SAlex Deucher DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 33060a7e396SChristian König goto out_cleanup; 33160a7e396SChristian König } 3328b25ed34SAlex Deucher radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 3331538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringA, false); 334f2ba57b5SChristian König 335f2ba57b5SChristian König r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1); 336f2ba57b5SChristian König if (r) 337f2ba57b5SChristian König goto out_cleanup; 338f2ba57b5SChristian König 339f2ba57b5SChristian König r = radeon_ring_lock(rdev, ringA, 64); 340876dc9f3SChristian König if (r) { 341f2ba57b5SChristian König DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 342876dc9f3SChristian König goto out_cleanup; 343876dc9f3SChristian König } 3448b25ed34SAlex Deucher radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 3451538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringA, false); 34660a7e396SChristian König 347f2ba57b5SChristian König r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2); 348f2ba57b5SChristian König if (r) 349f2ba57b5SChristian König goto out_cleanup; 350f2ba57b5SChristian König 35160a7e396SChristian König mdelay(1000); 35260a7e396SChristian König 353ce954884SChristian König if (radeon_fence_signaled(fence1)) { 354ce954884SChristian König DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); 35560a7e396SChristian König goto out_cleanup; 35660a7e396SChristian König } 35760a7e396SChristian König 358e32eb50dSChristian König r = radeon_ring_lock(rdev, ringB, 64); 35960a7e396SChristian König if (r) { 360e32eb50dSChristian König DRM_ERROR("Failed to lock ring B %p\n", ringB); 36160a7e396SChristian König goto out_cleanup; 36260a7e396SChristian König } 3638b25ed34SAlex Deucher radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 3641538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringB, false); 36560a7e396SChristian König 366ce954884SChristian König r = radeon_fence_wait(fence1, false); 36760a7e396SChristian König if (r) { 368ce954884SChristian König DRM_ERROR("Failed to wait for sync fence 1\n"); 36960a7e396SChristian König goto out_cleanup; 37060a7e396SChristian König } 37160a7e396SChristian König 372ce954884SChristian König mdelay(1000); 373ce954884SChristian König 374ce954884SChristian König if (radeon_fence_signaled(fence2)) { 375ce954884SChristian König DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); 376ce954884SChristian König goto out_cleanup; 377ce954884SChristian König } 378ce954884SChristian König 379ce954884SChristian König r = radeon_ring_lock(rdev, ringB, 64); 380ce954884SChristian König if (r) { 381ce954884SChristian König DRM_ERROR("Failed to lock ring B %p\n", ringB); 382ce954884SChristian König goto out_cleanup; 383ce954884SChristian König } 3848b25ed34SAlex Deucher radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 3851538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringB, false); 386ce954884SChristian König 387ce954884SChristian König r = radeon_fence_wait(fence2, false); 388ce954884SChristian König if (r) { 389ce954884SChristian König DRM_ERROR("Failed to wait for sync fence 1\n"); 390ce954884SChristian König goto out_cleanup; 391ce954884SChristian König } 39260a7e396SChristian König 39360a7e396SChristian König out_cleanup: 394220907d9SChristian König radeon_semaphore_free(rdev, &semaphore, NULL); 39560a7e396SChristian König 396ce954884SChristian König if (fence1) 397ce954884SChristian König radeon_fence_unref(&fence1); 398ce954884SChristian König 399ce954884SChristian König if (fence2) 400ce954884SChristian König radeon_fence_unref(&fence2); 401ce954884SChristian König 402ce954884SChristian König if (r) 4037ca85295SJoe Perches pr_warn("Error while testing ring sync (%d)\n", r); 404ce954884SChristian König } 405ce954884SChristian König 4061109ca09SLauri Kasanen static void radeon_test_ring_sync2(struct radeon_device *rdev, 407ce954884SChristian König struct radeon_ring *ringA, 408ce954884SChristian König struct radeon_ring *ringB, 409ce954884SChristian König struct radeon_ring *ringC) 410ce954884SChristian König { 411ce954884SChristian König struct radeon_fence *fenceA = NULL, *fenceB = NULL; 412ce954884SChristian König struct radeon_semaphore *semaphore = NULL; 413ce954884SChristian König bool sigA, sigB; 414ce954884SChristian König int i, r; 415ce954884SChristian König 416ce954884SChristian König r = radeon_semaphore_create(rdev, &semaphore); 417ce954884SChristian König if (r) { 418ce954884SChristian König DRM_ERROR("Failed to create semaphore\n"); 419ce954884SChristian König goto out_cleanup; 420ce954884SChristian König } 421ce954884SChristian König 422ce954884SChristian König r = radeon_ring_lock(rdev, ringA, 64); 423ce954884SChristian König if (r) { 4248b25ed34SAlex Deucher DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 425ce954884SChristian König goto out_cleanup; 426ce954884SChristian König } 4278b25ed34SAlex Deucher radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 4281538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringA, false); 429ce954884SChristian König 430f2ba57b5SChristian König r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA); 431f2ba57b5SChristian König if (r) 432f2ba57b5SChristian König goto out_cleanup; 433f2ba57b5SChristian König 434ce954884SChristian König r = radeon_ring_lock(rdev, ringB, 64); 435ce954884SChristian König if (r) { 4368b25ed34SAlex Deucher DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); 437ce954884SChristian König goto out_cleanup; 438ce954884SChristian König } 4398b25ed34SAlex Deucher radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); 4401538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringB, false); 441f2ba57b5SChristian König r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB); 442f2ba57b5SChristian König if (r) 443f2ba57b5SChristian König goto out_cleanup; 444ce954884SChristian König 445ce954884SChristian König mdelay(1000); 446ce954884SChristian König 447ce954884SChristian König if (radeon_fence_signaled(fenceA)) { 448ce954884SChristian König DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 449ce954884SChristian König goto out_cleanup; 450ce954884SChristian König } 451ce954884SChristian König if (radeon_fence_signaled(fenceB)) { 452f2ba57b5SChristian König DRM_ERROR("Fence B signaled without waiting for semaphore.\n"); 453ce954884SChristian König goto out_cleanup; 454ce954884SChristian König } 455ce954884SChristian König 456ce954884SChristian König r = radeon_ring_lock(rdev, ringC, 64); 457ce954884SChristian König if (r) { 458ce954884SChristian König DRM_ERROR("Failed to lock ring B %p\n", ringC); 459ce954884SChristian König goto out_cleanup; 460ce954884SChristian König } 4618b25ed34SAlex Deucher radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 4621538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringC, false); 463ce954884SChristian König 464ce954884SChristian König for (i = 0; i < 30; ++i) { 465ce954884SChristian König mdelay(100); 466ce954884SChristian König sigA = radeon_fence_signaled(fenceA); 467ce954884SChristian König sigB = radeon_fence_signaled(fenceB); 468ce954884SChristian König if (sigA || sigB) 469ce954884SChristian König break; 470ce954884SChristian König } 471ce954884SChristian König 472ce954884SChristian König if (!sigA && !sigB) { 473ce954884SChristian König DRM_ERROR("Neither fence A nor B has been signaled\n"); 474ce954884SChristian König goto out_cleanup; 475ce954884SChristian König } else if (sigA && sigB) { 476ce954884SChristian König DRM_ERROR("Both fence A and B has been signaled\n"); 477ce954884SChristian König goto out_cleanup; 478ce954884SChristian König } 479ce954884SChristian König 480ce954884SChristian König DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); 481ce954884SChristian König 482ce954884SChristian König r = radeon_ring_lock(rdev, ringC, 64); 483ce954884SChristian König if (r) { 484ce954884SChristian König DRM_ERROR("Failed to lock ring B %p\n", ringC); 485ce954884SChristian König goto out_cleanup; 486ce954884SChristian König } 4878b25ed34SAlex Deucher radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 4881538a9e0SMichel Dänzer radeon_ring_unlock_commit(rdev, ringC, false); 489ce954884SChristian König 490ce954884SChristian König mdelay(1000); 491ce954884SChristian König 492ce954884SChristian König r = radeon_fence_wait(fenceA, false); 493ce954884SChristian König if (r) { 494ce954884SChristian König DRM_ERROR("Failed to wait for sync fence A\n"); 495ce954884SChristian König goto out_cleanup; 496ce954884SChristian König } 497ce954884SChristian König r = radeon_fence_wait(fenceB, false); 498ce954884SChristian König if (r) { 499ce954884SChristian König DRM_ERROR("Failed to wait for sync fence B\n"); 500ce954884SChristian König goto out_cleanup; 501ce954884SChristian König } 502ce954884SChristian König 503ce954884SChristian König out_cleanup: 504220907d9SChristian König radeon_semaphore_free(rdev, &semaphore, NULL); 505ce954884SChristian König 506ce954884SChristian König if (fenceA) 507ce954884SChristian König radeon_fence_unref(&fenceA); 508ce954884SChristian König 509ce954884SChristian König if (fenceB) 510ce954884SChristian König radeon_fence_unref(&fenceB); 51160a7e396SChristian König 51260a7e396SChristian König if (r) 5137ca85295SJoe Perches pr_warn("Error while testing ring sync (%d)\n", r); 51460a7e396SChristian König } 51560a7e396SChristian König 516d93f7937SChristian König static bool radeon_test_sync_possible(struct radeon_ring *ringA, 517d93f7937SChristian König struct radeon_ring *ringB) 518d93f7937SChristian König { 519d93f7937SChristian König if (ringA->idx == TN_RING_TYPE_VCE2_INDEX && 520d93f7937SChristian König ringB->idx == TN_RING_TYPE_VCE1_INDEX) 521d93f7937SChristian König return false; 522d93f7937SChristian König 523d93f7937SChristian König return true; 524d93f7937SChristian König } 525d93f7937SChristian König 52660a7e396SChristian König void radeon_test_syncing(struct radeon_device *rdev) 52760a7e396SChristian König { 528ce954884SChristian König int i, j, k; 52960a7e396SChristian König 53060a7e396SChristian König for (i = 1; i < RADEON_NUM_RINGS; ++i) { 531e32eb50dSChristian König struct radeon_ring *ringA = &rdev->ring[i]; 532e32eb50dSChristian König if (!ringA->ready) 53360a7e396SChristian König continue; 53460a7e396SChristian König 53560a7e396SChristian König for (j = 0; j < i; ++j) { 536e32eb50dSChristian König struct radeon_ring *ringB = &rdev->ring[j]; 537e32eb50dSChristian König if (!ringB->ready) 53860a7e396SChristian König continue; 53960a7e396SChristian König 540d93f7937SChristian König if (!radeon_test_sync_possible(ringA, ringB)) 541d93f7937SChristian König continue; 542d93f7937SChristian König 543ce954884SChristian König DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); 544e32eb50dSChristian König radeon_test_ring_sync(rdev, ringA, ringB); 54560a7e396SChristian König 546ce954884SChristian König DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); 547e32eb50dSChristian König radeon_test_ring_sync(rdev, ringB, ringA); 548ce954884SChristian König 549ce954884SChristian König for (k = 0; k < j; ++k) { 550ce954884SChristian König struct radeon_ring *ringC = &rdev->ring[k]; 5511f2e124dSAlex Deucher if (!ringC->ready) 5521f2e124dSAlex Deucher continue; 553ce954884SChristian König 554d93f7937SChristian König if (!radeon_test_sync_possible(ringA, ringC)) 555d93f7937SChristian König continue; 556d93f7937SChristian König 557d93f7937SChristian König if (!radeon_test_sync_possible(ringB, ringC)) 558d93f7937SChristian König continue; 559d93f7937SChristian König 560ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); 561ce954884SChristian König radeon_test_ring_sync2(rdev, ringA, ringB, ringC); 562ce954884SChristian König 563ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); 564ce954884SChristian König radeon_test_ring_sync2(rdev, ringA, ringC, ringB); 565ce954884SChristian König 566ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); 567ce954884SChristian König radeon_test_ring_sync2(rdev, ringB, ringA, ringC); 568ce954884SChristian König 569ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); 570ce954884SChristian König radeon_test_ring_sync2(rdev, ringB, ringC, ringA); 571ce954884SChristian König 572ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); 573ce954884SChristian König radeon_test_ring_sync2(rdev, ringC, ringA, ringB); 574ce954884SChristian König 575ce954884SChristian König DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); 576ce954884SChristian König radeon_test_ring_sync2(rdev, ringC, ringB, ringA); 577ce954884SChristian König } 57860a7e396SChristian König } 57960a7e396SChristian König } 58060a7e396SChristian König } 581