[PATCH 5/8] active-ref
Chris Wilson
chris at chris-wilson.co.uk
Fri Mar 13 00:47:44 UTC 2020
---
drivers/gpu/drm/i915/i915_active.c | 57 ++++++++++++++++++++++++++----
drivers/gpu/drm/i915/i915_active.h | 3 ++
2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index c4048628188a..3db88e3af0a1 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -217,11 +217,10 @@ excl_retire(struct dma_fence *fence, struct dma_fence_cb *cb)
}
static struct i915_active_fence *
-active_instance(struct i915_active *ref, struct intel_timeline *tl)
+active_instance(struct i915_active *ref, u64 idx)
{
struct active_node *node, *prealloc;
struct rb_node **p, *parent;
- u64 idx = tl->fence_context;
/*
* We track the most recently used timeline to skip a rbtree search
@@ -367,7 +366,7 @@ int i915_active_ref(struct i915_active *ref,
if (err)
return err;
- active = active_instance(ref, tl);
+ active = active_instance(ref, tl->fence_context);
if (!active) {
err = -ENOMEM;
goto out;
@@ -391,8 +390,10 @@ int i915_active_ref(struct i915_active *ref,
return err;
}
-struct dma_fence *
-i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f)
+static struct dma_fence *
+__i915_active_set_fence(struct i915_active *ref,
+ struct i915_active_fence *active,
+ struct dma_fence *fence)
{
struct dma_fence *prev;
@@ -400,16 +401,58 @@ i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f)
GEM_BUG_ON(i915_active_is_idle(ref));
rcu_read_lock();
- prev = __i915_active_fence_set(&ref->excl, f);
+ prev = __i915_active_fence_set(active, fence);
if (prev)
prev = dma_fence_get_rcu(prev);
else
- atomic_inc(&ref->count);
+ __i915_active_acquire(ref);
rcu_read_unlock();
return prev;
}
+struct dma_fence *
+__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence)
+{
+ struct i915_active_fence *active;
+ struct dma_fence *prev;
+ int err;
+
+ /* Prevent reaping in case we malloc/wait while building the tree */
+ err = i915_active_acquire(ref);
+ if (err)
+ return ERR_PTR(err);
+
+ active = active_instance(ref, idx);
+ if (!active) {
+ i915_active_release(ref);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (is_barrier(active)) { /* proto-node used by our idle barrier */
+ /*
+ * This request is on the kernel_context timeline, and so
+ * we can use it to substitute for the pending idle-barrer
+ * request that we want to emit on the kernel_context.
+ */
+ __active_del_barrier(ref, node_from_active(active));
+ RCU_INIT_POINTER(active->fence, NULL);
+ atomic_dec(&ref->count);
+ }
+
+ prev = __i915_active_set_fence(ref, active, fence);
+
+ i915_active_release(ref);
+ return prev;
+}
+
+struct dma_fence *
+i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f)
+{
+ /* We expect the caller to manage the exclusive timeline ordering */
+ return __i915_active_set_fence(ref, &ref->excl, f);
+}
+
bool i915_active_acquire_if_busy(struct i915_active *ref)
{
debug_active_assert(ref);
diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h
index b3282ae7913c..a5b1ce3d114f 100644
--- a/drivers/gpu/drm/i915/i915_active.h
+++ b/drivers/gpu/drm/i915/i915_active.h
@@ -163,6 +163,9 @@ void __i915_active_init(struct i915_active *ref,
__i915_active_init(ref, active, retire, &__mkey, &__wkey); \
} while (0)
+struct dma_fence *
+__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence);
+
int i915_active_ref(struct i915_active *ref,
struct intel_timeline *tl,
struct dma_fence *fence);
--
2.20.1
More information about the Intel-gfx-trybot
mailing list