All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Auld <matthew.auld@intel.com>
To: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH v5 1/6] drm/i915: Initial introduction of vma resources
Date: Thu, 6 Jan 2022 15:22:26 +0000	[thread overview]
Message-ID: <32e64ade-e4fc-7fb0-1f5d-cd9406c91bf6@intel.com> (raw)
In-Reply-To: <20220104125132.35179-2-thomas.hellstrom@linux.intel.com>

On 04/01/2022 12:51, Thomas Hellström wrote:
> Introduce vma resources, sort of similar to TTM resources,  needed for
> asynchronous bind management. Initially we will use them to hold
> completion of unbinding when we capture data from a vma, but they will
> be used extensively in upcoming patches for asynchronous vma unbinding.
> 
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/Makefile                 |   1 +
>   .../gpu/drm/i915/gem/i915_gem_execbuffer.c    |   2 +-
>   drivers/gpu/drm/i915/i915_vma.c               |  55 +++++++-
>   drivers/gpu/drm/i915/i915_vma.h               |  19 ++-
>   drivers/gpu/drm/i915/i915_vma_resource.c      | 124 ++++++++++++++++++
>   drivers/gpu/drm/i915/i915_vma_resource.h      |  70 ++++++++++
>   drivers/gpu/drm/i915/i915_vma_snapshot.c      |  15 +--
>   drivers/gpu/drm/i915/i915_vma_snapshot.h      |   7 +-
>   drivers/gpu/drm/i915/i915_vma_types.h         |   5 +
>   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  99 ++++++++------
>   10 files changed, 334 insertions(+), 63 deletions(-)
>   create mode 100644 drivers/gpu/drm/i915/i915_vma_resource.c
>   create mode 100644 drivers/gpu/drm/i915/i915_vma_resource.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 1b62b9f65196..98433ad74194 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -174,6 +174,7 @@ i915-y += \
>   	  i915_trace_points.o \
>   	  i915_ttm_buddy_manager.o \
>   	  i915_vma.o \
> +	  i915_vma_resource.o \
>   	  i915_vma_snapshot.o \
>   	  intel_wopcm.o
>   
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> index e9541244027a..72e497745c12 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> @@ -1422,7 +1422,7 @@ eb_relocate_entry(struct i915_execbuffer *eb,
>   			mutex_lock(&vma->vm->mutex);
>   			err = i915_vma_bind(target->vma,
>   					    target->vma->obj->cache_level,
> -					    PIN_GLOBAL, NULL);
> +					    PIN_GLOBAL, NULL, NULL);
>   			mutex_unlock(&vma->vm->mutex);
>   			reloc_cache_remap(&eb->reloc_cache, ev->vma->obj);
>   			if (err)
> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> index be208a8f1ed0..7097c5016431 100644
> --- a/drivers/gpu/drm/i915/i915_vma.c
> +++ b/drivers/gpu/drm/i915/i915_vma.c
> @@ -37,6 +37,7 @@
>   #include "i915_sw_fence_work.h"
>   #include "i915_trace.h"
>   #include "i915_vma.h"
> +#include "i915_vma_resource.h"
>   
>   static struct kmem_cache *slab_vmas;
>   
> @@ -380,6 +381,8 @@ static int i915_vma_verify_bind_complete(struct i915_vma *vma)
>    * @cache_level: mapping cache level
>    * @flags: flags like global or local mapping
>    * @work: preallocated worker for allocating and binding the PTE
> + * @vma_res: pointer to a preallocated vma resource. The resource is either
> + * consumed or freed.
>    *
>    * DMA addresses are taken from the scatter-gather table of this object (or of
>    * this VMA in case of non-default GGTT views) and PTE entries set up.
> @@ -388,7 +391,8 @@ static int i915_vma_verify_bind_complete(struct i915_vma *vma)
>   int i915_vma_bind(struct i915_vma *vma,
>   		  enum i915_cache_level cache_level,
>   		  u32 flags,
> -		  struct i915_vma_work *work)
> +		  struct i915_vma_work *work,
> +		  struct i915_vma_resource *vma_res)
>   {
>   	u32 bind_flags;
>   	u32 vma_flags;
> @@ -399,11 +403,15 @@ int i915_vma_bind(struct i915_vma *vma,
>   
>   	if (GEM_DEBUG_WARN_ON(range_overflows(vma->node.start,
>   					      vma->node.size,
> -					      vma->vm->total)))
> +					      vma->vm->total))) {
> +		kfree(vma_res);
>   		return -ENODEV;
> +	}
>   
> -	if (GEM_DEBUG_WARN_ON(!flags))
> +	if (GEM_DEBUG_WARN_ON(!flags)) {
> +		kfree(vma_res);
>   		return -EINVAL;
> +	}
>   
>   	bind_flags = flags;
>   	bind_flags &= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
> @@ -412,11 +420,21 @@ int i915_vma_bind(struct i915_vma *vma,
>   	vma_flags &= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
>   
>   	bind_flags &= ~vma_flags;
> -	if (bind_flags == 0)
> +	if (bind_flags == 0) {
> +		kfree(vma_res);
>   		return 0;
> +	}
>   
>   	GEM_BUG_ON(!atomic_read(&vma->pages_count));
>   
> +	if (vma->resource || !vma_res) {
> +		/* Rebinding with an additional I915_VMA_*_BIND */
> +		GEM_WARN_ON(!vma_flags);
> +		kfree(vma_res);
> +	} else {
> +		i915_vma_resource_init(vma_res);
> +		vma->resource = vma_res;
> +	}
>   	trace_i915_vma_bind(vma, bind_flags);
>   	if (work && bind_flags & vma->vm->bind_async_flags) {
>   		struct dma_fence *prev;
> @@ -1279,6 +1297,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   {
>   	struct i915_vma_work *work = NULL;
>   	struct dma_fence *moving = NULL;
> +	struct i915_vma_resource *vma_res = NULL;
>   	intel_wakeref_t wakeref = 0;
>   	unsigned int bound;
>   	int err;
> @@ -1333,6 +1352,12 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   		}
>   	}
>   
> +	vma_res = i915_vma_resource_alloc();
> +	if (IS_ERR(vma_res)) {
> +		err = PTR_ERR(vma_res);
> +		goto err_fence;
> +	}
> +
>   	/*
>   	 * Differentiate between user/kernel vma inside the aliasing-ppgtt.
>   	 *
> @@ -1353,7 +1378,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	err = mutex_lock_interruptible_nested(&vma->vm->mutex,
>   					      !(flags & PIN_GLOBAL));
>   	if (err)
> -		goto err_fence;
> +		goto err_vma_res;
>   
>   	/* No more allocations allowed now we hold vm->mutex */
>   
> @@ -1394,7 +1419,8 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	GEM_BUG_ON(!vma->pages);
>   	err = i915_vma_bind(vma,
>   			    vma->obj->cache_level,
> -			    flags, work);
> +			    flags, work, vma_res);
> +	vma_res = NULL;
>   	if (err)
>   		goto err_remove;
>   
> @@ -1417,6 +1443,8 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	i915_active_release(&vma->active);
>   err_unlock:
>   	mutex_unlock(&vma->vm->mutex);
> +err_vma_res:
> +	kfree(vma_res);
>   err_fence:
>   	if (work)
>   		dma_fence_work_commit_imm(&work->base);
> @@ -1567,6 +1595,7 @@ void i915_vma_release(struct kref *ref)
>   	i915_vm_put(vma->vm);
>   
>   	i915_active_fini(&vma->active);
> +	GEM_WARN_ON(vma->resource);
>   	i915_vma_free(vma);
>   }
>   
> @@ -1715,6 +1744,8 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
>   
>   void __i915_vma_evict(struct i915_vma *vma)
>   {
> +	struct dma_fence *unbind_fence;
> +
>   	GEM_BUG_ON(i915_vma_is_pinned(vma));
>   
>   	if (i915_vma_is_map_and_fenceable(vma)) {
> @@ -1752,8 +1783,20 @@ void __i915_vma_evict(struct i915_vma *vma)
>   	atomic_and(~(I915_VMA_BIND_MASK | I915_VMA_ERROR | I915_VMA_GGTT_WRITE),
>   		   &vma->flags);
>   
> +	unbind_fence = i915_vma_resource_unbind(vma->resource);
> +	i915_vma_resource_put(vma->resource);
> +	vma->resource = NULL;
> +
>   	i915_vma_detach(vma);
>   	vma_unbind_pages(vma);
> +
> +	/*
> +	 * This uninterruptible wait under the vm mutex is currently
> +	 * only ever blocking while the vma is being captured from.
> +	 * With async unbinding, this wait here will be removed.
> +	 */
> +	dma_fence_wait(unbind_fence, false);
> +	dma_fence_put(unbind_fence);
>   }
>   
>   int __i915_vma_unbind(struct i915_vma *vma)
> diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
> index 32719431b3df..de0f3e44cdfa 100644
> --- a/drivers/gpu/drm/i915/i915_vma.h
> +++ b/drivers/gpu/drm/i915/i915_vma.h
> @@ -37,6 +37,7 @@
>   
>   #include "i915_active.h"
>   #include "i915_request.h"
> +#include "i915_vma_resource.h"
>   #include "i915_vma_types.h"
>   
>   struct i915_vma *
> @@ -204,7 +205,8 @@ struct i915_vma_work *i915_vma_work(void);
>   int i915_vma_bind(struct i915_vma *vma,
>   		  enum i915_cache_level cache_level,
>   		  u32 flags,
> -		  struct i915_vma_work *work);
> +		  struct i915_vma_work *work,
> +		  struct i915_vma_resource *vma_res);
>   
>   bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long color);
>   bool i915_vma_misplaced(const struct i915_vma *vma,
> @@ -428,6 +430,21 @@ static inline int i915_vma_sync(struct i915_vma *vma)
>   	return i915_active_wait(&vma->active);
>   }
>   
> +/**
> + * i915_vma_get_current_resource - Get the current resource of the vma
> + * @vma: The vma to get the current resource from.
> + *
> + * It's illegal to call this function if the vma is not bound.
> + *
> + * Return: A refcounted pointer to the current vma resource
> + * of the vma, assuming the vma is bound.
> + */
> +static inline struct i915_vma_resource *
> +i915_vma_get_current_resource(struct i915_vma *vma)
> +{
> +	return i915_vma_resource_get(vma->resource);
> +}
> +
>   void i915_vma_module_exit(void);
>   int i915_vma_module_init(void);
>   
> diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c b/drivers/gpu/drm/i915/i915_vma_resource.c
> new file mode 100644
> index 000000000000..833e987bed2a
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_vma_resource.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +#include <linux/slab.h>
> +
> +#include "i915_vma_resource.h"
> +
> +/* Callbacks for the unbind dma-fence. */
> +static const char *get_driver_name(struct dma_fence *fence)
> +{
> +	return "vma unbind fence";
> +}
> +
> +static const char *get_timeline_name(struct dma_fence *fence)
> +{
> +	return "unbound";
> +}
> +
> +static struct dma_fence_ops unbind_fence_ops = {
> +	.get_driver_name = get_driver_name,
> +	.get_timeline_name = get_timeline_name,
> +};
> +
> +/**
> + * i915_vma_resource_init - Initialize a vma resource.
> + * @vma_res: The vma resource to initialize
> + *
> + * Initializes a vma resource allocated using i915_vma_resource_alloc().
> + * The reason for having separate allocate and initialize function is that
> + * initialization may need to be performed from under a lock where
> + * allocation is not allowed.
> + */
> +void i915_vma_resource_init(struct i915_vma_resource *vma_res)
> +{
> +	spin_lock_init(&vma_res->lock);
> +	dma_fence_init(&vma_res->unbind_fence, &unbind_fence_ops,
> +		       &vma_res->lock, 0, 0);
> +	refcount_set(&vma_res->hold_count, 1);
> +}
> +
> +/**
> + * i915_vma_resource_alloc - Allocate a vma resource
> + *
> + * Return: A pointer to a cleared struct i915_vma_resource or
> + * a -ENOMEM error pointer if allocation fails.
> + */
> +struct i915_vma_resource *i915_vma_resource_alloc(void)
> +{
> +	struct i915_vma_resource *vma_res =
> +		kzalloc(sizeof(*vma_res), GFP_KERNEL);
> +
> +	return vma_res ? vma_res : ERR_PTR(-ENOMEM);
> +}
> +
> +static void __i915_vma_resource_unhold(struct i915_vma_resource *vma_res)
> +{
> +	if (refcount_dec_and_test(&vma_res->hold_count))
> +		dma_fence_signal(&vma_res->unbind_fence);
> +}
> +
> +/**
> + * i915_vma_resource_unhold - Unhold the signaling of the vma resource unbind
> + * fence.
> + * @vma_res: The vma resource.
> + * @lockdep_cookie: The lockdep cookie returned from i915_vma_resource_hold.
> + *
> + * The function may leave a dma_fence critical section.
> + */
> +void i915_vma_resource_unhold(struct i915_vma_resource *vma_res,
> +			      bool lockdep_cookie)
> +{
> +	dma_fence_end_signalling(lockdep_cookie);
> +
> +	if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> +		unsigned long irq_flags;
> +
> +		/* Inefficient open-coded might_lock_irqsave() */
> +		spin_lock_irqsave(&vma_res->lock, irq_flags);
> +		spin_unlock_irqrestore(&vma_res->lock, irq_flags);
> +	}
> +
> +	__i915_vma_resource_unhold(vma_res);
> +}
> +
> +/**
> + * i915_vma_resource_hold - Hold the signaling of the vma resource unbind fence.
> + * @vma_res: The vma resource.
> + * @lockdep_cookie: Pointer to a bool serving as a lockdep cooke that should
> + * be given as an argument to the pairing i915_vma_resource_unhold.
> + *
> + * If returning true, the function enters a dma_fence signalling critical
> + * section is not in one already.

if not?

> + *
> + * Return: true if holding successful, false if not.
> + */
> +bool i915_vma_resource_hold(struct i915_vma_resource *vma_res,
> +			    bool *lockdep_cookie)
> +{
> +	bool held = refcount_inc_not_zero(&vma_res->hold_count);
> +
> +	if (held)
> +		*lockdep_cookie = dma_fence_begin_signalling();
> +
> +	return held;
> +}
> +
> +/**
> + * i915_vma_resource_unbind - Unbind a vma resource
> + * @vma_res: The vma resource to unbind.
> + *
> + * At this point this function does little more than publish a fence that
> + * signals immediately unless signaling is held back.
> + *
> + * Return: A refcounted pointer to a dma-fence that signals when unbinding is
> + * complete.
> + */
> +struct dma_fence *
> +i915_vma_resource_unbind(struct i915_vma_resource *vma_res)
> +{
> +	__i915_vma_resource_unhold(vma_res);
> +	dma_fence_get(&vma_res->unbind_fence);
> +	return &vma_res->unbind_fence;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_vma_resource.h b/drivers/gpu/drm/i915/i915_vma_resource.h
> new file mode 100644
> index 000000000000..34744da23072
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_vma_resource.h
> @@ -0,0 +1,70 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#ifndef __I915_VMA_RESOURCE_H__
> +#define __I915_VMA_RESOURCE_H__
> +
> +#include <linux/dma-fence.h>
> +#include <linux/refcount.h>
> +
> +/**
> + * struct i915_vma_resource - Snapshotted unbind information.
> + * @unbind_fence: Fence to mark unbinding complete. Note that this fence
> + * is not considered published until unbind is scheduled, and as such it
> + * is illegal to access this fence before scheduled unbind other than
> + * for refcounting.
> + * @lock: The @unbind_fence lock. We're also using it to protect the weak
> + * pointer to the struct i915_vma, @vma during lookup and takedown.

Not sure what the @vma here is referring to?

Otherwise,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

WARNING: multiple messages have this Message-ID (diff)
From: Matthew Auld <matthew.auld@intel.com>
To: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v5 1/6] drm/i915: Initial introduction of vma resources
Date: Thu, 6 Jan 2022 15:22:26 +0000	[thread overview]
Message-ID: <32e64ade-e4fc-7fb0-1f5d-cd9406c91bf6@intel.com> (raw)
In-Reply-To: <20220104125132.35179-2-thomas.hellstrom@linux.intel.com>

On 04/01/2022 12:51, Thomas Hellström wrote:
> Introduce vma resources, sort of similar to TTM resources,  needed for
> asynchronous bind management. Initially we will use them to hold
> completion of unbinding when we capture data from a vma, but they will
> be used extensively in upcoming patches for asynchronous vma unbinding.
> 
> Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/Makefile                 |   1 +
>   .../gpu/drm/i915/gem/i915_gem_execbuffer.c    |   2 +-
>   drivers/gpu/drm/i915/i915_vma.c               |  55 +++++++-
>   drivers/gpu/drm/i915/i915_vma.h               |  19 ++-
>   drivers/gpu/drm/i915/i915_vma_resource.c      | 124 ++++++++++++++++++
>   drivers/gpu/drm/i915/i915_vma_resource.h      |  70 ++++++++++
>   drivers/gpu/drm/i915/i915_vma_snapshot.c      |  15 +--
>   drivers/gpu/drm/i915/i915_vma_snapshot.h      |   7 +-
>   drivers/gpu/drm/i915/i915_vma_types.h         |   5 +
>   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  99 ++++++++------
>   10 files changed, 334 insertions(+), 63 deletions(-)
>   create mode 100644 drivers/gpu/drm/i915/i915_vma_resource.c
>   create mode 100644 drivers/gpu/drm/i915/i915_vma_resource.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 1b62b9f65196..98433ad74194 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -174,6 +174,7 @@ i915-y += \
>   	  i915_trace_points.o \
>   	  i915_ttm_buddy_manager.o \
>   	  i915_vma.o \
> +	  i915_vma_resource.o \
>   	  i915_vma_snapshot.o \
>   	  intel_wopcm.o
>   
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> index e9541244027a..72e497745c12 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
> @@ -1422,7 +1422,7 @@ eb_relocate_entry(struct i915_execbuffer *eb,
>   			mutex_lock(&vma->vm->mutex);
>   			err = i915_vma_bind(target->vma,
>   					    target->vma->obj->cache_level,
> -					    PIN_GLOBAL, NULL);
> +					    PIN_GLOBAL, NULL, NULL);
>   			mutex_unlock(&vma->vm->mutex);
>   			reloc_cache_remap(&eb->reloc_cache, ev->vma->obj);
>   			if (err)
> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> index be208a8f1ed0..7097c5016431 100644
> --- a/drivers/gpu/drm/i915/i915_vma.c
> +++ b/drivers/gpu/drm/i915/i915_vma.c
> @@ -37,6 +37,7 @@
>   #include "i915_sw_fence_work.h"
>   #include "i915_trace.h"
>   #include "i915_vma.h"
> +#include "i915_vma_resource.h"
>   
>   static struct kmem_cache *slab_vmas;
>   
> @@ -380,6 +381,8 @@ static int i915_vma_verify_bind_complete(struct i915_vma *vma)
>    * @cache_level: mapping cache level
>    * @flags: flags like global or local mapping
>    * @work: preallocated worker for allocating and binding the PTE
> + * @vma_res: pointer to a preallocated vma resource. The resource is either
> + * consumed or freed.
>    *
>    * DMA addresses are taken from the scatter-gather table of this object (or of
>    * this VMA in case of non-default GGTT views) and PTE entries set up.
> @@ -388,7 +391,8 @@ static int i915_vma_verify_bind_complete(struct i915_vma *vma)
>   int i915_vma_bind(struct i915_vma *vma,
>   		  enum i915_cache_level cache_level,
>   		  u32 flags,
> -		  struct i915_vma_work *work)
> +		  struct i915_vma_work *work,
> +		  struct i915_vma_resource *vma_res)
>   {
>   	u32 bind_flags;
>   	u32 vma_flags;
> @@ -399,11 +403,15 @@ int i915_vma_bind(struct i915_vma *vma,
>   
>   	if (GEM_DEBUG_WARN_ON(range_overflows(vma->node.start,
>   					      vma->node.size,
> -					      vma->vm->total)))
> +					      vma->vm->total))) {
> +		kfree(vma_res);
>   		return -ENODEV;
> +	}
>   
> -	if (GEM_DEBUG_WARN_ON(!flags))
> +	if (GEM_DEBUG_WARN_ON(!flags)) {
> +		kfree(vma_res);
>   		return -EINVAL;
> +	}
>   
>   	bind_flags = flags;
>   	bind_flags &= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
> @@ -412,11 +420,21 @@ int i915_vma_bind(struct i915_vma *vma,
>   	vma_flags &= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
>   
>   	bind_flags &= ~vma_flags;
> -	if (bind_flags == 0)
> +	if (bind_flags == 0) {
> +		kfree(vma_res);
>   		return 0;
> +	}
>   
>   	GEM_BUG_ON(!atomic_read(&vma->pages_count));
>   
> +	if (vma->resource || !vma_res) {
> +		/* Rebinding with an additional I915_VMA_*_BIND */
> +		GEM_WARN_ON(!vma_flags);
> +		kfree(vma_res);
> +	} else {
> +		i915_vma_resource_init(vma_res);
> +		vma->resource = vma_res;
> +	}
>   	trace_i915_vma_bind(vma, bind_flags);
>   	if (work && bind_flags & vma->vm->bind_async_flags) {
>   		struct dma_fence *prev;
> @@ -1279,6 +1297,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   {
>   	struct i915_vma_work *work = NULL;
>   	struct dma_fence *moving = NULL;
> +	struct i915_vma_resource *vma_res = NULL;
>   	intel_wakeref_t wakeref = 0;
>   	unsigned int bound;
>   	int err;
> @@ -1333,6 +1352,12 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   		}
>   	}
>   
> +	vma_res = i915_vma_resource_alloc();
> +	if (IS_ERR(vma_res)) {
> +		err = PTR_ERR(vma_res);
> +		goto err_fence;
> +	}
> +
>   	/*
>   	 * Differentiate between user/kernel vma inside the aliasing-ppgtt.
>   	 *
> @@ -1353,7 +1378,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	err = mutex_lock_interruptible_nested(&vma->vm->mutex,
>   					      !(flags & PIN_GLOBAL));
>   	if (err)
> -		goto err_fence;
> +		goto err_vma_res;
>   
>   	/* No more allocations allowed now we hold vm->mutex */
>   
> @@ -1394,7 +1419,8 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	GEM_BUG_ON(!vma->pages);
>   	err = i915_vma_bind(vma,
>   			    vma->obj->cache_level,
> -			    flags, work);
> +			    flags, work, vma_res);
> +	vma_res = NULL;
>   	if (err)
>   		goto err_remove;
>   
> @@ -1417,6 +1443,8 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
>   	i915_active_release(&vma->active);
>   err_unlock:
>   	mutex_unlock(&vma->vm->mutex);
> +err_vma_res:
> +	kfree(vma_res);
>   err_fence:
>   	if (work)
>   		dma_fence_work_commit_imm(&work->base);
> @@ -1567,6 +1595,7 @@ void i915_vma_release(struct kref *ref)
>   	i915_vm_put(vma->vm);
>   
>   	i915_active_fini(&vma->active);
> +	GEM_WARN_ON(vma->resource);
>   	i915_vma_free(vma);
>   }
>   
> @@ -1715,6 +1744,8 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
>   
>   void __i915_vma_evict(struct i915_vma *vma)
>   {
> +	struct dma_fence *unbind_fence;
> +
>   	GEM_BUG_ON(i915_vma_is_pinned(vma));
>   
>   	if (i915_vma_is_map_and_fenceable(vma)) {
> @@ -1752,8 +1783,20 @@ void __i915_vma_evict(struct i915_vma *vma)
>   	atomic_and(~(I915_VMA_BIND_MASK | I915_VMA_ERROR | I915_VMA_GGTT_WRITE),
>   		   &vma->flags);
>   
> +	unbind_fence = i915_vma_resource_unbind(vma->resource);
> +	i915_vma_resource_put(vma->resource);
> +	vma->resource = NULL;
> +
>   	i915_vma_detach(vma);
>   	vma_unbind_pages(vma);
> +
> +	/*
> +	 * This uninterruptible wait under the vm mutex is currently
> +	 * only ever blocking while the vma is being captured from.
> +	 * With async unbinding, this wait here will be removed.
> +	 */
> +	dma_fence_wait(unbind_fence, false);
> +	dma_fence_put(unbind_fence);
>   }
>   
>   int __i915_vma_unbind(struct i915_vma *vma)
> diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
> index 32719431b3df..de0f3e44cdfa 100644
> --- a/drivers/gpu/drm/i915/i915_vma.h
> +++ b/drivers/gpu/drm/i915/i915_vma.h
> @@ -37,6 +37,7 @@
>   
>   #include "i915_active.h"
>   #include "i915_request.h"
> +#include "i915_vma_resource.h"
>   #include "i915_vma_types.h"
>   
>   struct i915_vma *
> @@ -204,7 +205,8 @@ struct i915_vma_work *i915_vma_work(void);
>   int i915_vma_bind(struct i915_vma *vma,
>   		  enum i915_cache_level cache_level,
>   		  u32 flags,
> -		  struct i915_vma_work *work);
> +		  struct i915_vma_work *work,
> +		  struct i915_vma_resource *vma_res);
>   
>   bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long color);
>   bool i915_vma_misplaced(const struct i915_vma *vma,
> @@ -428,6 +430,21 @@ static inline int i915_vma_sync(struct i915_vma *vma)
>   	return i915_active_wait(&vma->active);
>   }
>   
> +/**
> + * i915_vma_get_current_resource - Get the current resource of the vma
> + * @vma: The vma to get the current resource from.
> + *
> + * It's illegal to call this function if the vma is not bound.
> + *
> + * Return: A refcounted pointer to the current vma resource
> + * of the vma, assuming the vma is bound.
> + */
> +static inline struct i915_vma_resource *
> +i915_vma_get_current_resource(struct i915_vma *vma)
> +{
> +	return i915_vma_resource_get(vma->resource);
> +}
> +
>   void i915_vma_module_exit(void);
>   int i915_vma_module_init(void);
>   
> diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c b/drivers/gpu/drm/i915/i915_vma_resource.c
> new file mode 100644
> index 000000000000..833e987bed2a
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_vma_resource.c
> @@ -0,0 +1,124 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +#include <linux/slab.h>
> +
> +#include "i915_vma_resource.h"
> +
> +/* Callbacks for the unbind dma-fence. */
> +static const char *get_driver_name(struct dma_fence *fence)
> +{
> +	return "vma unbind fence";
> +}
> +
> +static const char *get_timeline_name(struct dma_fence *fence)
> +{
> +	return "unbound";
> +}
> +
> +static struct dma_fence_ops unbind_fence_ops = {
> +	.get_driver_name = get_driver_name,
> +	.get_timeline_name = get_timeline_name,
> +};
> +
> +/**
> + * i915_vma_resource_init - Initialize a vma resource.
> + * @vma_res: The vma resource to initialize
> + *
> + * Initializes a vma resource allocated using i915_vma_resource_alloc().
> + * The reason for having separate allocate and initialize function is that
> + * initialization may need to be performed from under a lock where
> + * allocation is not allowed.
> + */
> +void i915_vma_resource_init(struct i915_vma_resource *vma_res)
> +{
> +	spin_lock_init(&vma_res->lock);
> +	dma_fence_init(&vma_res->unbind_fence, &unbind_fence_ops,
> +		       &vma_res->lock, 0, 0);
> +	refcount_set(&vma_res->hold_count, 1);
> +}
> +
> +/**
> + * i915_vma_resource_alloc - Allocate a vma resource
> + *
> + * Return: A pointer to a cleared struct i915_vma_resource or
> + * a -ENOMEM error pointer if allocation fails.
> + */
> +struct i915_vma_resource *i915_vma_resource_alloc(void)
> +{
> +	struct i915_vma_resource *vma_res =
> +		kzalloc(sizeof(*vma_res), GFP_KERNEL);
> +
> +	return vma_res ? vma_res : ERR_PTR(-ENOMEM);
> +}
> +
> +static void __i915_vma_resource_unhold(struct i915_vma_resource *vma_res)
> +{
> +	if (refcount_dec_and_test(&vma_res->hold_count))
> +		dma_fence_signal(&vma_res->unbind_fence);
> +}
> +
> +/**
> + * i915_vma_resource_unhold - Unhold the signaling of the vma resource unbind
> + * fence.
> + * @vma_res: The vma resource.
> + * @lockdep_cookie: The lockdep cookie returned from i915_vma_resource_hold.
> + *
> + * The function may leave a dma_fence critical section.
> + */
> +void i915_vma_resource_unhold(struct i915_vma_resource *vma_res,
> +			      bool lockdep_cookie)
> +{
> +	dma_fence_end_signalling(lockdep_cookie);
> +
> +	if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> +		unsigned long irq_flags;
> +
> +		/* Inefficient open-coded might_lock_irqsave() */
> +		spin_lock_irqsave(&vma_res->lock, irq_flags);
> +		spin_unlock_irqrestore(&vma_res->lock, irq_flags);
> +	}
> +
> +	__i915_vma_resource_unhold(vma_res);
> +}
> +
> +/**
> + * i915_vma_resource_hold - Hold the signaling of the vma resource unbind fence.
> + * @vma_res: The vma resource.
> + * @lockdep_cookie: Pointer to a bool serving as a lockdep cooke that should
> + * be given as an argument to the pairing i915_vma_resource_unhold.
> + *
> + * If returning true, the function enters a dma_fence signalling critical
> + * section is not in one already.

if not?

> + *
> + * Return: true if holding successful, false if not.
> + */
> +bool i915_vma_resource_hold(struct i915_vma_resource *vma_res,
> +			    bool *lockdep_cookie)
> +{
> +	bool held = refcount_inc_not_zero(&vma_res->hold_count);
> +
> +	if (held)
> +		*lockdep_cookie = dma_fence_begin_signalling();
> +
> +	return held;
> +}
> +
> +/**
> + * i915_vma_resource_unbind - Unbind a vma resource
> + * @vma_res: The vma resource to unbind.
> + *
> + * At this point this function does little more than publish a fence that
> + * signals immediately unless signaling is held back.
> + *
> + * Return: A refcounted pointer to a dma-fence that signals when unbinding is
> + * complete.
> + */
> +struct dma_fence *
> +i915_vma_resource_unbind(struct i915_vma_resource *vma_res)
> +{
> +	__i915_vma_resource_unhold(vma_res);
> +	dma_fence_get(&vma_res->unbind_fence);
> +	return &vma_res->unbind_fence;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_vma_resource.h b/drivers/gpu/drm/i915/i915_vma_resource.h
> new file mode 100644
> index 000000000000..34744da23072
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_vma_resource.h
> @@ -0,0 +1,70 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#ifndef __I915_VMA_RESOURCE_H__
> +#define __I915_VMA_RESOURCE_H__
> +
> +#include <linux/dma-fence.h>
> +#include <linux/refcount.h>
> +
> +/**
> + * struct i915_vma_resource - Snapshotted unbind information.
> + * @unbind_fence: Fence to mark unbinding complete. Note that this fence
> + * is not considered published until unbind is scheduled, and as such it
> + * is illegal to access this fence before scheduled unbind other than
> + * for refcounting.
> + * @lock: The @unbind_fence lock. We're also using it to protect the weak
> + * pointer to the struct i915_vma, @vma during lookup and takedown.

Not sure what the @vma here is referring to?

Otherwise,
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

  reply	other threads:[~2022-01-06 15:22 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-04 12:51 [Intel-gfx] [PATCH v5 0/6] drm/i915: Asynchronous vma unbinding Thomas Hellström
2022-01-04 12:51 ` Thomas Hellström
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 1/6] drm/i915: Initial introduction of vma resources Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-06 15:22   ` Matthew Auld [this message]
2022-01-06 15:22     ` Matthew Auld
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 2/6] drm/i915: Use the vma resource as argument for gtt binding / unbinding Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-06 16:01   ` [Intel-gfx] " Matthew Auld
2022-01-06 16:01     ` Matthew Auld
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 3/6] drm/i915: Don't pin the object pages during pending vma binds Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-06 16:08   ` [Intel-gfx] " Matthew Auld
2022-01-06 16:08     ` Matthew Auld
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 4/6] drm/i915: Use vma resources for async unbinding Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-05 15:52   ` [Intel-gfx] " Matthew Auld
2022-01-05 15:52     ` Matthew Auld
2022-01-05 16:03     ` [Intel-gfx] " Thomas Hellström
2022-01-05 16:03       ` Thomas Hellström
2022-01-06 12:13   ` [Intel-gfx] " Matthew Auld
2022-01-06 12:13     ` Matthew Auld
2022-01-06 16:06   ` kernel test robot
2022-01-06 16:06     ` kernel test robot
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 5/6] drm/i915: Asynchronous migration selftest Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-04 12:51 ` [Intel-gfx] [PATCH v5 6/6] drm/i915: Use struct vma_resource instead of struct vma_snapshot Thomas Hellström
2022-01-04 12:51   ` Thomas Hellström
2022-01-04 15:56 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Asynchronous vma unbinding (rev5) Patchwork
2022-01-04 15:58 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-01-04 16:10 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-01-04 17:52 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=32e64ade-e4fc-7fb0-1f5d-cd9406c91bf6@intel.com \
    --to=matthew.auld@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=thomas.hellstrom@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.