1d38ceaf9SAlex Deucher /*
2d38ceaf9SAlex Deucher * Copyright 2008 Advanced Micro Devices, Inc.
3d38ceaf9SAlex Deucher * Copyright 2008 Red Hat Inc.
4d38ceaf9SAlex Deucher * Copyright 2009 Jerome Glisse.
5d38ceaf9SAlex Deucher *
6d38ceaf9SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a
7d38ceaf9SAlex Deucher * copy of this software and associated documentation files (the "Software"),
8d38ceaf9SAlex Deucher * to deal in the Software without restriction, including without limitation
9d38ceaf9SAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d38ceaf9SAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the
11d38ceaf9SAlex Deucher * Software is furnished to do so, subject to the following conditions:
12d38ceaf9SAlex Deucher *
13d38ceaf9SAlex Deucher * The above copyright notice and this permission notice shall be included in
14d38ceaf9SAlex Deucher * all copies or substantial portions of the Software.
15d38ceaf9SAlex Deucher *
16d38ceaf9SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d38ceaf9SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d38ceaf9SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19d38ceaf9SAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20d38ceaf9SAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21d38ceaf9SAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22d38ceaf9SAlex Deucher * OTHER DEALINGS IN THE SOFTWARE.
23d38ceaf9SAlex Deucher *
24d38ceaf9SAlex Deucher * Authors: Dave Airlie
25d38ceaf9SAlex Deucher * Alex Deucher
26d38ceaf9SAlex Deucher * Jerome Glisse
27d38ceaf9SAlex Deucher * Christian König
28d38ceaf9SAlex Deucher */
29d38ceaf9SAlex Deucher #include <linux/seq_file.h>
30d38ceaf9SAlex Deucher #include <linux/slab.h>
31fdf2f6c5SSam Ravnborg
32d38ceaf9SAlex Deucher #include <drm/amdgpu_drm.h>
33fdf2f6c5SSam Ravnborg
34d38ceaf9SAlex Deucher #include "amdgpu.h"
35d38ceaf9SAlex Deucher #include "atom.h"
3665f7260bSAndrey Grodzovsky #include "amdgpu_trace.h"
37d38ceaf9SAlex Deucher
38bb7ad55bSChunming Zhou #define AMDGPU_IB_TEST_TIMEOUT msecs_to_jiffies(1000)
39d4162c61Sshaoyunl #define AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT msecs_to_jiffies(2000)
40bbec97aaSChristian König
41d38ceaf9SAlex Deucher /*
42d38ceaf9SAlex Deucher * IB
43d38ceaf9SAlex Deucher * IBs (Indirect Buffers) and areas of GPU accessible memory where
44d38ceaf9SAlex Deucher * commands are stored. You can put a pointer to the IB in the
45d38ceaf9SAlex Deucher * command ring and the hw will fetch the commands from the IB
46d38ceaf9SAlex Deucher * and execute them. Generally userspace acceleration drivers
47d38ceaf9SAlex Deucher * produce command buffers which are send to the kernel and
48d38ceaf9SAlex Deucher * put in IBs for execution by the requested ring.
49d38ceaf9SAlex Deucher */
50d38ceaf9SAlex Deucher
51d38ceaf9SAlex Deucher /**
52d38ceaf9SAlex Deucher * amdgpu_ib_get - request an IB (Indirect Buffer)
53d38ceaf9SAlex Deucher *
54ad8eb024SLee Jones * @adev: amdgpu_device pointer
55ad8eb024SLee Jones * @vm: amdgpu_vm pointer
56d38ceaf9SAlex Deucher * @size: requested IB size
57ad8eb024SLee Jones * @pool_type: IB pool type (delayed, immediate, direct)
58d38ceaf9SAlex Deucher * @ib: IB object returned
59d38ceaf9SAlex Deucher *
60d38ceaf9SAlex Deucher * Request an IB (all asics). IBs are allocated using the
61d38ceaf9SAlex Deucher * suballocator.
62d38ceaf9SAlex Deucher * Returns 0 on success, error on failure.
63d38ceaf9SAlex Deucher */
amdgpu_ib_get(struct amdgpu_device * adev,struct amdgpu_vm * vm,unsigned int size,enum amdgpu_ib_pool_type pool_type,struct amdgpu_ib * ib)64b07c60c0SChristian König int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
65fc8e55f3SSrinivasan Shanmugam unsigned int size, enum amdgpu_ib_pool_type pool_type,
66c8e42d57Sxinhui pan struct amdgpu_ib *ib)
67d38ceaf9SAlex Deucher {
68d38ceaf9SAlex Deucher int r;
69d38ceaf9SAlex Deucher
70d38ceaf9SAlex Deucher if (size) {
719ecefb19SChristian König r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type],
72c103a23fSMaarten Lankhorst &ib->sa_bo, size);
73d38ceaf9SAlex Deucher if (r) {
74d38ceaf9SAlex Deucher dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
75d38ceaf9SAlex Deucher return r;
76d38ceaf9SAlex Deucher }
77d38ceaf9SAlex Deucher
78d38ceaf9SAlex Deucher ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo);
795c88e3b8SJinzhou Su /* flush the cache before commit the IB */
805c88e3b8SJinzhou Su ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC;
81d38ceaf9SAlex Deucher
82d38ceaf9SAlex Deucher if (!vm)
83d38ceaf9SAlex Deucher ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
84d38ceaf9SAlex Deucher }
85d38ceaf9SAlex Deucher
86d38ceaf9SAlex Deucher return 0;
87d38ceaf9SAlex Deucher }
88d38ceaf9SAlex Deucher
89d38ceaf9SAlex Deucher /**
90d38ceaf9SAlex Deucher * amdgpu_ib_free - free an IB (Indirect Buffer)
91d38ceaf9SAlex Deucher *
92d38ceaf9SAlex Deucher * @ib: IB object to free
93cc55c45dSMonk Liu * @f: the fence SA bo need wait on for the ib alloation
94d38ceaf9SAlex Deucher *
95d38ceaf9SAlex Deucher * Free an IB (all asics).
96d38ceaf9SAlex Deucher */
amdgpu_ib_free(struct amdgpu_ib * ib,struct dma_fence * f)970014952bSPierre-Eric Pelloux-Prayer void amdgpu_ib_free(struct amdgpu_ib *ib, struct dma_fence *f)
98d38ceaf9SAlex Deucher {
990014952bSPierre-Eric Pelloux-Prayer amdgpu_sa_bo_free(&ib->sa_bo, f);
100d38ceaf9SAlex Deucher }
101d38ceaf9SAlex Deucher
102d38ceaf9SAlex Deucher /**
103d38ceaf9SAlex Deucher * amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring
104d38ceaf9SAlex Deucher *
105ad8eb024SLee Jones * @ring: ring index the IB is associated with
106d38ceaf9SAlex Deucher * @num_ibs: number of IBs to schedule
107d38ceaf9SAlex Deucher * @ibs: IB objects to schedule
1087ad0c80cSLee Jones * @job: job to schedule
109ec72b800SChristian König * @f: fence created during this submission
110d38ceaf9SAlex Deucher *
111d38ceaf9SAlex Deucher * Schedule an IB on the associated ring (all asics).
112d38ceaf9SAlex Deucher * Returns 0 on success, error on failure.
113d38ceaf9SAlex Deucher *
114d38ceaf9SAlex Deucher * On SI, there are two parallel engines fed from the primary ring,
115d38ceaf9SAlex Deucher * the CE (Constant Engine) and the DE (Drawing Engine). Since
116d38ceaf9SAlex Deucher * resource descriptors have moved to memory, the CE allows you to
117d38ceaf9SAlex Deucher * prime the caches while the DE is updating register state so that
118d38ceaf9SAlex Deucher * the resource descriptors will be already in cache when the draw is
119d38ceaf9SAlex Deucher * processed. To accomplish this, the userspace driver submits two
120d38ceaf9SAlex Deucher * IBs, one for the CE and one for the DE. If there is a CE IB (called
121d38ceaf9SAlex Deucher * a CONST_IB), it will be put on the ring prior to the DE IB. Prior
122d38ceaf9SAlex Deucher * to SI there was just a DE IB.
123d38ceaf9SAlex Deucher */
amdgpu_ib_schedule(struct amdgpu_ring * ring,unsigned int num_ibs,struct amdgpu_ib * ibs,struct amdgpu_job * job,struct dma_fence ** f)124fc8e55f3SSrinivasan Shanmugam int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
12550ddc75eSJunwei Zhang struct amdgpu_ib *ibs, struct amdgpu_job *job,
12650ddc75eSJunwei Zhang struct dma_fence **f)
127d38ceaf9SAlex Deucher {
128b07c60c0SChristian König struct amdgpu_device *adev = ring->adev;
129d38ceaf9SAlex Deucher struct amdgpu_ib *ib = &ibs[0];
130b9bf33d5SChunming Zhou struct dma_fence *tmp = NULL;
1317d9c70d2SJiansong Chen bool need_ctx_switch;
13292f25098SChristian König struct amdgpu_vm *vm;
1333aecd24cSMonk Liu uint64_t fence_ctx;
1349a9db6efSAlex Deucher uint32_t status = 0, alloc_size;
135fc8e55f3SSrinivasan Shanmugam unsigned int fence_flags = 0;
136ac928705SChristian König bool secure, init_shadow;
137ac928705SChristian König u64 shadow_va, csa_va, gds_va;
138ac928705SChristian König int vmid = AMDGPU_JOB_GET_VMID(job);
139c68cbbfdSChristian König bool need_pipe_sync = false;
140c68cbbfdSChristian König unsigned int cond_exec;
14103ccf481SMonk Liu
142fc8e55f3SSrinivasan Shanmugam unsigned int i;
143d38ceaf9SAlex Deucher int r = 0;
144d38ceaf9SAlex Deucher
145d38ceaf9SAlex Deucher if (num_ibs == 0)
146d38ceaf9SAlex Deucher return -EINVAL;
147d38ceaf9SAlex Deucher
14892f25098SChristian König /* ring tests don't use a job */
14992f25098SChristian König if (job) {
150c5637837SMonk Liu vm = job->vm;
151dcafbd50SFelix Kuehling fence_ctx = job->base.s_fence ?
152dcafbd50SFelix Kuehling job->base.s_fence->scheduled.context : 0;
153ac928705SChristian König shadow_va = job->shadow_va;
154ac928705SChristian König csa_va = job->csa_va;
155ac928705SChristian König gds_va = job->gds_va;
156ac928705SChristian König init_shadow = job->init_shadow;
15792f25098SChristian König } else {
15892f25098SChristian König vm = NULL;
1593aecd24cSMonk Liu fence_ctx = 0;
160ac928705SChristian König shadow_va = 0;
161ac928705SChristian König csa_va = 0;
162ac928705SChristian König gds_va = 0;
163ac928705SChristian König init_shadow = false;
16492f25098SChristian König }
165d919ad49SChristian König
166f89703f5SJack Xiao if (!ring->sched.ready && !ring->is_mes_queue) {
1671b583649STom St Denis dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
168d38ceaf9SAlex Deucher return -EINVAL;
169d38ceaf9SAlex Deucher }
170be86c606SChunming Zhou
171f89703f5SJack Xiao if (vm && !job->vmid && !ring->is_mes_queue) {
1728d0a7ceaSChristian König dev_err(adev->dev, "VM IB without ID\n");
1738d0a7ceaSChristian König return -EINVAL;
1748d0a7ceaSChristian König }
1758d0a7ceaSChristian König
176b33f9d70SAlex Deucher if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) &&
1778c0f11ffSLang Yu (!ring->funcs->secure_submission_supported)) {
1788c0f11ffSLang Yu dev_err(adev->dev, "secure submissions not supported on ring <%s>\n", ring->name);
179b33f9d70SAlex Deucher return -EINVAL;
180b33f9d70SAlex Deucher }
181b33f9d70SAlex Deucher
182e12f3d7aSChristian König alloc_size = ring->funcs->emit_frame_size + num_ibs *
183e12f3d7aSChristian König ring->funcs->emit_ib_size;
1849a9db6efSAlex Deucher
1859a9db6efSAlex Deucher r = amdgpu_ring_alloc(ring, alloc_size);
186d38ceaf9SAlex Deucher if (r) {
187d38ceaf9SAlex Deucher dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
188d38ceaf9SAlex Deucher return r;
189d38ceaf9SAlex Deucher }
190df83d1ebSChunming Zhou
1914f0ecd36SEmily Deng need_ctx_switch = ring->current_ctx != fence_ctx;
192df83d1ebSChunming Zhou if (ring->funcs->emit_pipeline_sync && job &&
1931b2d5edaSChristian König ((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
194def59436SChristian König need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) {
195def59436SChristian König
1968fdf074fSMonk Liu need_pipe_sync = true;
19765f7260bSAndrey Grodzovsky
19865f7260bSAndrey Grodzovsky if (tmp)
19965f7260bSAndrey Grodzovsky trace_amdgpu_ib_pipe_sync(job, tmp);
20065f7260bSAndrey Grodzovsky
201df83d1ebSChunming Zhou dma_fence_put(tmp);
202df83d1ebSChunming Zhou }
203d38ceaf9SAlex Deucher
20443c8546bSAndrey Grodzovsky if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync)
20543c8546bSAndrey Grodzovsky ring->funcs->emit_mem_sync(ring);
20643c8546bSAndrey Grodzovsky
20722e4f315SNirmoy Das if (ring->funcs->emit_wave_limit &&
20822e4f315SNirmoy Das ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
20922e4f315SNirmoy Das ring->funcs->emit_wave_limit(ring, true);
21022e4f315SNirmoy Das
211ef44f854SLeo Liu if (ring->funcs->insert_start)
212ef44f854SLeo Liu ring->funcs->insert_start(ring);
213ef44f854SLeo Liu
214df264f9eSChristian König if (job) {
2158fdf074fSMonk Liu r = amdgpu_vm_flush(ring, job, need_pipe_sync);
21641d9eb2cSChristian König if (r) {
21741d9eb2cSChristian König amdgpu_ring_undo(ring);
21841d9eb2cSChristian König return r;
21941d9eb2cSChristian König }
220794ff571SMonk Liu }
221d38ceaf9SAlex Deucher
2223f4c175dSJiadong.Zhu amdgpu_ring_ib_begin(ring);
223ac928705SChristian König
22438be7796SAlex Deucher if (ring->funcs->emit_gfx_shadow)
225ac928705SChristian König amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va,
226ac928705SChristian König init_shadow, vmid);
227ac928705SChristian König
22838be7796SAlex Deucher if (ring->funcs->init_cond_exec)
229c68cbbfdSChristian König cond_exec = amdgpu_ring_init_cond_exec(ring,
230c68cbbfdSChristian König ring->cond_exe_gpu_addr);
231e9d672b2SMonk Liu
232810085ddSEric Huang amdgpu_device_flush_hdp(adev, ring);
233d2edb07bSChristian König
234753ad49cSMonk Liu if (need_ctx_switch)
235753ad49cSMonk Liu status |= AMDGPU_HAVE_CTX_SWITCH;
2367e6bf80fSMonk Liu
237c4c905ecSJack Xiao if (job && ring->funcs->emit_cntxcntl) {
238c4c905ecSJack Xiao status |= job->preamble_status;
239d8780dc7SJack Xiao status |= job->preemption_status;
2400bb5d5b0SLuben Tuikov amdgpu_ring_emit_cntxcntl(ring, status);
241753ad49cSMonk Liu }
242753ad49cSMonk Liu
243f77c9affSHuang Rui /* Setup initial TMZiness and send it off.
244f77c9affSHuang Rui */
2450bb5d5b0SLuben Tuikov secure = false;
246f77c9affSHuang Rui if (job && ring->funcs->emit_frame_cntl) {
247f77c9affSHuang Rui secure = ib->flags & AMDGPU_IB_FLAGS_SECURE;
248f77c9affSHuang Rui amdgpu_ring_emit_frame_cntl(ring, true, secure);
249f77c9affSHuang Rui }
250f77c9affSHuang Rui
251d38ceaf9SAlex Deucher for (i = 0; i < num_ibs; ++i) {
252f153d286SChristian König ib = &ibs[i];
2539f8fb5a2SChristian König
254f77c9affSHuang Rui if (job && ring->funcs->emit_frame_cntl) {
255f77c9affSHuang Rui if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) {
256f77c9affSHuang Rui amdgpu_ring_emit_frame_cntl(ring, false, secure);
257f77c9affSHuang Rui secure = !secure;
258f77c9affSHuang Rui amdgpu_ring_emit_frame_cntl(ring, true, secure);
2590bb5d5b0SLuben Tuikov }
2600bb5d5b0SLuben Tuikov }
2610bb5d5b0SLuben Tuikov
262c4c905ecSJack Xiao amdgpu_ring_emit_ib(ring, job, ib, status);
263c4c905ecSJack Xiao status &= ~AMDGPU_HAVE_CTX_SWITCH;
264d38ceaf9SAlex Deucher }
265d38ceaf9SAlex Deucher
266f77c9affSHuang Rui if (job && ring->funcs->emit_frame_cntl)
267f77c9affSHuang Rui amdgpu_ring_emit_frame_cntl(ring, false, secure);
2683b4d68e9SMonk Liu
269810085ddSEric Huang amdgpu_device_invalidate_hdp(adev, ring);
27011afbde8SChunming Zhou
271d240cd9eSMarek Olšák if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE)
272d240cd9eSMarek Olšák fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY;
273d240cd9eSMarek Olšák
2749fc15f5fSNicolai Hähnle /* wrap the last IB with fence */
2759fc15f5fSNicolai Hähnle if (job && job->uf_addr) {
2769fc15f5fSNicolai Hähnle amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence,
2779fc15f5fSNicolai Hähnle fence_flags | AMDGPU_FENCE_FLAG_64BIT);
2789fc15f5fSNicolai Hähnle }
2799fc15f5fSNicolai Hähnle
280c68cbbfdSChristian König if (ring->funcs->emit_gfx_shadow && ring->funcs->init_cond_exec) {
281ac928705SChristian König amdgpu_ring_emit_gfx_shadow(ring, 0, 0, 0, false, 0);
282c68cbbfdSChristian König amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr);
283ac928705SChristian König }
284ac928705SChristian König
285c530b02fSJack Zhang r = amdgpu_fence_emit(ring, f, job, fence_flags);
286d38ceaf9SAlex Deucher if (r) {
287d38ceaf9SAlex Deucher dev_err(adev->dev, "failed to emit fence (%d)\n", r);
288c4f46f22SChristian König if (job && job->vmid)
2890530553bSLe Ma amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
290a27de35cSChristian König amdgpu_ring_undo(ring);
291d38ceaf9SAlex Deucher return r;
292d38ceaf9SAlex Deucher }
293d38ceaf9SAlex Deucher
294135d4735SLeo Liu if (ring->funcs->insert_end)
295135d4735SLeo Liu ring->funcs->insert_end(ring);
296135d4735SLeo Liu
297c68cbbfdSChristian König amdgpu_ring_patch_cond_exec(ring, cond_exec);
29803ccf481SMonk Liu
2993aecd24cSMonk Liu ring->current_ctx = fence_ctx;
300*b5290939SLin.Cao if (job && ring->funcs->emit_switch_buffer)
301c2167a65SMonk Liu amdgpu_ring_emit_switch_buffer(ring);
30222e4f315SNirmoy Das
30322e4f315SNirmoy Das if (ring->funcs->emit_wave_limit &&
30422e4f315SNirmoy Das ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
30522e4f315SNirmoy Das ring->funcs->emit_wave_limit(ring, false);
30622e4f315SNirmoy Das
3073f4c175dSJiadong.Zhu amdgpu_ring_ib_end(ring);
308a27de35cSChristian König amdgpu_ring_commit(ring);
309d38ceaf9SAlex Deucher return 0;
310d38ceaf9SAlex Deucher }
311d38ceaf9SAlex Deucher
312d38ceaf9SAlex Deucher /**
313d38ceaf9SAlex Deucher * amdgpu_ib_pool_init - Init the IB (Indirect Buffer) pool
314d38ceaf9SAlex Deucher *
315d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer
316d38ceaf9SAlex Deucher *
317d38ceaf9SAlex Deucher * Initialize the suballocator to manage a pool of memory
318d38ceaf9SAlex Deucher * for use as IBs (all asics).
319d38ceaf9SAlex Deucher * Returns 0 on success, error on failure.
320d38ceaf9SAlex Deucher */
amdgpu_ib_pool_init(struct amdgpu_device * adev)321d38ceaf9SAlex Deucher int amdgpu_ib_pool_init(struct amdgpu_device *adev)
322d38ceaf9SAlex Deucher {
3239ecefb19SChristian König int r, i;
324d38ceaf9SAlex Deucher
3259ecefb19SChristian König if (adev->ib_pool_ready)
326d38ceaf9SAlex Deucher return 0;
3279ecefb19SChristian König
328c8e42d57Sxinhui pan for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {
3299ecefb19SChristian König r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],
330c103a23fSMaarten Lankhorst AMDGPU_IB_POOL_SIZE, 256,
331d38ceaf9SAlex Deucher AMDGPU_GEM_DOMAIN_GTT);
3329ecefb19SChristian König if (r)
3339ecefb19SChristian König goto error;
334c8e42d57Sxinhui pan }
335d38ceaf9SAlex Deucher adev->ib_pool_ready = true;
33615997544SAlex Deucher
337d38ceaf9SAlex Deucher return 0;
3389ecefb19SChristian König
3399ecefb19SChristian König error:
3409ecefb19SChristian König while (i--)
3419ecefb19SChristian König amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]);
3429ecefb19SChristian König return r;
343d38ceaf9SAlex Deucher }
344d38ceaf9SAlex Deucher
345d38ceaf9SAlex Deucher /**
346d38ceaf9SAlex Deucher * amdgpu_ib_pool_fini - Free the IB (Indirect Buffer) pool
347d38ceaf9SAlex Deucher *
348d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer
349d38ceaf9SAlex Deucher *
350d38ceaf9SAlex Deucher * Tear down the suballocator managing the pool of memory
351d38ceaf9SAlex Deucher * for use as IBs (all asics).
352d38ceaf9SAlex Deucher */
amdgpu_ib_pool_fini(struct amdgpu_device * adev)353d38ceaf9SAlex Deucher void amdgpu_ib_pool_fini(struct amdgpu_device *adev)
354d38ceaf9SAlex Deucher {
355c8e42d57Sxinhui pan int i;
356c8e42d57Sxinhui pan
3579ecefb19SChristian König if (!adev->ib_pool_ready)
3589ecefb19SChristian König return;
3599ecefb19SChristian König
360c8e42d57Sxinhui pan for (i = 0; i < AMDGPU_IB_POOL_MAX; i++)
3619ecefb19SChristian König amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]);
362d38ceaf9SAlex Deucher adev->ib_pool_ready = false;
363d38ceaf9SAlex Deucher }
364d38ceaf9SAlex Deucher
365d38ceaf9SAlex Deucher /**
366d38ceaf9SAlex Deucher * amdgpu_ib_ring_tests - test IBs on the rings
367d38ceaf9SAlex Deucher *
368d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer
369d38ceaf9SAlex Deucher *
370d38ceaf9SAlex Deucher * Test an IB (Indirect Buffer) on each ring.
371d38ceaf9SAlex Deucher * If the test fails, disable the ring.
372d38ceaf9SAlex Deucher * Returns 0 on success, error if the primary GFX ring
373d38ceaf9SAlex Deucher * IB test fails.
374d38ceaf9SAlex Deucher */
amdgpu_ib_ring_tests(struct amdgpu_device * adev)375d38ceaf9SAlex Deucher int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
376d38ceaf9SAlex Deucher {
377dbf79765SMonk Liu long tmo_gfx, tmo_mm;
3789ecefb19SChristian König int r, ret = 0;
379fc8e55f3SSrinivasan Shanmugam unsigned int i;
380dbf79765SMonk Liu
381dbf79765SMonk Liu tmo_mm = tmo_gfx = AMDGPU_IB_TEST_TIMEOUT;
382dbf79765SMonk Liu if (amdgpu_sriov_vf(adev)) {
383dbf79765SMonk Liu /* for MM engines in hypervisor side they are not scheduled together
384dbf79765SMonk Liu * with CP and SDMA engines, so even in exclusive mode MM engine could
385dbf79765SMonk Liu * still running on other VF thus the IB TEST TIMEOUT for MM engines
386dbf79765SMonk Liu * under SR-IOV should be set to a long time. 8 sec should be enough
387dbf79765SMonk Liu * for the MM comes back to this VF.
388dbf79765SMonk Liu */
389dbf79765SMonk Liu tmo_mm = 8 * AMDGPU_IB_TEST_TIMEOUT;
390dbf79765SMonk Liu }
391dbf79765SMonk Liu
392dbf79765SMonk Liu if (amdgpu_sriov_runtime(adev)) {
393dbf79765SMonk Liu /* for CP & SDMA engines since they are scheduled together so
394dbf79765SMonk Liu * need to make the timeout width enough to cover the time
395dbf79765SMonk Liu * cost waiting for it coming back under RUNTIME only
396dbf79765SMonk Liu */
397dbf79765SMonk Liu tmo_gfx = 8 * AMDGPU_IB_TEST_TIMEOUT;
398d4162c61Sshaoyunl } else if (adev->gmc.xgmi.hive_id) {
399d4162c61Sshaoyunl tmo_gfx = AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT;
400dbf79765SMonk Liu }
401d38ceaf9SAlex Deucher
402af70a471SChristian König for (i = 0; i < adev->num_rings; ++i) {
403d38ceaf9SAlex Deucher struct amdgpu_ring *ring = adev->rings[i];
404dbf79765SMonk Liu long tmo;
405d38ceaf9SAlex Deucher
406315fed03SChristian König /* KIQ rings don't have an IB test because we never submit IBs
407315fed03SChristian König * to them and they have no interrupt support.
408158b594aSPratik Vishwakarma */
409315fed03SChristian König if (!ring->sched.ready || !ring->funcs->test_ib)
410158b594aSPratik Vishwakarma continue;
411158b594aSPratik Vishwakarma
4129d3bccdcSJack Xiao if (adev->enable_mes &&
4139d3bccdcSJack Xiao ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
4149d3bccdcSJack Xiao continue;
4159d3bccdcSJack Xiao
416dbf79765SMonk Liu /* MM engine need more time */
417dbf79765SMonk Liu if (ring->funcs->type == AMDGPU_RING_TYPE_UVD ||
418dbf79765SMonk Liu ring->funcs->type == AMDGPU_RING_TYPE_VCE ||
419dbf79765SMonk Liu ring->funcs->type == AMDGPU_RING_TYPE_UVD_ENC ||
420dbf79765SMonk Liu ring->funcs->type == AMDGPU_RING_TYPE_VCN_DEC ||
4215b2329b6SBoyuan Zhang ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC ||
4225b2329b6SBoyuan Zhang ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
423dbf79765SMonk Liu tmo = tmo_mm;
424dbf79765SMonk Liu else
425dbf79765SMonk Liu tmo = tmo_gfx;
426dbf79765SMonk Liu
427dbf79765SMonk Liu r = amdgpu_ring_test_ib(ring, tmo);
428af70a471SChristian König if (!r) {
429af70a471SChristian König DRM_DEV_DEBUG(adev->dev, "ib test on %s succeeded\n",
430af70a471SChristian König ring->name);
431af70a471SChristian König continue;
432af70a471SChristian König }
433af70a471SChristian König
434c66ed765SAndrey Grodzovsky ring->sched.ready = false;
435af70a471SChristian König DRM_DEV_ERROR(adev->dev, "IB test failed on %s (%d).\n",
436af70a471SChristian König ring->name, r);
437d38ceaf9SAlex Deucher
438d38ceaf9SAlex Deucher if (ring == &adev->gfx.gfx_ring[0]) {
439d38ceaf9SAlex Deucher /* oh, oh, that's really bad */
440d38ceaf9SAlex Deucher adev->accel_working = false;
441d38ceaf9SAlex Deucher return r;
442d38ceaf9SAlex Deucher
443d38ceaf9SAlex Deucher } else {
4441f703e66SChunming Zhou ret = r;
445d38ceaf9SAlex Deucher }
446d38ceaf9SAlex Deucher }
4471f703e66SChunming Zhou return ret;
448d38ceaf9SAlex Deucher }
449d38ceaf9SAlex Deucher
450d38ceaf9SAlex Deucher /*
451d38ceaf9SAlex Deucher * Debugfs info
452d38ceaf9SAlex Deucher */
453d38ceaf9SAlex Deucher #if defined(CONFIG_DEBUG_FS)
454d38ceaf9SAlex Deucher
amdgpu_debugfs_sa_info_show(struct seq_file * m,void * unused)45598d28ac2SNirmoy Das static int amdgpu_debugfs_sa_info_show(struct seq_file *m, void *unused)
456d38ceaf9SAlex Deucher {
457109b4d8cSSu Hui struct amdgpu_device *adev = m->private;
458d38ceaf9SAlex Deucher
459fc8e55f3SSrinivasan Shanmugam seq_puts(m, "--------------------- DELAYED ---------------------\n");
4609ecefb19SChristian König amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED],
4619ecefb19SChristian König m);
462fc8e55f3SSrinivasan Shanmugam seq_puts(m, "-------------------- IMMEDIATE --------------------\n");
4639ecefb19SChristian König amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_IMMEDIATE],
4649ecefb19SChristian König m);
465fc8e55f3SSrinivasan Shanmugam seq_puts(m, "--------------------- DIRECT ----------------------\n");
4669ecefb19SChristian König amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DIRECT], m);
467d38ceaf9SAlex Deucher
468d38ceaf9SAlex Deucher return 0;
469d38ceaf9SAlex Deucher }
470d38ceaf9SAlex Deucher
47198d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_sa_info);
472d38ceaf9SAlex Deucher
473d38ceaf9SAlex Deucher #endif
474d38ceaf9SAlex Deucher
amdgpu_debugfs_sa_init(struct amdgpu_device * adev)47598d28ac2SNirmoy Das void amdgpu_debugfs_sa_init(struct amdgpu_device *adev)
476d38ceaf9SAlex Deucher {
477d38ceaf9SAlex Deucher #if defined(CONFIG_DEBUG_FS)
47898d28ac2SNirmoy Das struct drm_minor *minor = adev_to_drm(adev)->primary;
47998d28ac2SNirmoy Das struct dentry *root = minor->debugfs_root;
48098d28ac2SNirmoy Das
48198d28ac2SNirmoy Das debugfs_create_file("amdgpu_sa_info", 0444, root, adev,
48298d28ac2SNirmoy Das &amdgpu_debugfs_sa_info_fops);
48398d28ac2SNirmoy Das
484d38ceaf9SAlex Deucher #endif
485d38ceaf9SAlex Deucher }
486