* [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;
> }
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ 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: dri-devel, linaro-mm-sig, linux-media
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
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 5+ messages in thread