[PATCH 4/7] prune-fences
Chris Wilson
chris at chris-wilson.co.uk
Tue Jan 30 21:11:05 UTC 2018
---
drivers/dma-buf/reservation.c | 76 +++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_gem.c | 12 +++----
drivers/gpu/drm/i915/i915_vma.c | 3 +-
include/linux/reservation.h | 2 ++
4 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index de7b6e709a68..2f339b0a1a9b 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -219,6 +219,82 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
}
EXPORT_SYMBOL(reservation_object_add_excl_fence);
+int reservation_object_prune_fences(struct reservation_object *obj)
+{
+ struct reservation_object_list *old, *fobj = NULL;
+ struct dma_fence *check, *old_fence = NULL;
+ u32 uninitialized_var(discard);
+
+ old = reservation_object_get_list(obj);
+ if (old) {
+ u32 i, j;
+
+ fobj = obj->staged;
+ obj->staged = NULL;
+ if (!fobj) {
+ fobj = kmalloc(offsetof(typeof(*fobj),
+ shared[old->shared_max]),
+ GFP_KERNEL);
+ if (!fobj)
+ return -ENOMEM;
+
+ fobj->shared_max = old->shared_max;
+ }
+
+ for (i = j = 0, discard = fobj->shared_max;
+ i < old->shared_count; ++i) {
+ u32 idx;
+
+ check = rcu_dereference_protected(old->shared[i],
+ reservation_object_held(obj));
+
+ if (dma_fence_is_signaled(check))
+ idx = --discard;
+ else
+ idx = j++;
+ RCU_INIT_POINTER(fobj->shared[idx], check);
+ }
+ fobj->shared_count = j;
+
+ if (j == old->shared_count) {
+ kfree(fobj);
+ fobj = old;
+ }
+ }
+
+ check = rcu_dereference_protected(obj->fence_excl,
+ reservation_object_held(obj));
+ if (check && dma_fence_is_signaled(check)) {
+ old_fence = check;
+ check = NULL;
+ }
+
+ if (rcu_access_pointer(obj->fence_excl) == check &&
+ rcu_access_pointer(obj->fence) == fobj)
+ return 0;
+
+ write_seqcount_begin(&obj->seq);
+
+ RCU_INIT_POINTER(obj->fence_excl, check);
+ RCU_INIT_POINTER(obj->fence, fobj);
+
+ /* write_seqcount_end() provides the necessary mb for the RCU writes */
+ write_seqcount_end(&obj->seq);
+
+ dma_fence_put(old_fence);
+ if (fobj != old) {
+ for (; discard < fobj->shared_max; discard++) {
+ check = rcu_dereference_protected(fobj->shared[discard],
+ reservation_object_held(obj));
+ dma_fence_put(check);
+ }
+ kfree_rcu(old, rcu);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(reservation_object_prune_fences);
+
/**
* reservation_object_copy_fences - Copy all fences from src to dst.
* @dst: the destination reservation object
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 63308ec016a3..d7841a983c5f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -450,12 +450,12 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
* signaled and that the reservation object has not been changed (i.e.
* no new fences have been added).
*/
- if (prune_fences && !__read_seqcount_retry(&resv->seq, seq)) {
- if (reservation_object_trylock(resv)) {
- if (!__read_seqcount_retry(&resv->seq, seq))
- reservation_object_add_excl_fence(resv, NULL);
- reservation_object_unlock(resv);
- }
+ if (prune_fences && reservation_object_trylock(resv)) {
+ if (!__read_seqcount_retry(&resv->seq, seq))
+ reservation_object_add_excl_fence(resv, NULL);
+ else
+ reservation_object_prune_fences(resv);
+ reservation_object_unlock(resv);
}
return timeout;
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index e0e7c48f45dc..fafd1e1c507a 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -56,8 +56,7 @@ i915_vma_retire(struct i915_gem_active *active,
/* Prune the shared fence arrays iff completely idle (inc. external) */
if (reservation_object_trylock(obj->resv)) {
- if (reservation_object_test_signaled_rcu(obj->resv, true))
- reservation_object_add_excl_fence(obj->resv, NULL);
+ reservation_object_prune_fences(obj->resv);
reservation_object_unlock(obj->resv);
}
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 02166e815afb..940b8783e167 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -272,6 +272,8 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
void reservation_object_add_excl_fence(struct reservation_object *obj,
struct dma_fence *fence);
+int reservation_object_prune_fences(struct reservation_object *obj);
+
int reservation_object_get_fences_rcu(struct reservation_object *obj,
struct dma_fence **pfence_excl,
unsigned *pshared_count,
--
2.15.1
More information about the Intel-gfx-trybot
mailing list