LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - amdgpu_ib.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 152 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008 Advanced Micro Devices, Inc.
       3             :  * Copyright 2008 Red Hat Inc.
       4             :  * Copyright 2009 Jerome Glisse.
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7             :  * copy of this software and associated documentation files (the "Software"),
       8             :  * to deal in the Software without restriction, including without limitation
       9             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10             :  * and/or sell copies of the Software, and to permit persons to whom the
      11             :  * Software is furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice shall be included in
      14             :  * all copies or substantial portions of the Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      19             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      20             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      21             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      22             :  * OTHER DEALINGS IN THE SOFTWARE.
      23             :  *
      24             :  * Authors: Dave Airlie
      25             :  *          Alex Deucher
      26             :  *          Jerome Glisse
      27             :  *          Christian König
      28             :  */
      29             : #include <linux/seq_file.h>
      30             : #include <linux/slab.h>
      31             : 
      32             : #include <drm/amdgpu_drm.h>
      33             : 
      34             : #include "amdgpu.h"
      35             : #include "atom.h"
      36             : #include "amdgpu_trace.h"
      37             : 
      38             : #define AMDGPU_IB_TEST_TIMEOUT  msecs_to_jiffies(1000)
      39             : #define AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT msecs_to_jiffies(2000)
      40             : 
      41             : /*
      42             :  * IB
      43             :  * IBs (Indirect Buffers) and areas of GPU accessible memory where
      44             :  * commands are stored.  You can put a pointer to the IB in the
      45             :  * command ring and the hw will fetch the commands from the IB
      46             :  * and execute them.  Generally userspace acceleration drivers
      47             :  * produce command buffers which are send to the kernel and
      48             :  * put in IBs for execution by the requested ring.
      49             :  */
      50             : 
      51             : /**
      52             :  * amdgpu_ib_get - request an IB (Indirect Buffer)
      53             :  *
      54             :  * @adev: amdgpu_device pointer
      55             :  * @vm: amdgpu_vm pointer
      56             :  * @size: requested IB size
      57             :  * @pool_type: IB pool type (delayed, immediate, direct)
      58             :  * @ib: IB object returned
      59             :  *
      60             :  * Request an IB (all asics).  IBs are allocated using the
      61             :  * suballocator.
      62             :  * Returns 0 on success, error on failure.
      63             :  */
      64           0 : int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
      65             :                   unsigned size, enum amdgpu_ib_pool_type pool_type,
      66             :                   struct amdgpu_ib *ib)
      67             : {
      68             :         int r;
      69             : 
      70           0 :         if (size) {
      71           0 :                 r = amdgpu_sa_bo_new(&adev->ib_pools[pool_type],
      72             :                                       &ib->sa_bo, size, 256);
      73           0 :                 if (r) {
      74           0 :                         dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
      75           0 :                         return r;
      76             :                 }
      77             : 
      78           0 :                 ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo);
      79             :                 /* flush the cache before commit the IB */
      80           0 :                 ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC;
      81             : 
      82           0 :                 if (!vm)
      83           0 :                         ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
      84             :         }
      85             : 
      86             :         return 0;
      87             : }
      88             : 
      89             : /**
      90             :  * amdgpu_ib_free - free an IB (Indirect Buffer)
      91             :  *
      92             :  * @adev: amdgpu_device pointer
      93             :  * @ib: IB object to free
      94             :  * @f: the fence SA bo need wait on for the ib alloation
      95             :  *
      96             :  * Free an IB (all asics).
      97             :  */
      98           0 : void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
      99             :                     struct dma_fence *f)
     100             : {
     101           0 :         amdgpu_sa_bo_free(adev, &ib->sa_bo, f);
     102           0 : }
     103             : 
     104             : /**
     105             :  * amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring
     106             :  *
     107             :  * @ring: ring index the IB is associated with
     108             :  * @num_ibs: number of IBs to schedule
     109             :  * @ibs: IB objects to schedule
     110             :  * @job: job to schedule
     111             :  * @f: fence created during this submission
     112             :  *
     113             :  * Schedule an IB on the associated ring (all asics).
     114             :  * Returns 0 on success, error on failure.
     115             :  *
     116             :  * On SI, there are two parallel engines fed from the primary ring,
     117             :  * the CE (Constant Engine) and the DE (Drawing Engine).  Since
     118             :  * resource descriptors have moved to memory, the CE allows you to
     119             :  * prime the caches while the DE is updating register state so that
     120             :  * the resource descriptors will be already in cache when the draw is
     121             :  * processed.  To accomplish this, the userspace driver submits two
     122             :  * IBs, one for the CE and one for the DE.  If there is a CE IB (called
     123             :  * a CONST_IB), it will be put on the ring prior to the DE IB.  Prior
     124             :  * to SI there was just a DE IB.
     125             :  */
     126           0 : int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
     127             :                        struct amdgpu_ib *ibs, struct amdgpu_job *job,
     128             :                        struct dma_fence **f)
     129             : {
     130           0 :         struct amdgpu_device *adev = ring->adev;
     131           0 :         struct amdgpu_ib *ib = &ibs[0];
     132           0 :         struct dma_fence *tmp = NULL;
     133             :         bool need_ctx_switch;
     134           0 :         unsigned patch_offset = ~0;
     135             :         struct amdgpu_vm *vm;
     136             :         uint64_t fence_ctx;
     137           0 :         uint32_t status = 0, alloc_size;
     138           0 :         unsigned fence_flags = 0;
     139             :         bool secure;
     140             : 
     141             :         unsigned i;
     142           0 :         int r = 0;
     143           0 :         bool need_pipe_sync = false;
     144             : 
     145           0 :         if (num_ibs == 0)
     146             :                 return -EINVAL;
     147             : 
     148             :         /* ring tests don't use a job */
     149           0 :         if (job) {
     150           0 :                 vm = job->vm;
     151           0 :                 fence_ctx = job->base.s_fence ?
     152           0 :                         job->base.s_fence->scheduled.context : 0;
     153             :         } else {
     154             :                 vm = NULL;
     155             :                 fence_ctx = 0;
     156             :         }
     157             : 
     158           0 :         if (!ring->sched.ready && !ring->is_mes_queue) {
     159           0 :                 dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
     160           0 :                 return -EINVAL;
     161             :         }
     162             : 
     163           0 :         if (vm && !job->vmid && !ring->is_mes_queue) {
     164           0 :                 dev_err(adev->dev, "VM IB without ID\n");
     165           0 :                 return -EINVAL;
     166             :         }
     167             : 
     168           0 :         if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) &&
     169           0 :             (!ring->funcs->secure_submission_supported)) {
     170           0 :                 dev_err(adev->dev, "secure submissions not supported on ring <%s>\n", ring->name);
     171           0 :                 return -EINVAL;
     172             :         }
     173             : 
     174           0 :         alloc_size = ring->funcs->emit_frame_size + num_ibs *
     175           0 :                 ring->funcs->emit_ib_size;
     176             : 
     177           0 :         r = amdgpu_ring_alloc(ring, alloc_size);
     178           0 :         if (r) {
     179           0 :                 dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
     180           0 :                 return r;
     181             :         }
     182             : 
     183           0 :         need_ctx_switch = ring->current_ctx != fence_ctx;
     184           0 :         if (ring->funcs->emit_pipeline_sync && job &&
     185           0 :             ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) ||
     186           0 :              (amdgpu_sriov_vf(adev) && need_ctx_switch) ||
     187           0 :              amdgpu_vm_need_pipeline_sync(ring, job))) {
     188           0 :                 need_pipe_sync = true;
     189             : 
     190             :                 if (tmp)
     191             :                         trace_amdgpu_ib_pipe_sync(job, tmp);
     192             : 
     193             :                 dma_fence_put(tmp);
     194             :         }
     195             : 
     196           0 :         if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync)
     197           0 :                 ring->funcs->emit_mem_sync(ring);
     198             : 
     199           0 :         if (ring->funcs->emit_wave_limit &&
     200           0 :             ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
     201           0 :                 ring->funcs->emit_wave_limit(ring, true);
     202             : 
     203           0 :         if (ring->funcs->insert_start)
     204           0 :                 ring->funcs->insert_start(ring);
     205             : 
     206           0 :         if (job) {
     207           0 :                 r = amdgpu_vm_flush(ring, job, need_pipe_sync);
     208           0 :                 if (r) {
     209           0 :                         amdgpu_ring_undo(ring);
     210           0 :                         return r;
     211             :                 }
     212             :         }
     213             : 
     214           0 :         if (job && ring->funcs->init_cond_exec)
     215           0 :                 patch_offset = amdgpu_ring_init_cond_exec(ring);
     216             : 
     217           0 :         amdgpu_device_flush_hdp(adev, ring);
     218             : 
     219           0 :         if (need_ctx_switch)
     220           0 :                 status |= AMDGPU_HAVE_CTX_SWITCH;
     221             : 
     222           0 :         if (job && ring->funcs->emit_cntxcntl) {
     223           0 :                 status |= job->preamble_status;
     224           0 :                 status |= job->preemption_status;
     225           0 :                 amdgpu_ring_emit_cntxcntl(ring, status);
     226             :         }
     227             : 
     228             :         /* Setup initial TMZiness and send it off.
     229             :          */
     230           0 :         secure = false;
     231           0 :         if (job && ring->funcs->emit_frame_cntl) {
     232           0 :                 secure = ib->flags & AMDGPU_IB_FLAGS_SECURE;
     233           0 :                 amdgpu_ring_emit_frame_cntl(ring, true, secure);
     234             :         }
     235             : 
     236           0 :         for (i = 0; i < num_ibs; ++i) {
     237           0 :                 ib = &ibs[i];
     238             : 
     239           0 :                 if (job && ring->funcs->emit_frame_cntl) {
     240           0 :                         if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) {
     241           0 :                                 amdgpu_ring_emit_frame_cntl(ring, false, secure);
     242           0 :                                 secure = !secure;
     243           0 :                                 amdgpu_ring_emit_frame_cntl(ring, true, secure);
     244             :                         }
     245             :                 }
     246             : 
     247           0 :                 amdgpu_ring_emit_ib(ring, job, ib, status);
     248           0 :                 status &= ~AMDGPU_HAVE_CTX_SWITCH;
     249             :         }
     250             : 
     251           0 :         if (job && ring->funcs->emit_frame_cntl)
     252           0 :                 amdgpu_ring_emit_frame_cntl(ring, false, secure);
     253             : 
     254           0 :         amdgpu_device_invalidate_hdp(adev, ring);
     255             : 
     256           0 :         if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE)
     257           0 :                 fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY;
     258             : 
     259             :         /* wrap the last IB with fence */
     260           0 :         if (job && job->uf_addr) {
     261           0 :                 amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence,
     262             :                                        fence_flags | AMDGPU_FENCE_FLAG_64BIT);
     263             :         }
     264             : 
     265           0 :         r = amdgpu_fence_emit(ring, f, job, fence_flags);
     266           0 :         if (r) {
     267           0 :                 dev_err(adev->dev, "failed to emit fence (%d)\n", r);
     268           0 :                 if (job && job->vmid)
     269           0 :                         amdgpu_vmid_reset(adev, ring->funcs->vmhub, job->vmid);
     270           0 :                 amdgpu_ring_undo(ring);
     271           0 :                 return r;
     272             :         }
     273             : 
     274           0 :         if (ring->funcs->insert_end)
     275           0 :                 ring->funcs->insert_end(ring);
     276             : 
     277           0 :         if (patch_offset != ~0 && ring->funcs->patch_cond_exec)
     278           0 :                 amdgpu_ring_patch_cond_exec(ring, patch_offset);
     279             : 
     280           0 :         ring->current_ctx = fence_ctx;
     281           0 :         if (vm && ring->funcs->emit_switch_buffer)
     282           0 :                 amdgpu_ring_emit_switch_buffer(ring);
     283             : 
     284           0 :         if (ring->funcs->emit_wave_limit &&
     285           0 :             ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
     286           0 :                 ring->funcs->emit_wave_limit(ring, false);
     287             : 
     288           0 :         amdgpu_ring_commit(ring);
     289           0 :         return 0;
     290             : }
     291             : 
     292             : /**
     293             :  * amdgpu_ib_pool_init - Init the IB (Indirect Buffer) pool
     294             :  *
     295             :  * @adev: amdgpu_device pointer
     296             :  *
     297             :  * Initialize the suballocator to manage a pool of memory
     298             :  * for use as IBs (all asics).
     299             :  * Returns 0 on success, error on failure.
     300             :  */
     301           0 : int amdgpu_ib_pool_init(struct amdgpu_device *adev)
     302             : {
     303             :         int r, i;
     304             : 
     305           0 :         if (adev->ib_pool_ready)
     306             :                 return 0;
     307             : 
     308           0 :         for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) {
     309           0 :                 r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i],
     310             :                                               AMDGPU_IB_POOL_SIZE,
     311             :                                               AMDGPU_GPU_PAGE_SIZE,
     312             :                                               AMDGPU_GEM_DOMAIN_GTT);
     313           0 :                 if (r)
     314             :                         goto error;
     315             :         }
     316           0 :         adev->ib_pool_ready = true;
     317             : 
     318           0 :         return 0;
     319             : 
     320             : error:
     321           0 :         while (i--)
     322           0 :                 amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]);
     323             :         return r;
     324             : }
     325             : 
     326             : /**
     327             :  * amdgpu_ib_pool_fini - Free the IB (Indirect Buffer) pool
     328             :  *
     329             :  * @adev: amdgpu_device pointer
     330             :  *
     331             :  * Tear down the suballocator managing the pool of memory
     332             :  * for use as IBs (all asics).
     333             :  */
     334           0 : void amdgpu_ib_pool_fini(struct amdgpu_device *adev)
     335             : {
     336             :         int i;
     337             : 
     338           0 :         if (!adev->ib_pool_ready)
     339             :                 return;
     340             : 
     341           0 :         for (i = 0; i < AMDGPU_IB_POOL_MAX; i++)
     342           0 :                 amdgpu_sa_bo_manager_fini(adev, &adev->ib_pools[i]);
     343           0 :         adev->ib_pool_ready = false;
     344             : }
     345             : 
     346             : /**
     347             :  * amdgpu_ib_ring_tests - test IBs on the rings
     348             :  *
     349             :  * @adev: amdgpu_device pointer
     350             :  *
     351             :  * Test an IB (Indirect Buffer) on each ring.
     352             :  * If the test fails, disable the ring.
     353             :  * Returns 0 on success, error if the primary GFX ring
     354             :  * IB test fails.
     355             :  */
     356           0 : int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
     357             : {
     358             :         long tmo_gfx, tmo_mm;
     359           0 :         int r, ret = 0;
     360             :         unsigned i;
     361             : 
     362           0 :         tmo_mm = tmo_gfx = AMDGPU_IB_TEST_TIMEOUT;
     363           0 :         if (amdgpu_sriov_vf(adev)) {
     364             :                 /* for MM engines in hypervisor side they are not scheduled together
     365             :                  * with CP and SDMA engines, so even in exclusive mode MM engine could
     366             :                  * still running on other VF thus the IB TEST TIMEOUT for MM engines
     367             :                  * under SR-IOV should be set to a long time. 8 sec should be enough
     368             :                  * for the MM comes back to this VF.
     369             :                  */
     370           0 :                 tmo_mm = 8 * AMDGPU_IB_TEST_TIMEOUT;
     371             :         }
     372             : 
     373           0 :         if (amdgpu_sriov_runtime(adev)) {
     374             :                 /* for CP & SDMA engines since they are scheduled together so
     375             :                  * need to make the timeout width enough to cover the time
     376             :                  * cost waiting for it coming back under RUNTIME only
     377             :                 */
     378             :                 tmo_gfx = 8 * AMDGPU_IB_TEST_TIMEOUT;
     379           0 :         } else if (adev->gmc.xgmi.hive_id) {
     380           0 :                 tmo_gfx = AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT;
     381             :         }
     382             : 
     383           0 :         for (i = 0; i < adev->num_rings; ++i) {
     384           0 :                 struct amdgpu_ring *ring = adev->rings[i];
     385             :                 long tmo;
     386             : 
     387             :                 /* KIQ rings don't have an IB test because we never submit IBs
     388             :                  * to them and they have no interrupt support.
     389             :                  */
     390           0 :                 if (!ring->sched.ready || !ring->funcs->test_ib)
     391           0 :                         continue;
     392             : 
     393           0 :                 if (adev->enable_mes &&
     394           0 :                     ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
     395           0 :                         continue;
     396             : 
     397             :                 /* MM engine need more time */
     398           0 :                 if (ring->funcs->type == AMDGPU_RING_TYPE_UVD ||
     399             :                         ring->funcs->type == AMDGPU_RING_TYPE_VCE ||
     400             :                         ring->funcs->type == AMDGPU_RING_TYPE_UVD_ENC ||
     401             :                         ring->funcs->type == AMDGPU_RING_TYPE_VCN_DEC ||
     402           0 :                         ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC ||
     403             :                         ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
     404             :                         tmo = tmo_mm;
     405             :                 else
     406           0 :                         tmo = tmo_gfx;
     407             : 
     408           0 :                 r = amdgpu_ring_test_ib(ring, tmo);
     409           0 :                 if (!r) {
     410           0 :                         DRM_DEV_DEBUG(adev->dev, "ib test on %s succeeded\n",
     411             :                                       ring->name);
     412           0 :                         continue;
     413             :                 }
     414             : 
     415           0 :                 ring->sched.ready = false;
     416           0 :                 DRM_DEV_ERROR(adev->dev, "IB test failed on %s (%d).\n",
     417             :                           ring->name, r);
     418             : 
     419           0 :                 if (ring == &adev->gfx.gfx_ring[0]) {
     420             :                         /* oh, oh, that's really bad */
     421           0 :                         adev->accel_working = false;
     422           0 :                         return r;
     423             : 
     424             :                 } else {
     425             :                         ret = r;
     426             :                 }
     427             :         }
     428             :         return ret;
     429             : }
     430             : 
     431             : /*
     432             :  * Debugfs info
     433             :  */
     434             : #if defined(CONFIG_DEBUG_FS)
     435             : 
     436             : static int amdgpu_debugfs_sa_info_show(struct seq_file *m, void *unused)
     437             : {
     438             :         struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
     439             : 
     440             :         seq_printf(m, "--------------------- DELAYED --------------------- \n");
     441             :         amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED],
     442             :                                      m);
     443             :         seq_printf(m, "-------------------- IMMEDIATE -------------------- \n");
     444             :         amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_IMMEDIATE],
     445             :                                      m);
     446             :         seq_printf(m, "--------------------- DIRECT ---------------------- \n");
     447             :         amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DIRECT], m);
     448             : 
     449             :         return 0;
     450             : }
     451             : 
     452             : DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_sa_info);
     453             : 
     454             : #endif
     455             : 
     456           0 : void amdgpu_debugfs_sa_init(struct amdgpu_device *adev)
     457             : {
     458             : #if defined(CONFIG_DEBUG_FS)
     459             :         struct drm_minor *minor = adev_to_drm(adev)->primary;
     460             :         struct dentry *root = minor->debugfs_root;
     461             : 
     462             :         debugfs_create_file("amdgpu_sa_info", 0444, root, adev,
     463             :                             &amdgpu_debugfs_sa_info_fops);
     464             : 
     465             : #endif
     466           0 : }

Generated by: LCOV version 1.14