162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2009 VMware, Inc. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1362306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Authors: Michel Dänzer 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <drm/radeon_drm.h> 2762306a36Sopenharmony_ci#include "radeon_reg.h" 2862306a36Sopenharmony_ci#include "radeon.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define RADEON_TEST_COPY_BLIT 1 3162306a36Sopenharmony_ci#define RADEON_TEST_COPY_DMA 0 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ 3562306a36Sopenharmony_cistatic void radeon_do_test_moves(struct radeon_device *rdev, int flag) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct radeon_bo *vram_obj = NULL; 3862306a36Sopenharmony_ci struct radeon_bo **gtt_obj = NULL; 3962306a36Sopenharmony_ci uint64_t gtt_addr, vram_addr; 4062306a36Sopenharmony_ci unsigned n, size; 4162306a36Sopenharmony_ci int i, r, ring; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci switch (flag) { 4462306a36Sopenharmony_ci case RADEON_TEST_COPY_DMA: 4562306a36Sopenharmony_ci ring = radeon_copy_dma_ring_index(rdev); 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci case RADEON_TEST_COPY_BLIT: 4862306a36Sopenharmony_ci ring = radeon_copy_blit_ring_index(rdev); 4962306a36Sopenharmony_ci break; 5062306a36Sopenharmony_ci default: 5162306a36Sopenharmony_ci DRM_ERROR("Unknown copy method\n"); 5262306a36Sopenharmony_ci return; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci size = 1024 * 1024; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Number of tests = 5862306a36Sopenharmony_ci * (Total GTT - IB pool - writeback page - ring buffers) / test size 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci n = rdev->mc.gtt_size - rdev->gart_pin_size; 6162306a36Sopenharmony_ci n /= size; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL); 6462306a36Sopenharmony_ci if (!gtt_obj) { 6562306a36Sopenharmony_ci DRM_ERROR("Failed to allocate %d pointers\n", n); 6662306a36Sopenharmony_ci r = 1; 6762306a36Sopenharmony_ci goto out_cleanup; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 7162306a36Sopenharmony_ci 0, NULL, NULL, &vram_obj); 7262306a36Sopenharmony_ci if (r) { 7362306a36Sopenharmony_ci DRM_ERROR("Failed to create VRAM object\n"); 7462306a36Sopenharmony_ci goto out_cleanup; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci r = radeon_bo_reserve(vram_obj, false); 7762306a36Sopenharmony_ci if (unlikely(r != 0)) 7862306a36Sopenharmony_ci goto out_unref; 7962306a36Sopenharmony_ci r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); 8062306a36Sopenharmony_ci if (r) { 8162306a36Sopenharmony_ci DRM_ERROR("Failed to pin VRAM object\n"); 8262306a36Sopenharmony_ci goto out_unres; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci for (i = 0; i < n; i++) { 8562306a36Sopenharmony_ci void *gtt_map, *vram_map; 8662306a36Sopenharmony_ci void **gtt_start, **gtt_end; 8762306a36Sopenharmony_ci void **vram_start, **vram_end; 8862306a36Sopenharmony_ci struct radeon_fence *fence = NULL; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci r = radeon_bo_create(rdev, size, PAGE_SIZE, true, 9162306a36Sopenharmony_ci RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, 9262306a36Sopenharmony_ci gtt_obj + i); 9362306a36Sopenharmony_ci if (r) { 9462306a36Sopenharmony_ci DRM_ERROR("Failed to create GTT object %d\n", i); 9562306a36Sopenharmony_ci goto out_lclean; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci r = radeon_bo_reserve(gtt_obj[i], false); 9962306a36Sopenharmony_ci if (unlikely(r != 0)) 10062306a36Sopenharmony_ci goto out_lclean_unref; 10162306a36Sopenharmony_ci r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); 10262306a36Sopenharmony_ci if (r) { 10362306a36Sopenharmony_ci DRM_ERROR("Failed to pin GTT object %d\n", i); 10462306a36Sopenharmony_ci goto out_lclean_unres; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci r = radeon_bo_kmap(gtt_obj[i], >t_map); 10862306a36Sopenharmony_ci if (r) { 10962306a36Sopenharmony_ci DRM_ERROR("Failed to map GTT object %d\n", i); 11062306a36Sopenharmony_ci goto out_lclean_unpin; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci for (gtt_start = gtt_map, gtt_end = gtt_map + size; 11462306a36Sopenharmony_ci gtt_start < gtt_end; 11562306a36Sopenharmony_ci gtt_start++) 11662306a36Sopenharmony_ci *gtt_start = gtt_start; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci radeon_bo_kunmap(gtt_obj[i]); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (ring == R600_RING_TYPE_DMA_INDEX) 12162306a36Sopenharmony_ci fence = radeon_copy_dma(rdev, gtt_addr, vram_addr, 12262306a36Sopenharmony_ci size / RADEON_GPU_PAGE_SIZE, 12362306a36Sopenharmony_ci vram_obj->tbo.base.resv); 12462306a36Sopenharmony_ci else 12562306a36Sopenharmony_ci fence = radeon_copy_blit(rdev, gtt_addr, vram_addr, 12662306a36Sopenharmony_ci size / RADEON_GPU_PAGE_SIZE, 12762306a36Sopenharmony_ci vram_obj->tbo.base.resv); 12862306a36Sopenharmony_ci if (IS_ERR(fence)) { 12962306a36Sopenharmony_ci DRM_ERROR("Failed GTT->VRAM copy %d\n", i); 13062306a36Sopenharmony_ci r = PTR_ERR(fence); 13162306a36Sopenharmony_ci goto out_lclean_unpin; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci r = radeon_fence_wait(fence, false); 13562306a36Sopenharmony_ci if (r) { 13662306a36Sopenharmony_ci DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); 13762306a36Sopenharmony_ci goto out_lclean_unpin; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci radeon_fence_unref(&fence); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci r = radeon_bo_kmap(vram_obj, &vram_map); 14362306a36Sopenharmony_ci if (r) { 14462306a36Sopenharmony_ci DRM_ERROR("Failed to map VRAM object after copy %d\n", i); 14562306a36Sopenharmony_ci goto out_lclean_unpin; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci for (gtt_start = gtt_map, gtt_end = gtt_map + size, 14962306a36Sopenharmony_ci vram_start = vram_map, vram_end = vram_map + size; 15062306a36Sopenharmony_ci vram_start < vram_end; 15162306a36Sopenharmony_ci gtt_start++, vram_start++) { 15262306a36Sopenharmony_ci if (*vram_start != gtt_start) { 15362306a36Sopenharmony_ci DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " 15462306a36Sopenharmony_ci "expected 0x%p (GTT/VRAM offset " 15562306a36Sopenharmony_ci "0x%16llx/0x%16llx)\n", 15662306a36Sopenharmony_ci i, *vram_start, gtt_start, 15762306a36Sopenharmony_ci (unsigned long long) 15862306a36Sopenharmony_ci (gtt_addr - rdev->mc.gtt_start + 15962306a36Sopenharmony_ci (void *)gtt_start - gtt_map), 16062306a36Sopenharmony_ci (unsigned long long) 16162306a36Sopenharmony_ci (vram_addr - rdev->mc.vram_start + 16262306a36Sopenharmony_ci (void *)gtt_start - gtt_map)); 16362306a36Sopenharmony_ci radeon_bo_kunmap(vram_obj); 16462306a36Sopenharmony_ci goto out_lclean_unpin; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci *vram_start = vram_start; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci radeon_bo_kunmap(vram_obj); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (ring == R600_RING_TYPE_DMA_INDEX) 17262306a36Sopenharmony_ci fence = radeon_copy_dma(rdev, vram_addr, gtt_addr, 17362306a36Sopenharmony_ci size / RADEON_GPU_PAGE_SIZE, 17462306a36Sopenharmony_ci vram_obj->tbo.base.resv); 17562306a36Sopenharmony_ci else 17662306a36Sopenharmony_ci fence = radeon_copy_blit(rdev, vram_addr, gtt_addr, 17762306a36Sopenharmony_ci size / RADEON_GPU_PAGE_SIZE, 17862306a36Sopenharmony_ci vram_obj->tbo.base.resv); 17962306a36Sopenharmony_ci if (IS_ERR(fence)) { 18062306a36Sopenharmony_ci DRM_ERROR("Failed VRAM->GTT copy %d\n", i); 18162306a36Sopenharmony_ci r = PTR_ERR(fence); 18262306a36Sopenharmony_ci goto out_lclean_unpin; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci r = radeon_fence_wait(fence, false); 18662306a36Sopenharmony_ci if (r) { 18762306a36Sopenharmony_ci DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); 18862306a36Sopenharmony_ci goto out_lclean_unpin; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci radeon_fence_unref(&fence); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci r = radeon_bo_kmap(gtt_obj[i], >t_map); 19462306a36Sopenharmony_ci if (r) { 19562306a36Sopenharmony_ci DRM_ERROR("Failed to map GTT object after copy %d\n", i); 19662306a36Sopenharmony_ci goto out_lclean_unpin; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci for (gtt_start = gtt_map, gtt_end = gtt_map + size, 20062306a36Sopenharmony_ci vram_start = vram_map, vram_end = vram_map + size; 20162306a36Sopenharmony_ci gtt_start < gtt_end; 20262306a36Sopenharmony_ci gtt_start++, vram_start++) { 20362306a36Sopenharmony_ci if (*gtt_start != vram_start) { 20462306a36Sopenharmony_ci DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " 20562306a36Sopenharmony_ci "expected 0x%p (VRAM/GTT offset " 20662306a36Sopenharmony_ci "0x%16llx/0x%16llx)\n", 20762306a36Sopenharmony_ci i, *gtt_start, vram_start, 20862306a36Sopenharmony_ci (unsigned long long) 20962306a36Sopenharmony_ci (vram_addr - rdev->mc.vram_start + 21062306a36Sopenharmony_ci (void *)vram_start - vram_map), 21162306a36Sopenharmony_ci (unsigned long long) 21262306a36Sopenharmony_ci (gtt_addr - rdev->mc.gtt_start + 21362306a36Sopenharmony_ci (void *)vram_start - vram_map)); 21462306a36Sopenharmony_ci radeon_bo_kunmap(gtt_obj[i]); 21562306a36Sopenharmony_ci goto out_lclean_unpin; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci radeon_bo_kunmap(gtt_obj[i]); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", 22262306a36Sopenharmony_ci gtt_addr - rdev->mc.gtt_start); 22362306a36Sopenharmony_ci continue; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ciout_lclean_unpin: 22662306a36Sopenharmony_ci radeon_bo_unpin(gtt_obj[i]); 22762306a36Sopenharmony_ciout_lclean_unres: 22862306a36Sopenharmony_ci radeon_bo_unreserve(gtt_obj[i]); 22962306a36Sopenharmony_ciout_lclean_unref: 23062306a36Sopenharmony_ci radeon_bo_unref(>t_obj[i]); 23162306a36Sopenharmony_ciout_lclean: 23262306a36Sopenharmony_ci for (--i; i >= 0; --i) { 23362306a36Sopenharmony_ci radeon_bo_unpin(gtt_obj[i]); 23462306a36Sopenharmony_ci radeon_bo_unreserve(gtt_obj[i]); 23562306a36Sopenharmony_ci radeon_bo_unref(>t_obj[i]); 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci if (fence && !IS_ERR(fence)) 23862306a36Sopenharmony_ci radeon_fence_unref(&fence); 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci radeon_bo_unpin(vram_obj); 24362306a36Sopenharmony_ciout_unres: 24462306a36Sopenharmony_ci radeon_bo_unreserve(vram_obj); 24562306a36Sopenharmony_ciout_unref: 24662306a36Sopenharmony_ci radeon_bo_unref(&vram_obj); 24762306a36Sopenharmony_ciout_cleanup: 24862306a36Sopenharmony_ci kfree(gtt_obj); 24962306a36Sopenharmony_ci if (r) { 25062306a36Sopenharmony_ci pr_warn("Error while testing BO move\n"); 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_civoid radeon_test_moves(struct radeon_device *rdev) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci if (rdev->asic->copy.dma) 25762306a36Sopenharmony_ci radeon_do_test_moves(rdev, RADEON_TEST_COPY_DMA); 25862306a36Sopenharmony_ci if (rdev->asic->copy.blit) 25962306a36Sopenharmony_ci radeon_do_test_moves(rdev, RADEON_TEST_COPY_BLIT); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int radeon_test_create_and_emit_fence(struct radeon_device *rdev, 26362306a36Sopenharmony_ci struct radeon_ring *ring, 26462306a36Sopenharmony_ci struct radeon_fence **fence) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci uint32_t handle = ring->idx ^ 0xdeafbeef; 26762306a36Sopenharmony_ci int r; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (ring->idx == R600_RING_TYPE_UVD_INDEX) { 27062306a36Sopenharmony_ci r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL); 27162306a36Sopenharmony_ci if (r) { 27262306a36Sopenharmony_ci DRM_ERROR("Failed to get dummy create msg\n"); 27362306a36Sopenharmony_ci return r; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence); 27762306a36Sopenharmony_ci if (r) { 27862306a36Sopenharmony_ci DRM_ERROR("Failed to get dummy destroy msg\n"); 27962306a36Sopenharmony_ci return r; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX || 28362306a36Sopenharmony_ci ring->idx == TN_RING_TYPE_VCE2_INDEX) { 28462306a36Sopenharmony_ci r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL); 28562306a36Sopenharmony_ci if (r) { 28662306a36Sopenharmony_ci DRM_ERROR("Failed to get dummy create msg\n"); 28762306a36Sopenharmony_ci return r; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence); 29162306a36Sopenharmony_ci if (r) { 29262306a36Sopenharmony_ci DRM_ERROR("Failed to get dummy destroy msg\n"); 29362306a36Sopenharmony_ci return r; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci } else { 29762306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 64); 29862306a36Sopenharmony_ci if (r) { 29962306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring A %d\n", ring->idx); 30062306a36Sopenharmony_ci return r; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci r = radeon_fence_emit(rdev, fence, ring->idx); 30362306a36Sopenharmony_ci if (r) { 30462306a36Sopenharmony_ci DRM_ERROR("Failed to emit fence\n"); 30562306a36Sopenharmony_ci radeon_ring_unlock_undo(rdev, ring); 30662306a36Sopenharmony_ci return r; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci return 0; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_civoid radeon_test_ring_sync(struct radeon_device *rdev, 31462306a36Sopenharmony_ci struct radeon_ring *ringA, 31562306a36Sopenharmony_ci struct radeon_ring *ringB) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct radeon_fence *fence1 = NULL, *fence2 = NULL; 31862306a36Sopenharmony_ci struct radeon_semaphore *semaphore = NULL; 31962306a36Sopenharmony_ci int r; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci r = radeon_semaphore_create(rdev, &semaphore); 32262306a36Sopenharmony_ci if (r) { 32362306a36Sopenharmony_ci DRM_ERROR("Failed to create semaphore\n"); 32462306a36Sopenharmony_ci goto out_cleanup; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringA, 64); 32862306a36Sopenharmony_ci if (r) { 32962306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 33062306a36Sopenharmony_ci goto out_cleanup; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 33362306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringA, false); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1); 33662306a36Sopenharmony_ci if (r) 33762306a36Sopenharmony_ci goto out_cleanup; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringA, 64); 34062306a36Sopenharmony_ci if (r) { 34162306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 34262306a36Sopenharmony_ci goto out_cleanup; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 34562306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringA, false); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2); 34862306a36Sopenharmony_ci if (r) 34962306a36Sopenharmony_ci goto out_cleanup; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci msleep(1000); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (radeon_fence_signaled(fence1)) { 35462306a36Sopenharmony_ci DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); 35562306a36Sopenharmony_ci goto out_cleanup; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringB, 64); 35962306a36Sopenharmony_ci if (r) { 36062306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring B %p\n", ringB); 36162306a36Sopenharmony_ci goto out_cleanup; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 36462306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringB, false); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci r = radeon_fence_wait(fence1, false); 36762306a36Sopenharmony_ci if (r) { 36862306a36Sopenharmony_ci DRM_ERROR("Failed to wait for sync fence 1\n"); 36962306a36Sopenharmony_ci goto out_cleanup; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci msleep(1000); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (radeon_fence_signaled(fence2)) { 37562306a36Sopenharmony_ci DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); 37662306a36Sopenharmony_ci goto out_cleanup; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringB, 64); 38062306a36Sopenharmony_ci if (r) { 38162306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring B %p\n", ringB); 38262306a36Sopenharmony_ci goto out_cleanup; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); 38562306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringB, false); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci r = radeon_fence_wait(fence2, false); 38862306a36Sopenharmony_ci if (r) { 38962306a36Sopenharmony_ci DRM_ERROR("Failed to wait for sync fence 1\n"); 39062306a36Sopenharmony_ci goto out_cleanup; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciout_cleanup: 39462306a36Sopenharmony_ci radeon_semaphore_free(rdev, &semaphore, NULL); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci if (fence1) 39762306a36Sopenharmony_ci radeon_fence_unref(&fence1); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (fence2) 40062306a36Sopenharmony_ci radeon_fence_unref(&fence2); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (r) 40362306a36Sopenharmony_ci pr_warn("Error while testing ring sync (%d)\n", r); 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic void radeon_test_ring_sync2(struct radeon_device *rdev, 40762306a36Sopenharmony_ci struct radeon_ring *ringA, 40862306a36Sopenharmony_ci struct radeon_ring *ringB, 40962306a36Sopenharmony_ci struct radeon_ring *ringC) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct radeon_fence *fenceA = NULL, *fenceB = NULL; 41262306a36Sopenharmony_ci struct radeon_semaphore *semaphore = NULL; 41362306a36Sopenharmony_ci bool sigA, sigB; 41462306a36Sopenharmony_ci int i, r; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci r = radeon_semaphore_create(rdev, &semaphore); 41762306a36Sopenharmony_ci if (r) { 41862306a36Sopenharmony_ci DRM_ERROR("Failed to create semaphore\n"); 41962306a36Sopenharmony_ci goto out_cleanup; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringA, 64); 42362306a36Sopenharmony_ci if (r) { 42462306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); 42562306a36Sopenharmony_ci goto out_cleanup; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); 42862306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringA, false); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA); 43162306a36Sopenharmony_ci if (r) 43262306a36Sopenharmony_ci goto out_cleanup; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringB, 64); 43562306a36Sopenharmony_ci if (r) { 43662306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); 43762306a36Sopenharmony_ci goto out_cleanup; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); 44062306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringB, false); 44162306a36Sopenharmony_ci r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB); 44262306a36Sopenharmony_ci if (r) 44362306a36Sopenharmony_ci goto out_cleanup; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci msleep(1000); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci if (radeon_fence_signaled(fenceA)) { 44862306a36Sopenharmony_ci DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); 44962306a36Sopenharmony_ci goto out_cleanup; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci if (radeon_fence_signaled(fenceB)) { 45262306a36Sopenharmony_ci DRM_ERROR("Fence B signaled without waiting for semaphore.\n"); 45362306a36Sopenharmony_ci goto out_cleanup; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringC, 64); 45762306a36Sopenharmony_ci if (r) { 45862306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring B %p\n", ringC); 45962306a36Sopenharmony_ci goto out_cleanup; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 46262306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringC, false); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci for (i = 0; i < 30; ++i) { 46562306a36Sopenharmony_ci msleep(100); 46662306a36Sopenharmony_ci sigA = radeon_fence_signaled(fenceA); 46762306a36Sopenharmony_ci sigB = radeon_fence_signaled(fenceB); 46862306a36Sopenharmony_ci if (sigA || sigB) 46962306a36Sopenharmony_ci break; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (!sigA && !sigB) { 47362306a36Sopenharmony_ci DRM_ERROR("Neither fence A nor B has been signaled\n"); 47462306a36Sopenharmony_ci goto out_cleanup; 47562306a36Sopenharmony_ci } else if (sigA && sigB) { 47662306a36Sopenharmony_ci DRM_ERROR("Both fence A and B has been signaled\n"); 47762306a36Sopenharmony_ci goto out_cleanup; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B'); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ringC, 64); 48362306a36Sopenharmony_ci if (r) { 48462306a36Sopenharmony_ci DRM_ERROR("Failed to lock ring B %p\n", ringC); 48562306a36Sopenharmony_ci goto out_cleanup; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); 48862306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ringC, false); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci msleep(1000); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci r = radeon_fence_wait(fenceA, false); 49362306a36Sopenharmony_ci if (r) { 49462306a36Sopenharmony_ci DRM_ERROR("Failed to wait for sync fence A\n"); 49562306a36Sopenharmony_ci goto out_cleanup; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci r = radeon_fence_wait(fenceB, false); 49862306a36Sopenharmony_ci if (r) { 49962306a36Sopenharmony_ci DRM_ERROR("Failed to wait for sync fence B\n"); 50062306a36Sopenharmony_ci goto out_cleanup; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ciout_cleanup: 50462306a36Sopenharmony_ci radeon_semaphore_free(rdev, &semaphore, NULL); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (fenceA) 50762306a36Sopenharmony_ci radeon_fence_unref(&fenceA); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci if (fenceB) 51062306a36Sopenharmony_ci radeon_fence_unref(&fenceB); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (r) 51362306a36Sopenharmony_ci pr_warn("Error while testing ring sync (%d)\n", r); 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic bool radeon_test_sync_possible(struct radeon_ring *ringA, 51762306a36Sopenharmony_ci struct radeon_ring *ringB) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci if (ringA->idx == TN_RING_TYPE_VCE2_INDEX && 52062306a36Sopenharmony_ci ringB->idx == TN_RING_TYPE_VCE1_INDEX) 52162306a36Sopenharmony_ci return false; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return true; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_civoid radeon_test_syncing(struct radeon_device *rdev) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci int i, j, k; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci for (i = 1; i < RADEON_NUM_RINGS; ++i) { 53162306a36Sopenharmony_ci struct radeon_ring *ringA = &rdev->ring[i]; 53262306a36Sopenharmony_ci if (!ringA->ready) 53362306a36Sopenharmony_ci continue; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci for (j = 0; j < i; ++j) { 53662306a36Sopenharmony_ci struct radeon_ring *ringB = &rdev->ring[j]; 53762306a36Sopenharmony_ci if (!ringB->ready) 53862306a36Sopenharmony_ci continue; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (!radeon_test_sync_possible(ringA, ringB)) 54162306a36Sopenharmony_ci continue; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); 54462306a36Sopenharmony_ci radeon_test_ring_sync(rdev, ringA, ringB); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d and %d...\n", j, i); 54762306a36Sopenharmony_ci radeon_test_ring_sync(rdev, ringB, ringA); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci for (k = 0; k < j; ++k) { 55062306a36Sopenharmony_ci struct radeon_ring *ringC = &rdev->ring[k]; 55162306a36Sopenharmony_ci if (!ringC->ready) 55262306a36Sopenharmony_ci continue; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (!radeon_test_sync_possible(ringA, ringC)) 55562306a36Sopenharmony_ci continue; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (!radeon_test_sync_possible(ringB, ringC)) 55862306a36Sopenharmony_ci continue; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); 56162306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringA, ringB, ringC); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, k, j); 56462306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringA, ringC, ringB); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, i, k); 56762306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringB, ringA, ringC); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", j, k, i); 57062306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringB, ringC, ringA); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, i, j); 57362306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringC, ringA, ringB); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci DRM_INFO("Testing syncing between rings %d, %d and %d...\n", k, j, i); 57662306a36Sopenharmony_ci radeon_test_ring_sync2(rdev, ringC, ringB, ringA); 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci} 581