[Intel-gfx] [PATCH 39/50] drm/i915: Move GEM object domain management from struct_mutex to local
Matthew Auld
matthew.william.auld at gmail.com
Fri Apr 12 15:03:00 UTC 2019
On Fri, 12 Apr 2019 at 09:54, Chris Wilson <chris at chris-wilson.co.uk> wrote:
>
> Use the per-object local lock to control the cache domain of the
> individual GEM objects, not struct_mutex. This is a huge leap forward
> for us in terms of object-level synchronisation; execbuffers are
> coordinated using the ww_mutex and pread/pwrite is finally fully
> serialised again.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
> drivers/gpu/drm/i915/Makefile | 1 +
> drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 4 +-
> drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 10 +-
> drivers/gpu/drm/i915/gem/i915_gem_domain.c | 70 +++++-----
> .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 123 ++++++++++++------
> drivers/gpu/drm/i915/gem/i915_gem_fence.c | 99 ++++++++++++++
> drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +
> drivers/gpu/drm/i915/gem/i915_gem_object.h | 14 ++
> drivers/gpu/drm/i915/gem/i915_gem_pm.c | 7 +-
> .../gpu/drm/i915/gem/selftests/huge_pages.c | 12 +-
> .../i915/gem/selftests/i915_gem_coherency.c | 12 ++
> .../drm/i915/gem/selftests/i915_gem_context.c | 20 +++
> .../drm/i915/gem/selftests/i915_gem_mman.c | 6 +
> .../drm/i915/gem/selftests/i915_gem_phys.c | 4 +-
> drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 4 +
> drivers/gpu/drm/i915/gt/selftest_lrc.c | 2 +
> .../gpu/drm/i915/gt/selftest_workarounds.c | 8 ++
> drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +
> drivers/gpu/drm/i915/gvt/scheduler.c | 8 +-
> drivers/gpu/drm/i915/i915_cmd_parser.c | 23 ++--
> drivers/gpu/drm/i915/i915_gem.c | 122 +++++++++--------
> drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +-
> drivers/gpu/drm/i915/i915_gem_render_state.c | 2 +
> drivers/gpu/drm/i915/i915_vma.c | 8 +-
> drivers/gpu/drm/i915/i915_vma.h | 12 ++
> drivers/gpu/drm/i915/intel_display.c | 5 +
> drivers/gpu/drm/i915/intel_guc_log.c | 6 +-
> drivers/gpu/drm/i915/intel_overlay.c | 25 ++--
> drivers/gpu/drm/i915/intel_uc_fw.c | 2 +
> drivers/gpu/drm/i915/selftests/i915_request.c | 4 +
> drivers/gpu/drm/i915/selftests/igt_spinner.c | 2 +
> 31 files changed, 448 insertions(+), 176 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_fence.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 8e70d5972195..e30622229812 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -93,6 +93,7 @@ gem-y += \
> gem/i915_gem_dmabuf.o \
> gem/i915_gem_domain.o \
> gem/i915_gem_execbuffer.o \
> + gem/i915_gem_fence.o \
> gem/i915_gem_internal.o \
> gem/i915_gem_object.o \
> gem/i915_gem_mman.o \
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
> index 093bfff55a96..efab47250588 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
> @@ -96,6 +96,8 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj,
> {
> struct clflush *clflush;
>
> + assert_object_held(obj);
> +
> /*
> * Stolen memory is always coherent with the GPU as it is explicitly
> * marked as wc by the system, or the system is cache-coherent.
> @@ -145,9 +147,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj,
> true, I915_FENCE_TIMEOUT,
> I915_FENCE_GFP);
>
> - reservation_object_lock(obj->resv, NULL);
> reservation_object_add_excl_fence(obj->resv, &clflush->dma);
> - reservation_object_unlock(obj->resv);
>
> i915_sw_fence_commit(&clflush->wait);
> } else if (obj->mm.pages) {
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> index 4e7efe159531..50981ea513f0 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> @@ -152,7 +152,6 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
> static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
> {
> struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
> - struct drm_device *dev = obj->base.dev;
> bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
> int err;
>
> @@ -160,12 +159,12 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire
> if (err)
> return err;
>
> - err = i915_mutex_lock_interruptible(dev);
> + err = i915_gem_object_lock_interruptible(obj);
> if (err)
> goto out;
>
> err = i915_gem_object_set_to_cpu_domain(obj, write);
> - mutex_unlock(&dev->struct_mutex);
> + i915_gem_object_unlock(obj);
>
> out:
> i915_gem_object_unpin_pages(obj);
> @@ -175,19 +174,18 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire
> static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
> {
> struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
> - struct drm_device *dev = obj->base.dev;
> int err;
>
> err = i915_gem_object_pin_pages(obj);
> if (err)
> return err;
>
> - err = i915_mutex_lock_interruptible(dev);
> + err = i915_gem_object_lock_interruptible(obj);
> if (err)
> goto out;
>
> err = i915_gem_object_set_to_gtt_domain(obj, false);
> - mutex_unlock(&dev->struct_mutex);
> + i915_gem_object_unlock(obj);
>
> out:
> i915_gem_object_unpin_pages(obj);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
> index 5e1429f8e910..4c84bb911d6c 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
> @@ -31,9 +31,9 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj)
> if (!READ_ONCE(obj->pin_global))
> return;
>
> - mutex_lock(&obj->base.dev->struct_mutex);
> + i915_gem_object_lock(obj);
> __i915_gem_object_flush_for_display(obj);
> - mutex_unlock(&obj->base.dev->struct_mutex);
> + i915_gem_object_unlock(obj);
> }
>
> /**
> @@ -49,11 +49,10 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write)
> {
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> + assert_object_held(obj);
>
> ret = i915_gem_object_wait(obj,
> I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED |
> (write ? I915_WAIT_ALL : 0),
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> @@ -111,11 +110,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
> {
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> + assert_object_held(obj);
>
> ret = i915_gem_object_wait(obj,
> I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED |
> (write ? I915_WAIT_ALL : 0),
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> @@ -181,7 +179,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
> struct i915_vma *vma;
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> + assert_object_held(obj);
>
> if (obj->cache_level == cache_level)
> return 0;
> @@ -230,7 +228,6 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
> */
> ret = i915_gem_object_wait(obj,
> I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED |
> I915_WAIT_ALL,
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> @@ -374,12 +371,16 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
> if (ret)
> goto out;
>
> - ret = i915_mutex_lock_interruptible(dev);
> + ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
> if (ret)
> goto out;
>
> - ret = i915_gem_object_set_cache_level(obj, level);
> - mutex_unlock(&dev->struct_mutex);
> + ret = i915_gem_object_lock_interruptible(obj);
> + if (ret == 0) {
> + ret = i915_gem_object_set_cache_level(obj, level);
> + i915_gem_object_unlock(obj);
> + }
> + mutex_unlock(&i915->drm.struct_mutex);
>
> out:
> i915_gem_object_put(obj);
> @@ -401,7 +402,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
> struct i915_vma *vma;
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> + assert_object_held(obj);
>
> /* Mark the global pin early so that we account for the
> * display coherency whilst setting up the cache domains.
> @@ -486,16 +487,18 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
> void
> i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
> {
> - lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
> + struct drm_i915_gem_object *obj = vma->obj;
> +
> + assert_object_held(obj);
>
> - if (WARN_ON(vma->obj->pin_global == 0))
> + if (WARN_ON(obj->pin_global == 0))
> return;
>
> - if (--vma->obj->pin_global == 0)
> + if (--obj->pin_global == 0)
> vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
>
> /* Bump the LRU to try and avoid premature eviction whilst flipping */
> - i915_gem_object_bump_inactive_ggtt(vma->obj);
> + i915_gem_object_bump_inactive_ggtt(obj);
>
> i915_vma_unpin(vma);
> }
> @@ -513,11 +516,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
> {
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> + assert_object_held(obj);
>
> ret = i915_gem_object_wait(obj,
> I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED |
> (write ? I915_WAIT_ALL : 0),
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> @@ -639,7 +641,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
> if (err)
> goto out;
>
> - err = i915_mutex_lock_interruptible(dev);
> + err = i915_gem_object_lock_interruptible(obj);
> if (err)
> goto out_unpin;
>
> @@ -653,7 +655,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
> /* And bump the LRU for this access */
> i915_gem_object_bump_inactive_ggtt(obj);
>
> - mutex_unlock(&dev->struct_mutex);
> + i915_gem_object_unlock(obj);
>
> if (write_domain != 0)
> intel_fb_obj_invalidate(obj,
> @@ -676,22 +678,23 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj,
> {
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> -
> *needs_clflush = 0;
> if (!i915_gem_object_has_struct_page(obj))
> return -ENODEV;
>
> + ret = i915_gem_object_lock_interruptible(obj);
> + if (ret)
> + return ret;
> +
> ret = i915_gem_object_wait(obj,
> - I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED,
> + I915_WAIT_INTERRUPTIBLE,
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> - return ret;
> + goto err_unlock;
>
> ret = i915_gem_object_pin_pages(obj);
> if (ret)
> - return ret;
> + goto err_unlock;
>
> if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ ||
> !static_cpu_has(X86_FEATURE_CLFLUSH)) {
> @@ -719,6 +722,8 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj,
>
> err_unpin:
> i915_gem_object_unpin_pages(obj);
> +err_unlock:
> + i915_gem_object_unlock(obj);
> return ret;
> }
>
> @@ -727,23 +732,24 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
> {
> int ret;
>
> - lockdep_assert_held(&obj->base.dev->struct_mutex);
> -
> *needs_clflush = 0;
> if (!i915_gem_object_has_struct_page(obj))
> return -ENODEV;
>
> + ret = i915_gem_object_lock_interruptible(obj);
> + if (ret)
> + return ret;
> +
> ret = i915_gem_object_wait(obj,
> I915_WAIT_INTERRUPTIBLE |
> - I915_WAIT_LOCKED |
> I915_WAIT_ALL,
> MAX_SCHEDULE_TIMEOUT);
> if (ret)
> - return ret;
> + goto err_unlock;
>
> ret = i915_gem_object_pin_pages(obj);
> if (ret)
> - return ret;
> + goto err_unlock;
>
> if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE ||
> !static_cpu_has(X86_FEATURE_CLFLUSH)) {
> @@ -780,5 +786,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
>
> err_unpin:
> i915_gem_object_unpin_pages(obj);
> +err_unlock:
> + i915_gem_object_unlock(obj);
> return ret;
> }
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> index a2761029f0c3..080f69358224 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> @@ -1076,7 +1076,9 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
> if (use_cpu_reloc(cache, obj))
> return NULL;
>
> + i915_gem_object_lock(obj);
> err = i915_gem_object_set_to_gtt_domain(obj, true);
> + i915_gem_object_unlock(obj);
> if (err)
> return ERR_PTR(err);
>
> @@ -1165,6 +1167,26 @@ static void clflush_write32(u32 *addr, u32 value, unsigned int flushes)
> *addr = value;
> }
>
> +static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma)
> +{
> + struct drm_i915_gem_object *obj = vma->obj;
> + int err;
> +
> + i915_vma_lock(vma);
> +
> + if (obj->cache_dirty & ~obj->cache_coherent)
> + i915_gem_clflush_object(obj, 0);
> + obj->write_domain = 0;
> +
> + err = i915_request_await_object(rq, vma->obj, true);
> + if (err == 0)
> + err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
> +
> + i915_vma_unlock(vma);
> +
> + return err;
> +}
> +
> static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
> struct i915_vma *vma,
> unsigned int len)
> @@ -1176,15 +1198,6 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
> u32 *cmd;
> int err;
>
> - if (DBG_FORCE_RELOC == FORCE_GPU_RELOC) {
> - obj = vma->obj;
> - if (obj->cache_dirty & ~obj->cache_coherent)
> - i915_gem_clflush_object(obj, 0);
> - obj->write_domain = 0;
> - }
> -
> - GEM_BUG_ON(vma->obj->write_domain & I915_GEM_DOMAIN_CPU);
> -
> obj = i915_gem_batch_pool_get(&eb->engine->batch_pool, PAGE_SIZE);
> if (IS_ERR(obj))
> return PTR_ERR(obj);
> @@ -1213,7 +1226,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
> goto err_unpin;
> }
>
> - err = i915_request_await_object(rq, vma->obj, true);
> + err = reloc_move_to_gpu(rq, vma);
> if (err)
> goto err_request;
>
> @@ -1221,14 +1234,12 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb,
> batch->node.start, PAGE_SIZE,
> cache->gen > 5 ? 0 : I915_DISPATCH_SECURE);
> if (err)
> - goto err_request;
> + goto skip_request;
>
> + i915_vma_lock(batch);
> GEM_BUG_ON(!reservation_object_test_signaled_rcu(batch->resv, true));
> err = i915_vma_move_to_active(batch, rq, 0);
> - if (err)
> - goto skip_request;
> -
> - err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
> + i915_vma_unlock(batch);
> if (err)
> goto skip_request;
>
> @@ -1837,24 +1848,59 @@ static int eb_relocate(struct i915_execbuffer *eb)
> static int eb_move_to_gpu(struct i915_execbuffer *eb)
> {
> const unsigned int count = eb->buffer_count;
> + struct ww_acquire_ctx acquire;
> unsigned int i;
> - int err;
> + int err = 0;
> +
> + ww_acquire_init(&acquire, &reservation_ww_class);
>
> for (i = 0; i < count; i++) {
> + struct i915_vma *vma = eb->vma[i];
> +
> + err = ww_mutex_lock_interruptible(&vma->resv->lock, &acquire);
> + if (!err)
> + continue;
> +
> + GEM_BUG_ON(err == -EALREADY); /* No duplicate vma */
> +
> + if (err == -EDEADLK) {
> + GEM_BUG_ON(i == 0);
> + do {
> + int j = i - 1;
> +
> + ww_mutex_unlock(&eb->vma[j]->resv->lock);
> +
> + swap(eb->flags[i], eb->flags[j]);
> + swap(eb->vma[i], eb->vma[j]);
> + eb->vma[i]->exec_flags = &eb->flags[i];
> + } while (--i);
> + GEM_BUG_ON(vma != eb->vma[0]);
> + vma->exec_flags = &eb->flags[0];
> +
> + err = ww_mutex_lock_slow_interruptible(&vma->resv->lock,
> + &acquire);
> + }
> + if (err)
> + break;
> + }
> + ww_acquire_done(&acquire);
> +
> + while (i--) {
> unsigned int flags = eb->flags[i];
> struct i915_vma *vma = eb->vma[i];
> struct drm_i915_gem_object *obj = vma->obj;
>
> + assert_vma_held(vma);
> +
> if (flags & EXEC_OBJECT_CAPTURE) {
> struct i915_capture_list *capture;
>
> capture = kmalloc(sizeof(*capture), GFP_KERNEL);
> - if (unlikely(!capture))
> - return -ENOMEM;
> -
> - capture->next = eb->request->capture_list;
> - capture->vma = eb->vma[i];
> - eb->request->capture_list = capture;
> + if (capture) {
> + capture->next = eb->request->capture_list;
> + capture->vma = vma;
> + eb->request->capture_list = capture;
> + }
> }
>
> /*
> @@ -1874,24 +1920,15 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
> flags &= ~EXEC_OBJECT_ASYNC;
> }
>
> - if (flags & EXEC_OBJECT_ASYNC)
> - continue;
> -
> - err = i915_request_await_object
> - (eb->request, obj, flags & EXEC_OBJECT_WRITE);
> - if (err)
> - return err;
> - }
> + if (err == 0 && !(flags & EXEC_OBJECT_ASYNC)) {
> + err = i915_request_await_object
> + (eb->request, obj, flags & EXEC_OBJECT_WRITE);
> + }
>
> - for (i = 0; i < count; i++) {
> - unsigned int flags = eb->flags[i];
> - struct i915_vma *vma = eb->vma[i];
> + if (err == 0)
> + err = i915_vma_move_to_active(vma, eb->request, flags);
>
> - err = i915_vma_move_to_active(vma, eb->request, flags);
> - if (unlikely(err)) {
> - i915_request_skip(eb->request, err);
> - return err;
> - }
> + i915_vma_unlock(vma);
>
> __eb_unreserve_vma(vma, flags);
> vma->exec_flags = NULL;
> @@ -1899,12 +1936,20 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
> if (unlikely(flags & __EXEC_OBJECT_HAS_REF))
> i915_vma_put(vma);
> }
> + ww_acquire_fini(&acquire);
> +
> + if (unlikely(err))
> + goto err_skip;
> +
> eb->exec = NULL;
>
> /* Unconditionally flush any chipset caches (for streaming writes). */
> i915_gem_chipset_flush(eb->i915);
> -
> return 0;
> +
> +err_skip:
> + i915_request_skip(eb->request, err);
> + return err;
> }
>
> static bool i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_fence.c b/drivers/gpu/drm/i915/gem/i915_gem_fence.c
> new file mode 100644
> index 000000000000..021425f30a66
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_fence.c
> @@ -0,0 +1,99 @@
> +/*
> + * SPDX-License-Identifier: MIT
> + *
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#include "i915_gem_object.h"
> +
> +#include "../i915_drv.h"
> +
> +static DEFINE_SPINLOCK(fence_lock);
> +
> +struct stub_fence {
> + struct dma_fence dma;
> + struct i915_sw_fence chain;
> +};
> +
> +static int __i915_sw_fence_call
> +stub_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
> +{
> + struct stub_fence *stub = container_of(fence, typeof(*stub), chain);
> +
> + switch (state) {
> + case FENCE_COMPLETE:
> + dma_fence_signal(&stub->dma);
> + break;
> +
> + case FENCE_FREE:
> + dma_fence_put(&stub->dma);
> + break;
> + }
> +
> + return NOTIFY_DONE;
> +}
> +
> +static const char *stub_driver_name(struct dma_fence *fence)
> +{
> + return DRIVER_NAME;
> +}
> +
> +static const char *stub_timeline_name(struct dma_fence *fence)
> +{
> + return "object";
> +}
> +
> +static void stub_release(struct dma_fence *fence)
> +{
> + struct stub_fence *stub = container_of(fence, typeof(*stub), dma);
> +
> + i915_sw_fence_fini(&stub->chain);
> +
> + BUILD_BUG_ON(offsetof(typeof(*stub), dma));
> + dma_fence_free(&stub->dma);
> +}
> +
> +static const struct dma_fence_ops stub_fence_ops = {
> + .get_driver_name = stub_driver_name,
> + .get_timeline_name = stub_timeline_name,
> + .release = stub_release,
> +};
> +
> +struct dma_fence *
> +i915_gem_object_lock_fence(struct drm_i915_gem_object *obj)
> +{
> + struct stub_fence *stub;
> +
> + assert_object_held(obj);
> +
> + stub = kmalloc(sizeof(*stub), GFP_KERNEL);
> + if (!stub)
> + return NULL;
> +
> + dma_fence_init(&stub->dma, &stub_fence_ops, &fence_lock,
> + to_i915(obj->base.dev)->mm.unordered_timeline,
> + 0);
> + i915_sw_fence_init(&stub->chain, stub_notify);
> +
> + if (i915_sw_fence_await_reservation(&stub->chain,
> + obj->resv, NULL,
> + true, I915_FENCE_TIMEOUT,
> + I915_FENCE_GFP) < 0)
> + goto err;
> +
> + reservation_object_add_excl_fence(obj->resv, &stub->dma);
> +
> + return &stub->dma;
> +
> +err:
> + stub_release(&stub->dma);
> + return NULL;
> +}
> +
> +void i915_gem_object_unlock_fence(struct drm_i915_gem_object *obj,
> + struct dma_fence *fence)
> +{
> + struct stub_fence *stub = container_of(fence, typeof(*stub), dma);
> +
> + i915_sw_fence_commit(&stub->chain);
> +}
Nifty.
Hopefully I didn't miss anything,
Reviewed-by: Matthew Auld <matthew.auld at intel.com>
More information about the Intel-gfx
mailing list