This patch adds basic eviction fence framework for the gfx buffers. The idea is to: - One eviction fence is created per gfx process, at kms_open. - This same fence is attached to all the gem buffers created by this process. This framework will be further used for usermode queues. Cc: Christian Koenig <christian.koenig@xxxxxxx> Cc: Alex Deucher <alexander.deucher@xxxxxxx> Signed-off-by: Shashank Sharma <shashank.sharma@xxxxxxx> --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 15 +++ .../drm/amd/amdgpu/amdgpu_eviction_fence.c | 96 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 + 6 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 4536c8ad0e11..ba00789eb4ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -80,7 +80,8 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ - amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o + amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o \ + amdgpu_eviction_fence.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9c62552bec34..4a4b2680eb9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -463,6 +463,13 @@ struct amdgpu_flip_work { bool async; }; +struct amdgpu_eviction_fence { + u64 fence_ctx; + atomic_t seq; + spinlock_t lock; + struct dma_fence base; + char timeline_name[TASK_COMM_LEN]; +}; /* * file private structure @@ -476,6 +483,7 @@ struct amdgpu_fpriv { struct mutex bo_list_lock; struct idr bo_list_handles; struct amdgpu_ctx_mgr ctx_mgr; + struct amdgpu_eviction_fence eviction_fence; /** GPU partition selection */ uint32_t xcp_id; }; @@ -1474,6 +1482,13 @@ void amdgpu_disable_vblank_kms(struct drm_crtc *crtc); int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +/* Eviction fence */ +void amdgpu_eviction_fence_create(struct amdgpu_fpriv *fpriv); +int amdgpu_eviction_fence_attach(struct amdgpu_fpriv *fpriv, + struct amdgpu_bo *bo); +void amdgpu_eviction_fence_detach(struct amdgpu_fpriv *fpriv); +void amdgpu_eviction_fence_signal(struct amdgpu_fpriv *fpriv); + /* * functions used by amdgpu_encoder.c */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c new file mode 100644 index 000000000000..36009d89be03 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2024 Advanced Micro Devices, 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. + * + */ +#include <linux/sched.h> +#include "amdgpu.h" + +static const char * +amdgpu_ev_fence_get_driver_name(struct dma_fence *fence) +{ + return "amdgpu"; +} + +static const char * +amdgpu_ev_fence_get_timeline_name(struct dma_fence *f) +{ + struct amdgpu_eviction_fence *ef; + + ef = container_of(f, struct amdgpu_eviction_fence, base); + return ef->timeline_name; +} + +static const struct dma_fence_ops amdgpu_eviction_fence_ops = { + .use_64bit_seqno = true, + .get_driver_name = amdgpu_ev_fence_get_driver_name, + .get_timeline_name = amdgpu_ev_fence_get_timeline_name, +}; + +void amdgpu_eviction_fence_create(struct amdgpu_fpriv *fpriv) +{ + struct amdgpu_eviction_fence *fence = &fpriv->eviction_fence; + atomic_t seq = ATOMIC_INIT(0); + + spin_lock_init(&fence->lock); + fence->fence_ctx = dma_fence_context_alloc(1); + fence->seq = seq; + dma_fence_init(&fence->base, &amdgpu_eviction_fence_ops, + &fence->lock, fence->fence_ctx, + atomic_inc_return(&fence->seq)); +} + +int amdgpu_eviction_fence_attach(struct amdgpu_fpriv *fpriv, + struct amdgpu_bo *bo) +{ + struct dma_fence *ef = &fpriv->eviction_fence.base; + struct dma_resv *resv = bo->tbo.base.resv; + int ret; + + if (bo->eviction_fence) + return 0; + + ret = dma_resv_reserve_fences(resv, 1); + if (ret) { + dma_fence_wait(ef, false); + return ret; + } + + dma_resv_add_fence(resv, ef, DMA_RESV_USAGE_BOOKKEEP); + bo->eviction_fence = dma_fence_get(ef); + return 0; +} + +void amdgpu_eviction_fence_detach(struct amdgpu_fpriv *fpriv) +{ + struct dma_fence *ef = &fpriv->eviction_fence.base; + + if (!dma_fence_is_signaled(ef)) + dma_fence_put(ef); +} + +void amdgpu_eviction_fence_signal(struct amdgpu_fpriv *fpriv) +{ + struct dma_fence *ef = &fpriv->eviction_fence.base; + + if (!dma_fence_is_signaled(ef)) + dma_fence_signal(ef); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 67c234bcf89f..b75a19a0b5aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -199,8 +199,14 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj, * but not for export, this is a different lock class that cannot lead to * circular lock dependencies. */ - if (!vm->is_compute_context || !vm->process_info) + if (!vm->is_compute_context || !vm->process_info) { + /* attach gfx eviction fence */ + if (amdgpu_eviction_fence_attach(fpriv, abo)) + DRM_DEBUG_DRIVER("Failed to attach eviction fence to BO\n"); + return 0; + } + if (!obj->import_attach || !dma_buf_is_dynamic(obj->import_attach->dmabuf)) return 0; @@ -236,6 +242,8 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, struct drm_exec exec; long r; + amdgpu_eviction_fence_detach(fpriv); + drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0); drm_exec_until_all_locked(&exec) { r = drm_exec_prepare_obj(&exec, &bo->tbo.base, 1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index a2df3025a754..7804fe215d36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1293,7 +1293,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return 0; } - /* * Outdated mess for old drm with Xorg being in charge (void function now). */ @@ -1386,6 +1385,8 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) mutex_init(&fpriv->bo_list_lock); idr_init_base(&fpriv->bo_list_handles, 1); + amdgpu_eviction_fence_create(fpriv); + amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev); file_priv->driver_priv = fpriv; @@ -1455,6 +1456,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, amdgpu_bo_unreserve(pd); } + amdgpu_eviction_fence_signal(fpriv); amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); amdgpu_vm_fini(adev, &fpriv->vm); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index be679c42b0b8..91ae8d21ee5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -105,6 +105,8 @@ struct amdgpu_bo { struct amdgpu_vm_bo_base *vm_bo; /* Constant after initialization */ struct amdgpu_bo *parent; + /* Eviction fence attached to bo */ + struct dma_fence *eviction_fence; #ifdef CONFIG_MMU_NOTIFIER struct mmu_interval_notifier notifier; -- 2.43.2