public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: Danilo Krummrich <dakr@redhat.com>,
	airlied@gmail.com, daniel@ffwll.ch, matthew.brost@intel.com,
	sarah.walker@imgtec.com, donald.robson@imgtec.com,
	boris.brezillon@collabora.com, christian.koenig@amd.com,
	faith@gfxstrand.net
Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH drm-misc-next v5 3/6] drm/gpuvm: add an abstraction for a VM / BO combination
Date: Thu, 5 Oct 2023 13:51:00 +0200	[thread overview]
Message-ID: <28528b64-e760-d9a8-c56d-e44672cb02fb@linux.intel.com> (raw)
In-Reply-To: <20230928191624.13703-4-dakr@redhat.com>

Hi,

On 9/28/23 21:16, Danilo Krummrich wrote:
> This patch adds an abstraction layer between the drm_gpuva mappings of
NIT: imperative:  s/This patch adds/Add/
> a particular drm_gem_object and this GEM object itself. The abstraction
> represents a combination of a drm_gem_object and drm_gpuvm. The
> drm_gem_object holds a list of drm_gpuvm_bo structures (the structure
> representing this abstraction), while each drm_gpuvm_bo contains list of
> mappings of this GEM object.
>
> This has multiple advantages:
>
> 1) We can use the drm_gpuvm_bo structure to attach it to various lists
>     of the drm_gpuvm. This is useful for tracking external and evicted
>     objects per VM, which is introduced in subsequent patches.
>
> 2) Finding mappings of a certain drm_gem_object mapped in a certain
>     drm_gpuvm becomes much cheaper.
>
> 3) Drivers can derive and extend the structure to easily represent
>     driver specific states of a BO for a certain GPUVM.
>
> The idea of this abstraction was taken from amdgpu, hence the credit for
> this idea goes to the developers of amdgpu.
>
> Cc: Christian König <christian.koenig@amd.com>
> Signed-off-by: Danilo Krummrich <dakr@redhat.com>
> ---
>   drivers/gpu/drm/drm_gpuvm.c            | 334 +++++++++++++++++++++----
>   drivers/gpu/drm/nouveau/nouveau_uvmm.c |  64 +++--
>   include/drm/drm_gem.h                  |  32 +--
>   include/drm/drm_gpuvm.h                | 177 ++++++++++++-
>   4 files changed, 523 insertions(+), 84 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
> index 6368dfdbe9dd..27100423154b 100644
> --- a/drivers/gpu/drm/drm_gpuvm.c
> +++ b/drivers/gpu/drm/drm_gpuvm.c
> @@ -70,6 +70,18 @@
>    * &drm_gem_object, such as the &drm_gem_object containing the root page table,
>    * but it can also be a 'dummy' object, which can be allocated with
>    * drm_gpuvm_root_object_alloc().
> + *
> + * In order to connect a struct drm_gpuva its backing &drm_gem_object each
> + * &drm_gem_object maintains a list of &drm_gpuvm_bo structures, and each
> + * &drm_gpuvm_bo contains a list of &&drm_gpuva structures.
> + *
> + * A &drm_gpuvm_bo is an abstraction that represents a combination of a
> + * &drm_gpuvm and a &drm_gem_object. Every such combination should be unique.
> + * This is ensured by the API through drm_gpuvm_bo_obtain() and
> + * drm_gpuvm_bo_obtain_prealloc() which first look into the corresponding
> + * &drm_gem_object list of &drm_gpuvm_bos for an existing instance of this
> + * particular combination. If not existent a new instance is created and linked
> + * to the &drm_gem_object.
>    */
>   
>   /**
> @@ -395,21 +407,28 @@
>   /**
>    * DOC: Locking
>    *
> - * Generally, the GPU VA manager does not take care of locking itself, it is
> - * the drivers responsibility to take care about locking. Drivers might want to
> - * protect the following operations: inserting, removing and iterating
> - * &drm_gpuva objects as well as generating all kinds of operations, such as
> - * split / merge or prefetch.
> - *
> - * The GPU VA manager also does not take care of the locking of the backing
> - * &drm_gem_object buffers GPU VA lists by itself; drivers are responsible to
> - * enforce mutual exclusion using either the GEMs dma_resv lock or alternatively
> - * a driver specific external lock. For the latter see also
> - * drm_gem_gpuva_set_lock().
> - *
> - * However, the GPU VA manager contains lockdep checks to ensure callers of its
> - * API hold the corresponding lock whenever the &drm_gem_objects GPU VA list is
> - * accessed by functions such as drm_gpuva_link() or drm_gpuva_unlink().
> + * In terms of managing &drm_gpuva entries DRM GPUVM does not take care of
> + * locking itself, it is the drivers responsibility to take care about locking.
> + * Drivers might want to protect the following operations: inserting, removing
> + * and iterating &drm_gpuva objects as well as generating all kinds of
> + * operations, such as split / merge or prefetch.
> + *
> + * DRM GPUVM also does not take care of the locking of the backing
> + * &drm_gem_object buffers GPU VA lists and &drm_gpuvm_bo abstractions by
> + * itself; drivers are responsible to enforce mutual exclusion using either the
> + * GEMs dma_resv lock or alternatively a driver specific external lock. For the
> + * latter see also drm_gem_gpuva_set_lock().
> + *
> + * However, DRM GPUVM contains lockdep checks to ensure callers of its API hold
> + * the corresponding lock whenever the &drm_gem_objects GPU VA list is accessed
> + * by functions such as drm_gpuva_link() or drm_gpuva_unlink(), but also
> + * drm_gpuvm_bo_obtain() and drm_gpuvm_bo_put().
> + *
> + * The latter is required since on creation and destruction of a &drm_gpuvm_bo
> + * the &drm_gpuvm_bo is attached / removed from the &drm_gem_objects gpuva list.
> + * Subsequent calls to drm_gpuvm_bo_obtain() for the same &drm_gpuvm and
> + * &drm_gem_object must be able to observe previous creations and destructions
> + * of &drm_gpuvm_bos in order to keep instances unique.
>    */
>   
>   /**
> @@ -439,6 +458,7 @@
>    *	{
>    *		struct drm_gpuva_ops *ops;
>    *		struct drm_gpuva_op *op
> + *		struct drm_gpuvm_bo *vm_bo;
>    *
>    *		driver_lock_va_space();
>    *		ops = drm_gpuvm_sm_map_ops_create(gpuvm, addr, range,
> @@ -446,6 +466,10 @@
>    *		if (IS_ERR(ops))
>    *			return PTR_ERR(ops);
>    *
> + *		vm_bo = drm_gpuvm_bo_obtain(gpuvm, obj);
> + *		if (IS_ERR(vm_bo))
> + *			return PTR_ERR(vm_bo);
> + *
>    *		drm_gpuva_for_each_op(op, ops) {
>    *			struct drm_gpuva *va;
>    *
> @@ -458,7 +482,7 @@
>    *
>    *				driver_vm_map();
>    *				drm_gpuva_map(gpuvm, va, &op->map);
> - *				drm_gpuva_link(va);
> + *				drm_gpuva_link(va, vm_bo);
>    *
>    *				break;
>    *			case DRM_GPUVA_OP_REMAP: {
> @@ -485,11 +509,11 @@
>    *				driver_vm_remap();
>    *				drm_gpuva_remap(prev, next, &op->remap);
>    *
> - *				drm_gpuva_unlink(va);
>    *				if (prev)
> - *					drm_gpuva_link(prev);
> + *					drm_gpuva_link(prev, va->vm_bo);
>    *				if (next)
> - *					drm_gpuva_link(next);
> + *					drm_gpuva_link(next, va->vm_bo);
> + *				drm_gpuva_unlink(va);
>    *
>    *				break;
>    *			}
> @@ -505,6 +529,7 @@
>    *				break;
>    *			}
>    *		}
> + *		drm_gpuvm_bo_put(vm_bo);
>    *		driver_unlock_va_space();
>    *
>    *		return 0;
> @@ -514,6 +539,7 @@
>    *
>    *	struct driver_context {
>    *		struct drm_gpuvm *gpuvm;
> + *		struct drm_gpuvm_bo *vm_bo;
>    *		struct drm_gpuva *new_va;
>    *		struct drm_gpuva *prev_va;
>    *		struct drm_gpuva *next_va;
> @@ -534,6 +560,7 @@
>    *				  struct drm_gem_object *obj, u64 offset)
>    *	{
>    *		struct driver_context ctx;
> + *		struct drm_gpuvm_bo *vm_bo;
>    *		struct drm_gpuva_ops *ops;
>    *		struct drm_gpuva_op *op;
>    *		int ret = 0;
> @@ -543,16 +570,23 @@
>    *		ctx.new_va = kzalloc(sizeof(*ctx.new_va), GFP_KERNEL);
>    *		ctx.prev_va = kzalloc(sizeof(*ctx.prev_va), GFP_KERNEL);
>    *		ctx.next_va = kzalloc(sizeof(*ctx.next_va), GFP_KERNEL);
> - *		if (!ctx.new_va || !ctx.prev_va || !ctx.next_va) {
> + *		ctx.vm_bo = drm_gpuvm_bo_create(gpuvm, obj);
> + *		if (!ctx.new_va || !ctx.prev_va || !ctx.next_va || !vm_bo) {
>    *			ret = -ENOMEM;
>    *			goto out;
>    *		}
>    *
> + *		// Typically protected with a driver specific GEM gpuva lock
> + *		// used in the fence signaling path for drm_gpuva_link() and
> + *		// drm_gpuva_unlink(), hence pre-allocate.
> + *		ctx.vm_bo = drm_gpuvm_bo_obtain_prealloc(ctx.vm_bo);
> + *
>    *		driver_lock_va_space();
>    *		ret = drm_gpuvm_sm_map(gpuvm, &ctx, addr, range, obj, offset);
>    *		driver_unlock_va_space();
>    *
>    *	out:
> + *		drm_gpuvm_bo_put(ctx.vm_bo);
>    *		kfree(ctx.new_va);
>    *		kfree(ctx.prev_va);
>    *		kfree(ctx.next_va);
> @@ -565,7 +599,7 @@
>    *
>    *		drm_gpuva_map(ctx->vm, ctx->new_va, &op->map);
>    *
> - *		drm_gpuva_link(ctx->new_va);
> + *		drm_gpuva_link(ctx->new_va, ctx->vm_bo);
>    *
>    *		// prevent the new GPUVA from being freed in
>    *		// driver_mapping_create()
> @@ -577,22 +611,23 @@
>    *	int driver_gpuva_remap(struct drm_gpuva_op *op, void *__ctx)
>    *	{
>    *		struct driver_context *ctx = __ctx;
> + *		struct drm_gpuva *va = op->remap.unmap->va;
>    *
>    *		drm_gpuva_remap(ctx->prev_va, ctx->next_va, &op->remap);
>    *
> - *		drm_gpuva_unlink(op->remap.unmap->va);
> - *		kfree(op->remap.unmap->va);
> - *
>    *		if (op->remap.prev) {
> - *			drm_gpuva_link(ctx->prev_va);
> + *			drm_gpuva_link(ctx->prev_va, va->vm_bo);
>    *			ctx->prev_va = NULL;
>    *		}
>    *
>    *		if (op->remap.next) {
> - *			drm_gpuva_link(ctx->next_va);
> + *			drm_gpuva_link(ctx->next_va, va->vm_bo);
>    *			ctx->next_va = NULL;
>    *		}
>    *
> + *		drm_gpuva_unlink(va);
> + *		kfree(va);
> + *
>    *		return 0;
>    *	}
>    *
> @@ -771,6 +806,194 @@ drm_gpuvm_destroy(struct drm_gpuvm *gpuvm)
>   }
>   EXPORT_SYMBOL_GPL(drm_gpuvm_destroy);
>   
> +/**
> + * drm_gpuvm_bo_create() - create a new instance of struct drm_gpuvm_bo
> + * @gpuvm: The &drm_gpuvm the @obj is mapped in.
> + * @obj: The &drm_gem_object being mapped in the @gpuvm.
> + *
> + * If provided by the driver, this function uses the &drm_gpuvm_ops
> + * vm_bo_alloc() callback to allocate.
> + *
> + * Returns: a pointer to the &drm_gpuvm_bo on success, NULL on failure
> + */
> +struct drm_gpuvm_bo *
> +drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
> +		    struct drm_gem_object *obj)
> +{
> +	const struct drm_gpuvm_ops *ops = gpuvm->ops;
> +	struct drm_gpuvm_bo *vm_bo;
> +
> +	if (ops && ops->vm_bo_alloc)
> +		vm_bo = ops->vm_bo_alloc();
> +	else
> +		vm_bo = kzalloc(sizeof(*vm_bo), GFP_KERNEL);
> +
> +	if (unlikely(!vm_bo))
> +		return NULL;
> +
> +	vm_bo->vm = gpuvm;
> +	vm_bo->obj = obj;
> +
> +	kref_init(&vm_bo->kref);
> +	INIT_LIST_HEAD(&vm_bo->list.gpuva);
> +	INIT_LIST_HEAD(&vm_bo->list.entry.gem);
> +
> +	drm_gem_object_get(obj);
> +
> +	return vm_bo;
> +}
> +EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create);
> +
> +static void
> +drm_gpuvm_bo_destroy(struct kref *kref)
> +{
> +	struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
> +						  kref);
> +	struct drm_gpuvm *gpuvm = vm_bo->vm;
> +	const struct drm_gpuvm_ops *ops = gpuvm->ops;
> +	struct drm_gem_object *obj = vm_bo->obj;
> +	bool lock = !drm_gpuvm_resv_protected(gpuvm);
> +
> +	drm_gem_gpuva_assert_lock_held(obj);
> +	if (!lock)
> +		drm_gpuvm_resv_assert_held(gpuvm);
> +
> +	list_del(&vm_bo->list.entry.gem);
> +
> +	drm_gem_object_put(obj);
> +
> +	if (ops && ops->vm_bo_free)
> +		ops->vm_bo_free(vm_bo);
> +	else
> +		kfree(vm_bo);
> +}
> +
> +/**
> + * drm_gpuvm_bo_put() - drop a struct drm_gpuvm_bo reference
> + * @vm_bo: the &drm_gpuvm_bo to release the reference of
> + *
> + * This releases a reference to @vm_bo.
> + *
> + * If the reference count drops to zero, the &gpuvm_bo is destroyed, which
> + * includes removing it from the GEMs gpuva list. Hence, if a call to this
> + * function can potentially let the reference count to zero the caller must
> + * hold the dma-resv or driver specific GEM gpuva lock.
> + */
> +void
> +drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
> +{
> +	if (vm_bo)
> +		kref_put(&vm_bo->kref, drm_gpuvm_bo_destroy);
> +}
> +EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put);
> +
> +static struct drm_gpuvm_bo *
> +__drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
> +		    struct drm_gem_object *obj)
> +{
> +	struct drm_gpuvm_bo *vm_bo;
> +
> +	drm_gem_gpuva_assert_lock_held(obj);
> +
> +	drm_gem_for_each_gpuvm_bo(vm_bo, obj)
> +		if (vm_bo->vm == gpuvm)
> +			return vm_bo;
> +
> +	return NULL;
> +}
> +
> +/**
> + * drm_gpuvm_bo_find() - find the &drm_gpuvm_bo for the given
> + * &drm_gpuvm and &drm_gem_object
> + * @gpuvm: The &drm_gpuvm the @obj is mapped in.
> + * @obj: The &drm_gem_object being mapped in the @gpuvm.
> + *
> + * Find the &drm_gpuvm_bo representing the combination of the given
> + * &drm_gpuvm and &drm_gem_object. If found, increases the reference
> + * count of the &drm_gpuvm_bo accordingly.
> + *
> + * Returns: a pointer to the &drm_gpuvm_bo on success, NULL on failure
> + */
> +struct drm_gpuvm_bo *
> +drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
> +		  struct drm_gem_object *obj)
> +{
> +	struct drm_gpuvm_bo *vm_bo = __drm_gpuvm_bo_find(gpuvm, obj);
> +
> +	return vm_bo ? drm_gpuvm_bo_get(vm_bo) : NULL;
> +}
> +EXPORT_SYMBOL_GPL(drm_gpuvm_bo_find);
> +
> +/**
> + * drm_gpuvm_bo_obtain() - obtains and instance of the &drm_gpuvm_bo for the
> + * given &drm_gpuvm and &drm_gem_object
> + * @gpuvm: The &drm_gpuvm the @obj is mapped in.
> + * @obj: The &drm_gem_object being mapped in the @gpuvm.
> + *
> + * Find the &drm_gpuvm_bo representing the combination of the given
> + * &drm_gpuvm and &drm_gem_object. If found, increases the reference
> + * count of the &drm_gpuvm_bo accordingly. If not found, allocates a new
> + * &drm_gpuvm_bo.
> + *
> + * A new &drm_gpuvm_bo is added to the GEMs gpuva list.
> + *
> + * Returns: a pointer to the &drm_gpuvm_bo on success, an ERR_PTR on failure
> + */
> +struct drm_gpuvm_bo *
> +drm_gpuvm_bo_obtain(struct drm_gpuvm *gpuvm,
> +		    struct drm_gem_object *obj)
> +{
> +	struct drm_gpuvm_bo *vm_bo;
> +
> +	vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
> +	if (vm_bo)
> +		return vm_bo;
> +
> +	vm_bo = drm_gpuvm_bo_create(gpuvm, obj);
> +	if (!vm_bo)
> +		return ERR_PTR(-ENOMEM);
> +
> +	list_add_tail(&vm_bo->list.entry.gem, &obj->gpuva.list);
> +
> +	return vm_bo;
> +}
> +EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain);
> +
> +/**
> + * drm_gpuvm_bo_obtain_prealloc() - obtains and instance of the &drm_gpuvm_bo
> + * for the given &drm_gpuvm and &drm_gem_object
> + * @__vm_bo: A pre-allocated struct drm_gpuvm_bo.
> + *
> + * Find the &drm_gpuvm_bo representing the combination of the given
> + * &drm_gpuvm and &drm_gem_object. If found, increases the reference
> + * count of the found &drm_gpuvm_bo accordingly, while the @__vm_bo reference
> + * count is decreased. If not found @__vm_bo is returned without further
> + * increase of the reference count.
> + *
> + * A new &drm_gpuvm_bo is added to the GEMs gpuva list.
> + *
> + * Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing
> + * &drm_gpuvm_bo was found
> + */
> +struct drm_gpuvm_bo *
> +drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo)
> +{
> +	struct drm_gpuvm *gpuvm = __vm_bo->vm;
> +	struct drm_gem_object *obj = __vm_bo->obj;
> +	struct drm_gpuvm_bo *vm_bo;
> +
> +	vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
> +	if (vm_bo) {
> +		drm_gpuvm_bo_put(__vm_bo);
> +		return vm_bo;
> +	}
> +
> +	list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list);
> +
> +	return __vm_bo;
> +}
> +EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain_prealloc);
> +
>   static int
>   __drm_gpuva_insert(struct drm_gpuvm *gpuvm,
>   		   struct drm_gpuva *va)
> @@ -860,24 +1083,33 @@ EXPORT_SYMBOL_GPL(drm_gpuva_remove);
>   /**
>    * drm_gpuva_link() - link a &drm_gpuva
>    * @va: the &drm_gpuva to link
> + * @vm_bo: the &drm_gpuvm_bo to add the &drm_gpuva to
>    *
> - * This adds the given &va to the GPU VA list of the &drm_gem_object it is
> - * associated with.
> + * This adds the given &va to the GPU VA list of the &drm_gpuvm_bo and the
> + * &drm_gpuvm_bo to the &drm_gem_object it is associated with.
> + *
> + * For every &drm_gpuva entry added to the &drm_gpuvm_bo an additional
> + * reference of the latter is taken.
>    *
>    * This function expects the caller to protect the GEM's GPUVA list against
> - * concurrent access using the GEMs dma_resv lock.
> + * concurrent access using either the GEMs dma_resv lock or a driver specific
> + * lock set through drm_gem_gpuva_set_lock().
>    */
>   void
> -drm_gpuva_link(struct drm_gpuva *va)
> +drm_gpuva_link(struct drm_gpuva *va, struct drm_gpuvm_bo *vm_bo)
>   {
>   	struct drm_gem_object *obj = va->gem.obj;
>   
>   	if (unlikely(!obj))
>   		return;
>   
> +	WARN_ON(obj != vm_bo->obj);
>   	drm_gem_gpuva_assert_lock_held(obj);
>   
> -	list_add_tail(&va->gem.entry, &obj->gpuva.list);
> +	drm_gpuvm_bo_get(vm_bo);
> +
> +	va->vm_bo = vm_bo;
> +	list_add_tail(&va->gem.entry, &vm_bo->list.gpuva);
>   }
>   EXPORT_SYMBOL_GPL(drm_gpuva_link);
>   
> @@ -888,13 +1120,22 @@ EXPORT_SYMBOL_GPL(drm_gpuva_link);
>    * This removes the given &va from the GPU VA list of the &drm_gem_object it is
>    * associated with.
>    *
> + * This removes the given &va from the GPU VA list of the &drm_gpuvm_bo and
> + * the &drm_gpuvm_bo from the &drm_gem_object it is associated with in case
> + * this call unlinks the last &drm_gpuva from the &drm_gpuvm_bo.
> + *
> + * For every &drm_gpuva entry removed from the &drm_gpuvm_bo a reference of
> + * the latter is dropped.
> + *
>    * This function expects the caller to protect the GEM's GPUVA list against
> - * concurrent access using the GEMs dma_resv lock.
> + * concurrent access using either the GEMs dma_resv lock or a driver specific
> + * lock set through drm_gem_gpuva_set_lock().
>    */
>   void
>   drm_gpuva_unlink(struct drm_gpuva *va)
>   {
>   	struct drm_gem_object *obj = va->gem.obj;
Can we ditch va->gem.obj now and replace it with an accessor to the  
vm_bo's pointer?
> +	struct drm_gpuvm_bo *vm_bo = va->vm_bo;
>   
>   	if (unlikely(!obj))
>   		return;
> @@ -902,6 +1143,11 @@ drm_gpuva_unlink(struct drm_gpuva *va)
>   	drm_gem_gpuva_assert_lock_held(obj);
>   
>   	list_del_init(&va->gem.entry);
> +	va->vm_bo = NULL;
> +
> +	drm_gem_object_get(obj);
> +	drm_gpuvm_bo_put(vm_bo);
> +	drm_gem_object_put(obj);

This get->put dance is unneccesary? If the caller is required to hold a 
lock on obj it is also required to hold a reference on obj.

Besides, if the vm_bo's reference on obj is otherwise the last one, it 
will still be freed before the function exits.

/Thomas



  parent reply	other threads:[~2023-10-05 15:49 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-28 19:16 [PATCH drm-misc-next v5 0/6] [RFC] DRM GPUVM features Danilo Krummrich
2023-09-28 19:16 ` [PATCH drm-misc-next v5 1/6] drm/gpuvm: add common dma-resv per struct drm_gpuvm Danilo Krummrich
2023-09-28 19:16 ` [PATCH drm-misc-next v5 2/6] drm/gpuvm: add drm_gpuvm_flags to drm_gpuvm Danilo Krummrich
2023-09-28 19:16 ` [PATCH drm-misc-next v5 3/6] drm/gpuvm: add an abstraction for a VM / BO combination Danilo Krummrich
2023-10-02  6:34   ` kernel test robot
2023-10-05 11:51   ` Thomas Hellström [this message]
2023-10-08 23:08     ` Danilo Krummrich
2023-09-28 19:16 ` [PATCH drm-misc-next v5 4/6] drm/gpuvm: track/lock/validate external/evicted objects Danilo Krummrich
2023-10-02 15:40   ` kernel test robot
2023-10-03  8:36   ` Thomas Hellström
2023-10-03  9:11     ` Thomas Hellström
2023-10-04 12:57       ` Danilo Krummrich
2023-10-04 15:29         ` Thomas Hellström
2023-10-04 17:17           ` Danilo Krummrich
2023-10-04 17:57             ` Thomas Hellström
2023-10-04 18:24               ` Danilo Krummrich
2023-10-03 10:05     ` Boris Brezillon
2023-10-03 12:25       ` Thomas Hellström
2023-10-03 14:21         ` Boris Brezillon
2023-10-03 16:55           ` Danilo Krummrich
2023-10-03 17:37             ` Thomas Hellström
2023-10-04 13:35               ` Danilo Krummrich
2023-10-03 18:57             ` Thomas Hellström
2023-10-05 11:55   ` Thomas Hellström
2023-09-28 19:16 ` [PATCH drm-misc-next v5 5/6] drm/nouveau: make use of the GPUVM's shared dma-resv Danilo Krummrich
2023-09-28 19:16 ` [PATCH drm-misc-next v5 6/6] drm/nouveau: use GPUVM common infrastructure Danilo Krummrich
2023-10-05  9:35 ` [PATCH drm-misc-next v5 0/6] [RFC] DRM GPUVM features Thomas Hellström
2023-10-08 22:48   ` Danilo Krummrich

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=28528b64-e760-d9a8-c56d-e44672cb02fb@linux.intel.com \
    --to=thomas.hellstrom@linux.intel.com \
    --cc=airlied@gmail.com \
    --cc=boris.brezillon@collabora.com \
    --cc=christian.koenig@amd.com \
    --cc=dakr@redhat.com \
    --cc=daniel@ffwll.ch \
    --cc=donald.robson@imgtec.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=faith@gfxstrand.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matthew.brost@intel.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=sarah.walker@imgtec.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox