// SPDX-License-Identifier: GPL-2.0 OR MIT /* * Copyright 2009 VMware, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Michel Dänzer
*/
/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ staticvoid radeon_do_test_moves(struct radeon_device *rdev, int flag)
{ struct radeon_bo *vram_obj = NULL; struct radeon_bo **gtt_obj = NULL;
uint64_t gtt_addr, vram_addr; unsigned n, size; int i, r, ring;
switch (flag) { case RADEON_TEST_COPY_DMA:
ring = radeon_copy_dma_ring_index(rdev); break; case RADEON_TEST_COPY_BLIT:
ring = radeon_copy_blit_ring_index(rdev); break; default:
DRM_ERROR("Unknown copy method\n"); return;
}
size = 1024 * 1024;
/* Number of tests = * (Total GTT - IB pool - writeback page - ring buffers) / test size
*/
n = rdev->mc.gtt_size - rdev->gart_pin_size;
n /= size;
gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1; goto out_cleanup;
}
r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
0, NULL, NULL, &vram_obj); if (r) {
DRM_ERROR("Failed to create VRAM object\n"); goto out_cleanup;
}
r = radeon_bo_reserve(vram_obj, false); if (unlikely(r != 0)) goto out_unref;
r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); if (r) {
DRM_ERROR("Failed to pin VRAM object\n"); goto out_unres;
} for (i = 0; i < n; i++) { void *gtt_map, *vram_map; void **gtt_start, **gtt_end; void **vram_start, **vram_end; struct radeon_fence *fence = NULL;
r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL,
gtt_obj + i); if (r) {
DRM_ERROR("Failed to create GTT object %d\n", i); goto out_lclean;
}
r = radeon_bo_reserve(gtt_obj[i], false); if (unlikely(r != 0)) goto out_lclean_unref;
r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); if (r) {
DRM_ERROR("Failed to pin GTT object %d\n", i); goto out_lclean_unres;
}
r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) {
DRM_ERROR("Failed to map GTT object %d\n", i); goto out_lclean_unpin;
}
if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL); if (r) {
DRM_ERROR("Failed to get dummy create msg\n"); return r;
}
r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence); if (r) {
DRM_ERROR("Failed to get dummy destroy msg\n"); return r;
}
} elseif (ring->idx == TN_RING_TYPE_VCE1_INDEX ||
ring->idx == TN_RING_TYPE_VCE2_INDEX) {
r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL); if (r) {
DRM_ERROR("Failed to get dummy create msg\n"); return r;
}
r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence); if (r) {
DRM_ERROR("Failed to get dummy destroy msg\n"); return r;
}
} else {
r = radeon_ring_lock(rdev, ring, 64); if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ring->idx); return r;
}
r = radeon_fence_emit(rdev, fence, ring->idx); if (r) {
DRM_ERROR("Failed to emit fence\n");
radeon_ring_unlock_undo(rdev, ring); return r;
}
radeon_ring_unlock_commit(rdev, ring, false);
} return 0;
}
r = radeon_semaphore_create(rdev, &semaphore); if (r) {
DRM_ERROR("Failed to create semaphore\n"); goto out_cleanup;
}
r = radeon_ring_lock(rdev, ringA, 64); if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); goto out_cleanup;
}
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringA, false);
r = radeon_test_create_and_emit_fence(rdev, ringA, &fence1); if (r) goto out_cleanup;
r = radeon_ring_lock(rdev, ringA, 64); if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); goto out_cleanup;
}
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringA, false);
r = radeon_test_create_and_emit_fence(rdev, ringA, &fence2); if (r) goto out_cleanup;
msleep(1000);
if (radeon_fence_signaled(fence1)) {
DRM_ERROR("Fence 1 signaled without waiting for semaphore.\n"); goto out_cleanup;
}
r = radeon_ring_lock(rdev, ringB, 64); if (r) {
DRM_ERROR("Failed to lock ring B %p\n", ringB); goto out_cleanup;
}
radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringB, false);
r = radeon_fence_wait(fence1, false); if (r) {
DRM_ERROR("Failed to wait for sync fence 1\n"); goto out_cleanup;
}
msleep(1000);
if (radeon_fence_signaled(fence2)) {
DRM_ERROR("Fence 2 signaled without waiting for semaphore.\n"); goto out_cleanup;
}
r = radeon_ring_lock(rdev, ringB, 64); if (r) {
DRM_ERROR("Failed to lock ring B %p\n", ringB); goto out_cleanup;
}
radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringB, false);
r = radeon_fence_wait(fence2, false); if (r) {
DRM_ERROR("Failed to wait for sync fence 1\n"); goto out_cleanup;
}
r = radeon_semaphore_create(rdev, &semaphore); if (r) {
DRM_ERROR("Failed to create semaphore\n"); goto out_cleanup;
}
r = radeon_ring_lock(rdev, ringA, 64); if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); goto out_cleanup;
}
radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringA, false);
r = radeon_test_create_and_emit_fence(rdev, ringA, &fenceA); if (r) goto out_cleanup;
r = radeon_ring_lock(rdev, ringB, 64); if (r) {
DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); goto out_cleanup;
}
radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringB, false);
r = radeon_test_create_and_emit_fence(rdev, ringB, &fenceB); if (r) goto out_cleanup;
msleep(1000);
if (radeon_fence_signaled(fenceA)) {
DRM_ERROR("Fence A signaled without waiting for semaphore.\n"); goto out_cleanup;
} if (radeon_fence_signaled(fenceB)) {
DRM_ERROR("Fence B signaled without waiting for semaphore.\n"); goto out_cleanup;
}
r = radeon_ring_lock(rdev, ringC, 64); if (r) {
DRM_ERROR("Failed to lock ring B %p\n", ringC); goto out_cleanup;
}
radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringC, false);
for (i = 0; i < 30; ++i) {
msleep(100);
sigA = radeon_fence_signaled(fenceA);
sigB = radeon_fence_signaled(fenceB); if (sigA || sigB) break;
}
if (!sigA && !sigB) {
DRM_ERROR("Neither fence A nor B has been signaled\n"); goto out_cleanup;
} elseif (sigA && sigB) {
DRM_ERROR("Both fence A and B has been signaled\n"); goto out_cleanup;
}
DRM_INFO("Fence %c was first signaled\n", sigA ? 'A' : 'B');
r = radeon_ring_lock(rdev, ringC, 64); if (r) {
DRM_ERROR("Failed to lock ring B %p\n", ringC); goto out_cleanup;
}
radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringC, false);
msleep(1000);
r = radeon_fence_wait(fenceA, false); if (r) {
DRM_ERROR("Failed to wait for sync fence A\n"); goto out_cleanup;
}
r = radeon_fence_wait(fenceB, false); if (r) {
DRM_ERROR("Failed to wait for sync fence B\n"); goto out_cleanup;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.