linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] dma-buf: make returning the exclusive fence optional
@ 2018-01-12  9:47 Christian König
  2018-01-12  9:47 ` [PATCH 2/3] drm/amdgpu: add amdgpu_pasid_free_delayed v2 Christian König
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Christian König @ 2018-01-12  9:47 UTC (permalink / raw)
  To: daniel, sumit.semwal, gustavo, linux-media, dri-devel, linaro-mm-sig

Change reservation_object_get_fences_rcu to make the exclusive fence
pointer optional.

If not specified the exclusive fence is put into the fence array as
well.

This is helpful for a couple of cases where we need all fences in a
single array.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/reservation.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index b759a569b7b8..461afa9febd4 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -374,8 +374,9 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
  * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
  * the required size, and must be freed by caller)
  *
- * RETURNS
- * Zero or -errno
+ * Retrieve all fences from the reservation object. If the pointer for the
+ * exclusive fence is not specified the fence is put into the array of the
+ * shared fences as well. Returns either zero or -ENOMEM.
  */
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
 				      struct dma_fence **pfence_excl,
@@ -389,8 +390,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 
 	do {
 		struct reservation_object_list *fobj;
-		unsigned seq;
-		unsigned int i;
+		unsigned int i, seq;
+		size_t sz = 0;
 
 		shared_count = i = 0;
 
@@ -402,9 +403,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 			goto unlock;
 
 		fobj = rcu_dereference(obj->fence);
-		if (fobj) {
+		if (fobj)
+			sz += sizeof(*shared) * fobj->shared_max;
+
+		if (!pfence_excl && fence_excl)
+			sz += sizeof(*shared);
+
+		if (sz) {
 			struct dma_fence **nshared;
-			size_t sz = sizeof(*shared) * fobj->shared_max;
 
 			nshared = krealloc(shared, sz,
 					   GFP_NOWAIT | __GFP_NOWARN);
@@ -420,13 +426,19 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 				break;
 			}
 			shared = nshared;
-			shared_count = fobj->shared_count;
-
+			shared_count = fobj ? fobj->shared_count : 0;
 			for (i = 0; i < shared_count; ++i) {
 				shared[i] = rcu_dereference(fobj->shared[i]);
 				if (!dma_fence_get_rcu(shared[i]))
 					break;
 			}
+
+			if (!pfence_excl && fence_excl) {
+				shared[i] = fence_excl;
+				fence_excl = NULL;
+				++i;
+				++shared_count;
+			}
 		}
 
 		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
@@ -448,7 +460,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 
 	*pshared_count = shared_count;
 	*pshared = shared;
-	*pfence_excl = fence_excl;
+	if (pfence_excl)
+		*pfence_excl = fence_excl;
 
 	return ret;
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] drm/amdgpu: add amdgpu_pasid_free_delayed v2
  2018-01-12  9:47 [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
@ 2018-01-12  9:47 ` Christian König
  2018-01-12  9:47 ` [PATCH 3/3] drm/amdgpu: always allocate a PASIDs for each VM v2 Christian König
  2018-01-16 10:14 ` [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
  2 siblings, 0 replies; 5+ messages in thread
From: Christian König @ 2018-01-12  9:47 UTC (permalink / raw)
  To: daniel, sumit.semwal, gustavo, linux-media, dri-devel, linaro-mm-sig

Free up a pasid after all fences signaled.

v2: also handle the case when we can't allocate a fence array.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 82 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h |  2 +
 2 files changed, 84 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 5248a3232aff..842caa5ed73b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -40,6 +40,12 @@
  */
 static DEFINE_IDA(amdgpu_pasid_ida);
 
+/* Helper to free pasid from a fence callback */
+struct amdgpu_pasid_cb {
+	struct dma_fence_cb cb;
+	unsigned int pasid;
+};
+
 /**
  * amdgpu_pasid_alloc - Allocate a PASID
  * @bits: Maximum width of the PASID in bits, must be at least 1
@@ -75,6 +81,82 @@ void amdgpu_pasid_free(unsigned int pasid)
 	ida_simple_remove(&amdgpu_pasid_ida, pasid);
 }
 
+static void amdgpu_pasid_free_cb(struct dma_fence *fence,
+				 struct dma_fence_cb *_cb)
+{
+	struct amdgpu_pasid_cb *cb =
+		container_of(_cb, struct amdgpu_pasid_cb, cb);
+
+	amdgpu_pasid_free(cb->pasid);
+	dma_fence_put(fence);
+	kfree(cb);
+}
+
+/**
+ * amdgpu_pasid_free_delayed - free pasid when fences signal
+ *
+ * @resv: reservation object with the fences to wait for
+ * @pasid: pasid to free
+ *
+ * Free the pasid only after all the fences in resv are signaled.
+ */
+void amdgpu_pasid_free_delayed(struct reservation_object *resv,
+			       unsigned int pasid)
+{
+	struct dma_fence *fence, **fences;
+	struct amdgpu_pasid_cb *cb;
+	unsigned count;
+	int r;
+
+	r = reservation_object_get_fences_rcu(resv, NULL, &count, &fences);
+	if (r)
+		goto fallback;
+
+	if (count == 0) {
+		amdgpu_pasid_free(pasid);
+		return;
+	}
+
+	if (count == 1) {
+		fence = fences[0];
+		kfree(fences);
+	} else {
+		uint64_t context = dma_fence_context_alloc(1);
+		struct dma_fence_array *array;
+
+		array = dma_fence_array_create(count, fences, context,
+					       1, false);
+		if (!array) {
+			kfree(fences);
+			goto fallback;
+		}
+		fence = &array->base;
+	}
+
+	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
+	if (!cb) {
+		/* Last resort when we are OOM */
+		dma_fence_wait(fence, false);
+		dma_fence_put(fence);
+		amdgpu_pasid_free(pasid);
+	} else {
+		cb->pasid = pasid;
+		if (dma_fence_add_callback(fence, &cb->cb,
+					   amdgpu_pasid_free_cb))
+			amdgpu_pasid_free_cb(fence, &cb->cb);
+	}
+
+	return;
+
+fallback:
+	/* Not enough memory for the delayed delete, as last resort
+	 * block for all the fences to complete.
+	 */
+	reservation_object_wait_timeout_rcu(resv, true, false,
+					    MAX_SCHEDULE_TIMEOUT);
+	amdgpu_pasid_free(pasid);
+}
+
 /*
  * VMID manager
  *
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index ad931fa570b3..38f37c16fc5e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -69,6 +69,8 @@ struct amdgpu_vmid_mgr {
 
 int amdgpu_pasid_alloc(unsigned int bits);
 void amdgpu_pasid_free(unsigned int pasid);
+void amdgpu_pasid_free_delayed(struct reservation_object *resv,
+			       unsigned int pasid);
 
 bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
 			       struct amdgpu_vmid *id);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] drm/amdgpu: always allocate a PASIDs for each VM v2
  2018-01-12  9:47 [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
  2018-01-12  9:47 ` [PATCH 2/3] drm/amdgpu: add amdgpu_pasid_free_delayed v2 Christian König
@ 2018-01-12  9:47 ` Christian König
  2018-01-16 10:14 ` [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
  2 siblings, 0 replies; 5+ messages in thread
From: Christian König @ 2018-01-12  9:47 UTC (permalink / raw)
  To: daniel, sumit.semwal, gustavo, linux-media, dri-devel, linaro-mm-sig

Start to always allocate a pasid for each VM.

v2: use dev_warn when we run out of PASIDs

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 43 ++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 5773a581761b..a108b30d8186 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -805,7 +805,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct amdgpu_device *adev = dev->dev_private;
 	struct amdgpu_fpriv *fpriv;
-	int r;
+	int r, pasid;
 
 	file_priv->driver_priv = NULL;
 
@@ -819,28 +819,25 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 		goto out_suspend;
 	}
 
-	r = amdgpu_vm_init(adev, &fpriv->vm,
-			   AMDGPU_VM_CONTEXT_GFX, 0);
-	if (r) {
-		kfree(fpriv);
-		goto out_suspend;
+	pasid = amdgpu_pasid_alloc(16);
+	if (pasid < 0) {
+		dev_warn(adev->dev, "No more PASIDs available!");
+		pasid = 0;
 	}
+	r = amdgpu_vm_init(adev, &fpriv->vm, AMDGPU_VM_CONTEXT_GFX, pasid);
+	if (r)
+		goto error_pasid;
 
 	fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL);
 	if (!fpriv->prt_va) {
 		r = -ENOMEM;
-		amdgpu_vm_fini(adev, &fpriv->vm);
-		kfree(fpriv);
-		goto out_suspend;
+		goto error_vm;
 	}
 
 	if (amdgpu_sriov_vf(adev)) {
 		r = amdgpu_map_static_csa(adev, &fpriv->vm, &fpriv->csa_va);
-		if (r) {
-			amdgpu_vm_fini(adev, &fpriv->vm);
-			kfree(fpriv);
-			goto out_suspend;
-		}
+		if (r)
+			goto error_vm;
 	}
 
 	mutex_init(&fpriv->bo_list_lock);
@@ -849,6 +846,16 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 	amdgpu_ctx_mgr_init(&fpriv->ctx_mgr);
 
 	file_priv->driver_priv = fpriv;
+	goto out_suspend;
+
+error_vm:
+	amdgpu_vm_fini(adev, &fpriv->vm);
+
+error_pasid:
+	if (pasid)
+		amdgpu_pasid_free(pasid);
+
+	kfree(fpriv);
 
 out_suspend:
 	pm_runtime_mark_last_busy(dev->dev);
@@ -871,6 +878,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
 	struct amdgpu_device *adev = dev->dev_private;
 	struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
 	struct amdgpu_bo_list *list;
+	struct amdgpu_bo *pd;
+	unsigned int pasid;
 	int handle;
 
 	if (!fpriv)
@@ -895,7 +904,13 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
 		amdgpu_bo_unreserve(adev->virt.csa_obj);
 	}
 
+	pasid = fpriv->vm.pasid;
+	pd = amdgpu_bo_ref(fpriv->vm.root.base.bo);
+
 	amdgpu_vm_fini(adev, &fpriv->vm);
+	if (pasid)
+		amdgpu_pasid_free_delayed(pd->tbo.resv, pasid);
+	amdgpu_bo_unref(&pd);
 
 	idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
 		amdgpu_bo_list_free(list);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/3] dma-buf: make returning the exclusive fence optional
  2018-01-12  9:47 [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
  2018-01-12  9:47 ` [PATCH 2/3] drm/amdgpu: add amdgpu_pasid_free_delayed v2 Christian König
  2018-01-12  9:47 ` [PATCH 3/3] drm/amdgpu: always allocate a PASIDs for each VM v2 Christian König
@ 2018-01-16 10:14 ` Christian König
  2018-01-17  8:02   ` Daniel Vetter
  2 siblings, 1 reply; 5+ messages in thread
From: Christian König @ 2018-01-16 10:14 UTC (permalink / raw)
  To: daniel, sumit.semwal, gustavo, linux-media, dri-devel, linaro-mm-sig

Ping? Daniel you requested the patch with its user.

Would be nice when I can commit this cause we need it for debugging and 
cleaning up a bunch of other things as well.

Regards,
Christian.

Am 12.01.2018 um 10:47 schrieb Christian König:
> Change reservation_object_get_fences_rcu to make the exclusive fence
> pointer optional.
>
> If not specified the exclusive fence is put into the fence array as
> well.
>
> This is helpful for a couple of cases where we need all fences in a
> single array.
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>   drivers/dma-buf/reservation.c | 31 ++++++++++++++++++++++---------
>   1 file changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
> index b759a569b7b8..461afa9febd4 100644
> --- a/drivers/dma-buf/reservation.c
> +++ b/drivers/dma-buf/reservation.c
> @@ -374,8 +374,9 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
>    * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
>    * the required size, and must be freed by caller)
>    *
> - * RETURNS
> - * Zero or -errno
> + * Retrieve all fences from the reservation object. If the pointer for the
> + * exclusive fence is not specified the fence is put into the array of the
> + * shared fences as well. Returns either zero or -ENOMEM.
>    */
>   int reservation_object_get_fences_rcu(struct reservation_object *obj,
>   				      struct dma_fence **pfence_excl,
> @@ -389,8 +390,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
>   
>   	do {
>   		struct reservation_object_list *fobj;
> -		unsigned seq;
> -		unsigned int i;
> +		unsigned int i, seq;
> +		size_t sz = 0;
>   
>   		shared_count = i = 0;
>   
> @@ -402,9 +403,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
>   			goto unlock;
>   
>   		fobj = rcu_dereference(obj->fence);
> -		if (fobj) {
> +		if (fobj)
> +			sz += sizeof(*shared) * fobj->shared_max;
> +
> +		if (!pfence_excl && fence_excl)
> +			sz += sizeof(*shared);
> +
> +		if (sz) {
>   			struct dma_fence **nshared;
> -			size_t sz = sizeof(*shared) * fobj->shared_max;
>   
>   			nshared = krealloc(shared, sz,
>   					   GFP_NOWAIT | __GFP_NOWARN);
> @@ -420,13 +426,19 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
>   				break;
>   			}
>   			shared = nshared;
> -			shared_count = fobj->shared_count;
> -
> +			shared_count = fobj ? fobj->shared_count : 0;
>   			for (i = 0; i < shared_count; ++i) {
>   				shared[i] = rcu_dereference(fobj->shared[i]);
>   				if (!dma_fence_get_rcu(shared[i]))
>   					break;
>   			}
> +
> +			if (!pfence_excl && fence_excl) {
> +				shared[i] = fence_excl;
> +				fence_excl = NULL;
> +				++i;
> +				++shared_count;
> +			}
>   		}
>   
>   		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
> @@ -448,7 +460,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
>   
>   	*pshared_count = shared_count;
>   	*pshared = shared;
> -	*pfence_excl = fence_excl;
> +	if (pfence_excl)
> +		*pfence_excl = fence_excl;
>   
>   	return ret;
>   }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/3] dma-buf: make returning the exclusive fence optional
  2018-01-16 10:14 ` [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
@ 2018-01-17  8:02   ` Daniel Vetter
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Vetter @ 2018-01-17  8:02 UTC (permalink / raw)
  To: Christian König
  Cc: daniel, sumit.semwal, gustavo, linux-media, dri-devel, linaro-mm-sig

On Tue, Jan 16, 2018 at 11:14:26AM +0100, Christian König wrote:
> Ping? Daniel you requested the patch with its user.

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

but might be good to get a review from one of the usual reservation stuff
folks.
-Daniel

> 
> Would be nice when I can commit this cause we need it for debugging and
> cleaning up a bunch of other things as well.
> 
> Regards,
> Christian.
> 
> Am 12.01.2018 um 10:47 schrieb Christian König:
> > Change reservation_object_get_fences_rcu to make the exclusive fence
> > pointer optional.
> > 
> > If not specified the exclusive fence is put into the fence array as
> > well.
> > 
> > This is helpful for a couple of cases where we need all fences in a
> > single array.
> > 
> > Signed-off-by: Christian König <christian.koenig@amd.com>
> > ---
> >   drivers/dma-buf/reservation.c | 31 ++++++++++++++++++++++---------
> >   1 file changed, 22 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
> > index b759a569b7b8..461afa9febd4 100644
> > --- a/drivers/dma-buf/reservation.c
> > +++ b/drivers/dma-buf/reservation.c
> > @@ -374,8 +374,9 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
> >    * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
> >    * the required size, and must be freed by caller)
> >    *
> > - * RETURNS
> > - * Zero or -errno
> > + * Retrieve all fences from the reservation object. If the pointer for the
> > + * exclusive fence is not specified the fence is put into the array of the
> > + * shared fences as well. Returns either zero or -ENOMEM.
> >    */
> >   int reservation_object_get_fences_rcu(struct reservation_object *obj,
> >   				      struct dma_fence **pfence_excl,
> > @@ -389,8 +390,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
> >   	do {
> >   		struct reservation_object_list *fobj;
> > -		unsigned seq;
> > -		unsigned int i;
> > +		unsigned int i, seq;
> > +		size_t sz = 0;
> >   		shared_count = i = 0;
> > @@ -402,9 +403,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
> >   			goto unlock;
> >   		fobj = rcu_dereference(obj->fence);
> > -		if (fobj) {
> > +		if (fobj)
> > +			sz += sizeof(*shared) * fobj->shared_max;
> > +
> > +		if (!pfence_excl && fence_excl)
> > +			sz += sizeof(*shared);
> > +
> > +		if (sz) {
> >   			struct dma_fence **nshared;
> > -			size_t sz = sizeof(*shared) * fobj->shared_max;
> >   			nshared = krealloc(shared, sz,
> >   					   GFP_NOWAIT | __GFP_NOWARN);
> > @@ -420,13 +426,19 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
> >   				break;
> >   			}
> >   			shared = nshared;
> > -			shared_count = fobj->shared_count;
> > -
> > +			shared_count = fobj ? fobj->shared_count : 0;
> >   			for (i = 0; i < shared_count; ++i) {
> >   				shared[i] = rcu_dereference(fobj->shared[i]);
> >   				if (!dma_fence_get_rcu(shared[i]))
> >   					break;
> >   			}
> > +
> > +			if (!pfence_excl && fence_excl) {
> > +				shared[i] = fence_excl;
> > +				fence_excl = NULL;
> > +				++i;
> > +				++shared_count;
> > +			}
> >   		}
> >   		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
> > @@ -448,7 +460,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
> >   	*pshared_count = shared_count;
> >   	*pshared = shared;
> > -	*pfence_excl = fence_excl;
> > +	if (pfence_excl)
> > +		*pfence_excl = fence_excl;
> >   	return ret;
> >   }
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-01-17  8:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-12  9:47 [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
2018-01-12  9:47 ` [PATCH 2/3] drm/amdgpu: add amdgpu_pasid_free_delayed v2 Christian König
2018-01-12  9:47 ` [PATCH 3/3] drm/amdgpu: always allocate a PASIDs for each VM v2 Christian König
2018-01-16 10:14 ` [PATCH 1/3] dma-buf: make returning the exclusive fence optional Christian König
2018-01-17  8:02   ` Daniel Vetter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).