18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci * Christian König 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 308c2ecf20Sopenharmony_ci#include <linux/slab.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <drm/amdgpu_drm.h> 338c2ecf20Sopenharmony_ci#include <drm/drm_debugfs.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include "amdgpu.h" 368c2ecf20Sopenharmony_ci#include "atom.h" 378c2ecf20Sopenharmony_ci#include "amdgpu_trace.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define AMDGPU_IB_TEST_TIMEOUT msecs_to_jiffies(1000) 408c2ecf20Sopenharmony_ci#define AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT msecs_to_jiffies(2000) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * IB 448c2ecf20Sopenharmony_ci * IBs (Indirect Buffers) and areas of GPU accessible memory where 458c2ecf20Sopenharmony_ci * commands are stored. You can put a pointer to the IB in the 468c2ecf20Sopenharmony_ci * command ring and the hw will fetch the commands from the IB 478c2ecf20Sopenharmony_ci * and execute them. Generally userspace acceleration drivers 488c2ecf20Sopenharmony_ci * produce command buffers which are send to the kernel and 498c2ecf20Sopenharmony_ci * put in IBs for execution by the requested ring. 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/** 538c2ecf20Sopenharmony_ci * amdgpu_ib_get - request an IB (Indirect Buffer) 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * @ring: ring index the IB is associated with 568c2ecf20Sopenharmony_ci * @size: requested IB size 578c2ecf20Sopenharmony_ci * @ib: IB object returned 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Request an IB (all asics). IBs are allocated using the 608c2ecf20Sopenharmony_ci * suballocator. 618c2ecf20Sopenharmony_ci * Returns 0 on success, error on failure. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ciint amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, 648c2ecf20Sopenharmony_ci unsigned size, enum amdgpu_ib_pool_type pool_type, 658c2ecf20Sopenharmony_ci struct amdgpu_ib *ib) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci int r; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (size) { 708c2ecf20Sopenharmony_ci r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type], 718c2ecf20Sopenharmony_ci &ib->sa_bo, size, 256); 728c2ecf20Sopenharmony_ci if (r) { 738c2ecf20Sopenharmony_ci dev_err(adev->dev, "failed to get a new IB (%d)\n", r); 748c2ecf20Sopenharmony_ci return r; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo); 788c2ecf20Sopenharmony_ci /* flush the cache before commit the IB */ 798c2ecf20Sopenharmony_ci ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (!vm) 828c2ecf20Sopenharmony_ci ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/** 898c2ecf20Sopenharmony_ci * amdgpu_ib_free - free an IB (Indirect Buffer) 908c2ecf20Sopenharmony_ci * 918c2ecf20Sopenharmony_ci * @adev: amdgpu_device pointer 928c2ecf20Sopenharmony_ci * @ib: IB object to free 938c2ecf20Sopenharmony_ci * @f: the fence SA bo need wait on for the ib alloation 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * Free an IB (all asics). 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_civoid amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, 988c2ecf20Sopenharmony_ci struct dma_fence *f) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci amdgpu_sa_bo_free(adev, &ib->sa_bo, f); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/** 1048c2ecf20Sopenharmony_ci * amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring 1058c2ecf20Sopenharmony_ci * 1068c2ecf20Sopenharmony_ci * @adev: amdgpu_device pointer 1078c2ecf20Sopenharmony_ci * @num_ibs: number of IBs to schedule 1088c2ecf20Sopenharmony_ci * @ibs: IB objects to schedule 1098c2ecf20Sopenharmony_ci * @f: fence created during this submission 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * Schedule an IB on the associated ring (all asics). 1128c2ecf20Sopenharmony_ci * Returns 0 on success, error on failure. 1138c2ecf20Sopenharmony_ci * 1148c2ecf20Sopenharmony_ci * On SI, there are two parallel engines fed from the primary ring, 1158c2ecf20Sopenharmony_ci * the CE (Constant Engine) and the DE (Drawing Engine). Since 1168c2ecf20Sopenharmony_ci * resource descriptors have moved to memory, the CE allows you to 1178c2ecf20Sopenharmony_ci * prime the caches while the DE is updating register state so that 1188c2ecf20Sopenharmony_ci * the resource descriptors will be already in cache when the draw is 1198c2ecf20Sopenharmony_ci * processed. To accomplish this, the userspace driver submits two 1208c2ecf20Sopenharmony_ci * IBs, one for the CE and one for the DE. If there is a CE IB (called 1218c2ecf20Sopenharmony_ci * a CONST_IB), it will be put on the ring prior to the DE IB. Prior 1228c2ecf20Sopenharmony_ci * to SI there was just a DE IB. 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_ciint amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, 1258c2ecf20Sopenharmony_ci struct amdgpu_ib *ibs, struct amdgpu_job *job, 1268c2ecf20Sopenharmony_ci struct dma_fence **f) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci struct amdgpu_device *adev = ring->adev; 1298c2ecf20Sopenharmony_ci struct amdgpu_ib *ib = &ibs[0]; 1308c2ecf20Sopenharmony_ci struct dma_fence *tmp = NULL; 1318c2ecf20Sopenharmony_ci bool need_ctx_switch; 1328c2ecf20Sopenharmony_ci unsigned patch_offset = ~0; 1338c2ecf20Sopenharmony_ci struct amdgpu_vm *vm; 1348c2ecf20Sopenharmony_ci uint64_t fence_ctx; 1358c2ecf20Sopenharmony_ci uint32_t status = 0, alloc_size; 1368c2ecf20Sopenharmony_ci unsigned fence_flags = 0; 1378c2ecf20Sopenharmony_ci bool secure; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci unsigned i; 1408c2ecf20Sopenharmony_ci int r = 0; 1418c2ecf20Sopenharmony_ci bool need_pipe_sync = false; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (num_ibs == 0) 1448c2ecf20Sopenharmony_ci return -EINVAL; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* ring tests don't use a job */ 1478c2ecf20Sopenharmony_ci if (job) { 1488c2ecf20Sopenharmony_ci vm = job->vm; 1498c2ecf20Sopenharmony_ci fence_ctx = job->base.s_fence ? 1508c2ecf20Sopenharmony_ci job->base.s_fence->scheduled.context : 0; 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci vm = NULL; 1538c2ecf20Sopenharmony_ci fence_ctx = 0; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (!ring->sched.ready) { 1578c2ecf20Sopenharmony_ci dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name); 1588c2ecf20Sopenharmony_ci return -EINVAL; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (vm && !job->vmid) { 1628c2ecf20Sopenharmony_ci dev_err(adev->dev, "VM IB without ID\n"); 1638c2ecf20Sopenharmony_ci return -EINVAL; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) && 1678c2ecf20Sopenharmony_ci (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE)) { 1688c2ecf20Sopenharmony_ci dev_err(adev->dev, "secure submissions not supported on compute rings\n"); 1698c2ecf20Sopenharmony_ci return -EINVAL; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci alloc_size = ring->funcs->emit_frame_size + num_ibs * 1738c2ecf20Sopenharmony_ci ring->funcs->emit_ib_size; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci r = amdgpu_ring_alloc(ring, alloc_size); 1768c2ecf20Sopenharmony_ci if (r) { 1778c2ecf20Sopenharmony_ci dev_err(adev->dev, "scheduling IB failed (%d).\n", r); 1788c2ecf20Sopenharmony_ci return r; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci need_ctx_switch = ring->current_ctx != fence_ctx; 1828c2ecf20Sopenharmony_ci if (ring->funcs->emit_pipeline_sync && job && 1838c2ecf20Sopenharmony_ci ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) || 1848c2ecf20Sopenharmony_ci (amdgpu_sriov_vf(adev) && need_ctx_switch) || 1858c2ecf20Sopenharmony_ci amdgpu_vm_need_pipeline_sync(ring, job))) { 1868c2ecf20Sopenharmony_ci need_pipe_sync = true; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (tmp) 1898c2ecf20Sopenharmony_ci trace_amdgpu_ib_pipe_sync(job, tmp); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci dma_fence_put(tmp); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync) 1958c2ecf20Sopenharmony_ci ring->funcs->emit_mem_sync(ring); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (ring->funcs->insert_start) 1988c2ecf20Sopenharmony_ci ring->funcs->insert_start(ring); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (job) { 2018c2ecf20Sopenharmony_ci r = amdgpu_vm_flush(ring, job, need_pipe_sync); 2028c2ecf20Sopenharmony_ci if (r) { 2038c2ecf20Sopenharmony_ci amdgpu_ring_undo(ring); 2048c2ecf20Sopenharmony_ci return r; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (job && ring->funcs->init_cond_exec) 2098c2ecf20Sopenharmony_ci patch_offset = amdgpu_ring_init_cond_exec(ring); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 2128c2ecf20Sopenharmony_ci if (!(adev->flags & AMD_IS_APU)) 2138c2ecf20Sopenharmony_ci#endif 2148c2ecf20Sopenharmony_ci { 2158c2ecf20Sopenharmony_ci if (ring->funcs->emit_hdp_flush) 2168c2ecf20Sopenharmony_ci amdgpu_ring_emit_hdp_flush(ring); 2178c2ecf20Sopenharmony_ci else 2188c2ecf20Sopenharmony_ci amdgpu_asic_flush_hdp(adev, ring); 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (need_ctx_switch) 2228c2ecf20Sopenharmony_ci status |= AMDGPU_HAVE_CTX_SWITCH; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (job && ring->funcs->emit_cntxcntl) { 2258c2ecf20Sopenharmony_ci status |= job->preamble_status; 2268c2ecf20Sopenharmony_ci status |= job->preemption_status; 2278c2ecf20Sopenharmony_ci amdgpu_ring_emit_cntxcntl(ring, status); 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Setup initial TMZiness and send it off. 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_ci secure = false; 2338c2ecf20Sopenharmony_ci if (job && ring->funcs->emit_frame_cntl) { 2348c2ecf20Sopenharmony_ci secure = ib->flags & AMDGPU_IB_FLAGS_SECURE; 2358c2ecf20Sopenharmony_ci amdgpu_ring_emit_frame_cntl(ring, true, secure); 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci for (i = 0; i < num_ibs; ++i) { 2398c2ecf20Sopenharmony_ci ib = &ibs[i]; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (job && ring->funcs->emit_frame_cntl) { 2428c2ecf20Sopenharmony_ci if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) { 2438c2ecf20Sopenharmony_ci amdgpu_ring_emit_frame_cntl(ring, false, secure); 2448c2ecf20Sopenharmony_ci secure = !secure; 2458c2ecf20Sopenharmony_ci amdgpu_ring_emit_frame_cntl(ring, true, secure); 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci amdgpu_ring_emit_ib(ring, job, ib, status); 2508c2ecf20Sopenharmony_ci status &= ~AMDGPU_HAVE_CTX_SWITCH; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (job && ring->funcs->emit_frame_cntl) 2548c2ecf20Sopenharmony_ci amdgpu_ring_emit_frame_cntl(ring, false, secure); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 2578c2ecf20Sopenharmony_ci if (!(adev->flags & AMD_IS_APU)) 2588c2ecf20Sopenharmony_ci#endif 2598c2ecf20Sopenharmony_ci amdgpu_asic_invalidate_hdp(adev, ring); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE) 2628c2ecf20Sopenharmony_ci fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* wrap the last IB with fence */ 2658c2ecf20Sopenharmony_ci if (job && job->uf_addr) { 2668c2ecf20Sopenharmony_ci amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence, 2678c2ecf20Sopenharmony_ci fence_flags | AMDGPU_FENCE_FLAG_64BIT); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci r = amdgpu_fence_emit(ring, f, fence_flags); 2718c2ecf20Sopenharmony_ci if (r) { 2728c2ecf20Sopenharmony_ci dev_err(adev->dev, "failed to emit fence (%d)\n", r); 2738c2ecf20Sopenharmony_ci if (job && job->vmid) 2748c2ecf20Sopenharmony_ci amdgpu_vmid_reset(adev, ring->funcs->vmhub, job->vmid); 2758c2ecf20Sopenharmony_ci amdgpu_ring_undo(ring); 2768c2ecf20Sopenharmony_ci return r; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (ring->funcs->insert_end) 2808c2ecf20Sopenharmony_ci ring->funcs->insert_end(ring); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (patch_offset != ~0 && ring->funcs->patch_cond_exec) 2838c2ecf20Sopenharmony_ci amdgpu_ring_patch_cond_exec(ring, patch_offset); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci ring->current_ctx = fence_ctx; 2868c2ecf20Sopenharmony_ci if (vm && ring->funcs->emit_switch_buffer) 2878c2ecf20Sopenharmony_ci amdgpu_ring_emit_switch_buffer(ring); 2888c2ecf20Sopenharmony_ci amdgpu_ring_commit(ring); 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** 2938c2ecf20Sopenharmony_ci * amdgpu_ib_pool_init - Init the IB (Indirect Buffer) pool 2948c2ecf20Sopenharmony_ci * 2958c2ecf20Sopenharmony_ci * @adev: amdgpu_device pointer 2968c2ecf20Sopenharmony_ci * 2978c2ecf20Sopenharmony_ci * Initialize the suballocator to manage a pool of memory 2988c2ecf20Sopenharmony_ci * for use as IBs (all asics). 2998c2ecf20Sopenharmony_ci * Returns 0 on success, error on failure. 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_ciint amdgpu_ib_pool_init(struct amdgpu_device *adev) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci unsigned size; 3048c2ecf20Sopenharmony_ci int r, i; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (adev->ib_pool_ready) 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) { 3108c2ecf20Sopenharmony_ci if (i == AMDGPU_IB_POOL_DIRECT) 3118c2ecf20Sopenharmony_ci size = PAGE_SIZE * 2; 3128c2ecf20Sopenharmony_ci else 3138c2ecf20Sopenharmony_ci size = AMDGPU_IB_POOL_SIZE; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i], 3168c2ecf20Sopenharmony_ci size, AMDGPU_GPU_PAGE_SIZE, 3178c2ecf20Sopenharmony_ci AMDGPU_GEM_DOMAIN_GTT); 3188c2ecf20Sopenharmony_ci if (r) 3198c2ecf20Sopenharmony_ci goto error; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci adev->ib_pool_ready = true; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return 0; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cierror: 3268c2ecf20Sopenharmony_ci while (i--) 3278c2ecf20Sopenharmony_ci amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]); 3288c2ecf20Sopenharmony_ci return r; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/** 3328c2ecf20Sopenharmony_ci * amdgpu_ib_pool_fini - Free the IB (Indirect Buffer) pool 3338c2ecf20Sopenharmony_ci * 3348c2ecf20Sopenharmony_ci * @adev: amdgpu_device pointer 3358c2ecf20Sopenharmony_ci * 3368c2ecf20Sopenharmony_ci * Tear down the suballocator managing the pool of memory 3378c2ecf20Sopenharmony_ci * for use as IBs (all asics). 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_civoid amdgpu_ib_pool_fini(struct amdgpu_device *adev) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci int i; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (!adev->ib_pool_ready) 3448c2ecf20Sopenharmony_ci return; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) 3478c2ecf20Sopenharmony_ci amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]); 3488c2ecf20Sopenharmony_ci adev->ib_pool_ready = false; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci/** 3528c2ecf20Sopenharmony_ci * amdgpu_ib_ring_tests - test IBs on the rings 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * @adev: amdgpu_device pointer 3558c2ecf20Sopenharmony_ci * 3568c2ecf20Sopenharmony_ci * Test an IB (Indirect Buffer) on each ring. 3578c2ecf20Sopenharmony_ci * If the test fails, disable the ring. 3588c2ecf20Sopenharmony_ci * Returns 0 on success, error if the primary GFX ring 3598c2ecf20Sopenharmony_ci * IB test fails. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ciint amdgpu_ib_ring_tests(struct amdgpu_device *adev) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci long tmo_gfx, tmo_mm; 3648c2ecf20Sopenharmony_ci int r, ret = 0; 3658c2ecf20Sopenharmony_ci unsigned i; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci tmo_mm = tmo_gfx = AMDGPU_IB_TEST_TIMEOUT; 3688c2ecf20Sopenharmony_ci if (amdgpu_sriov_vf(adev)) { 3698c2ecf20Sopenharmony_ci /* for MM engines in hypervisor side they are not scheduled together 3708c2ecf20Sopenharmony_ci * with CP and SDMA engines, so even in exclusive mode MM engine could 3718c2ecf20Sopenharmony_ci * still running on other VF thus the IB TEST TIMEOUT for MM engines 3728c2ecf20Sopenharmony_ci * under SR-IOV should be set to a long time. 8 sec should be enough 3738c2ecf20Sopenharmony_ci * for the MM comes back to this VF. 3748c2ecf20Sopenharmony_ci */ 3758c2ecf20Sopenharmony_ci tmo_mm = 8 * AMDGPU_IB_TEST_TIMEOUT; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (amdgpu_sriov_runtime(adev)) { 3798c2ecf20Sopenharmony_ci /* for CP & SDMA engines since they are scheduled together so 3808c2ecf20Sopenharmony_ci * need to make the timeout width enough to cover the time 3818c2ecf20Sopenharmony_ci * cost waiting for it coming back under RUNTIME only 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_ci tmo_gfx = 8 * AMDGPU_IB_TEST_TIMEOUT; 3848c2ecf20Sopenharmony_ci } else if (adev->gmc.xgmi.hive_id) { 3858c2ecf20Sopenharmony_ci tmo_gfx = AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci for (i = 0; i < adev->num_rings; ++i) { 3898c2ecf20Sopenharmony_ci struct amdgpu_ring *ring = adev->rings[i]; 3908c2ecf20Sopenharmony_ci long tmo; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci /* KIQ rings don't have an IB test because we never submit IBs 3938c2ecf20Sopenharmony_ci * to them and they have no interrupt support. 3948c2ecf20Sopenharmony_ci */ 3958c2ecf20Sopenharmony_ci if (!ring->sched.ready || !ring->funcs->test_ib) 3968c2ecf20Sopenharmony_ci continue; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* MM engine need more time */ 3998c2ecf20Sopenharmony_ci if (ring->funcs->type == AMDGPU_RING_TYPE_UVD || 4008c2ecf20Sopenharmony_ci ring->funcs->type == AMDGPU_RING_TYPE_VCE || 4018c2ecf20Sopenharmony_ci ring->funcs->type == AMDGPU_RING_TYPE_UVD_ENC || 4028c2ecf20Sopenharmony_ci ring->funcs->type == AMDGPU_RING_TYPE_VCN_DEC || 4038c2ecf20Sopenharmony_ci ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC || 4048c2ecf20Sopenharmony_ci ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) 4058c2ecf20Sopenharmony_ci tmo = tmo_mm; 4068c2ecf20Sopenharmony_ci else 4078c2ecf20Sopenharmony_ci tmo = tmo_gfx; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci r = amdgpu_ring_test_ib(ring, tmo); 4108c2ecf20Sopenharmony_ci if (!r) { 4118c2ecf20Sopenharmony_ci DRM_DEV_DEBUG(adev->dev, "ib test on %s succeeded\n", 4128c2ecf20Sopenharmony_ci ring->name); 4138c2ecf20Sopenharmony_ci continue; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci ring->sched.ready = false; 4178c2ecf20Sopenharmony_ci DRM_DEV_ERROR(adev->dev, "IB test failed on %s (%d).\n", 4188c2ecf20Sopenharmony_ci ring->name, r); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci if (ring == &adev->gfx.gfx_ring[0]) { 4218c2ecf20Sopenharmony_ci /* oh, oh, that's really bad */ 4228c2ecf20Sopenharmony_ci adev->accel_working = false; 4238c2ecf20Sopenharmony_ci return r; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci } else { 4268c2ecf20Sopenharmony_ci ret = r; 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci return ret; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/* 4338c2ecf20Sopenharmony_ci * Debugfs info 4348c2ecf20Sopenharmony_ci */ 4358c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic int amdgpu_debugfs_sa_info(struct seq_file *m, void *data) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct drm_info_node *node = (struct drm_info_node *) m->private; 4408c2ecf20Sopenharmony_ci struct drm_device *dev = node->minor->dev; 4418c2ecf20Sopenharmony_ci struct amdgpu_device *adev = drm_to_adev(dev); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci seq_printf(m, "--------------------- DELAYED --------------------- \n"); 4448c2ecf20Sopenharmony_ci amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED], 4458c2ecf20Sopenharmony_ci m); 4468c2ecf20Sopenharmony_ci seq_printf(m, "-------------------- IMMEDIATE -------------------- \n"); 4478c2ecf20Sopenharmony_ci amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_IMMEDIATE], 4488c2ecf20Sopenharmony_ci m); 4498c2ecf20Sopenharmony_ci seq_printf(m, "--------------------- DIRECT ---------------------- \n"); 4508c2ecf20Sopenharmony_ci amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DIRECT], m); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic const struct drm_info_list amdgpu_debugfs_sa_list[] = { 4568c2ecf20Sopenharmony_ci {"amdgpu_sa_info", &amdgpu_debugfs_sa_info, 0, NULL}, 4578c2ecf20Sopenharmony_ci}; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci#endif 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ciint amdgpu_debugfs_sa_init(struct amdgpu_device *adev) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 4648c2ecf20Sopenharmony_ci return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_sa_list, 4658c2ecf20Sopenharmony_ci ARRAY_SIZE(amdgpu_debugfs_sa_list)); 4668c2ecf20Sopenharmony_ci#else 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci#endif 4698c2ecf20Sopenharmony_ci} 470