From 16c35db52c7e1018eb17f09dc3ca9b6422bd0376 Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Fri, 1 Jul 2022 15:50:49 -0700 Subject: drm/i915/vm_bind: Add out fence support Add support for handling out fence of vm_bind call. Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h | 2 + drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c | 74 ++++++++++++++++++++++ drivers/gpu/drm/i915/i915_vma.c | 6 +- drivers/gpu/drm/i915/i915_vma_types.h | 7 ++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h index ee6e4c52e80e..849bf3c1061e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind.h @@ -45,5 +45,7 @@ int i915_gem_vm_bind_obj(struct i915_address_space *vm, struct drm_file *file); int i915_gem_vm_unbind_obj(struct i915_address_space *vm, struct drm_i915_gem_vm_unbind *va); +void i915_vm_bind_signal_fence(struct i915_vma *vma, + struct dma_fence * const fence); #endif /* __I915_GEM_VM_BIND_H */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c index 3201204c8e74..96f139cc8060 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_vm_bind_object.c @@ -5,6 +5,8 @@ #include +#include + #include "gem/i915_gem_vm_bind.h" #include "gt/gen8_engine_cs.h" @@ -94,6 +96,68 @@ void i915_gem_vm_bind_remove(struct i915_vma *vma, bool release_obj) } } +static int i915_vm_bind_add_fence(struct drm_file *file, struct i915_vma *vma, + u32 handle, u64 point) +{ + struct drm_syncobj *syncobj; + + syncobj = drm_syncobj_find(file, handle); + if (!syncobj) { + DRM_DEBUG("Invalid syncobj handle provided\n"); + return -ENOENT; + } + + /* + * For timeline syncobjs we need to preallocate chains for + * later signaling. + */ + if (point) { + vma->vm_bind_fence.chain_fence = dma_fence_chain_alloc(); + if (!vma->vm_bind_fence.chain_fence) { + drm_syncobj_put(syncobj); + return -ENOMEM; + } + } else { + vma->vm_bind_fence.chain_fence = NULL; + } + + vma->vm_bind_fence.syncobj = syncobj; + vma->vm_bind_fence.value = point; + + return 0; +} + +static void i915_vm_bind_put_fence(struct i915_vma *vma) +{ + if (!vma->vm_bind_fence.syncobj) + return; + + drm_syncobj_put(vma->vm_bind_fence.syncobj); + dma_fence_chain_free(vma->vm_bind_fence.chain_fence); +} + +void i915_vm_bind_signal_fence(struct i915_vma *vma, + struct dma_fence * const fence) +{ + struct drm_syncobj *syncobj = vma->vm_bind_fence.syncobj; + + if (!syncobj) + return; + + if (vma->vm_bind_fence.chain_fence) { + drm_syncobj_add_point(syncobj, + vma->vm_bind_fence.chain_fence, + fence, vma->vm_bind_fence.value); + /* + * The chain's ownership is transferred to the + * timeline. + */ + vma->vm_bind_fence.chain_fence = NULL; + } else { + drm_syncobj_replace_fence(syncobj, fence); + } +} + int i915_gem_vm_unbind_obj(struct i915_address_space *vm, struct drm_i915_gem_vm_unbind *va) { @@ -202,6 +266,14 @@ int i915_gem_vm_bind_obj(struct i915_address_space *vm, } i915_gem_ww_ctx_init(&ww, true); + + if (va->fence.flags & I915_TIMELINE_FENCE_SIGNAL) { + ret = i915_vm_bind_add_fence(file, vma, va->fence.handle, + va->fence.value); + if (ret) + goto put_vma; + } + pin_flags = va->start | PIN_OFFSET_FIXED | PIN_USER; retry: ret = i915_gem_object_lock(vma->obj, &ww); @@ -230,6 +302,8 @@ out_ww: goto retry; } + i915_vm_bind_put_fence(vma); +put_vma: if (ret) i915_vma_destroy(vma); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index c669aff143f0..8243818b1c6c 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1510,8 +1510,12 @@ err_unlock: err_vma_res: i915_vma_resource_free(vma_res); err_fence: - if (work) + if (work) { + if (i915_vma_is_persistent(vma)) + i915_vm_bind_signal_fence(vma, &work->base.dma); + dma_fence_work_commit_imm(&work->base); + } err_rpm: if (wakeref) intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref); diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index 2298b3d6b7c4..7d830a6a0b51 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -293,6 +293,13 @@ struct i915_vma { /* Link in non-private persistent VMA list */ struct list_head non_priv_vm_bind_link; + /** Timeline fence for vm_bind completion notification */ + struct { + struct drm_syncobj *syncobj; + u64 value; + struct dma_fence_chain *chain_fence; + } vm_bind_fence; + /** Interval tree structures for persistent vma */ struct rb_node rb; u64 start; -- cgit v1.2.3