[RFC 07/10] drm/i915: Track latest request per engine class

Tvrtko Ursulin
2018-01-25T13:33:49Z

We add a per-context, per-engine-class timeline so we are later able to
implement a virtual engine by creating implicit dependencies between
requests submitted to the same engine class.

v2: Rebase.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 6 ++++++
drivers/gpu/drm/i915/i915_gem_request.c | 13 +++++++++++++
drivers/gpu/drm/i915/i915_gem_request.h | 2 ++
drivers/gpu/drm/i915/i915_gem_timeline.c | 12 ++++++++++++
drivers/gpu/drm/i915/i915_gem_timeline.h | 2 ++
5 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0c348f6ab386..d20c6c542c2d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3449,6 +3449,12 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
return ctx;
}

+static inline struct intel_timeline *
+i915_gem_context_lookup_timeline_class(struct i915_gem_context *ctx, u8 class)
+{
+ return &ctx->timeline->class[class];
+}
+
int i915_perf_open_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 160d81bf6d85..85da7f7eee03 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -380,6 +380,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *engine = request->engine;
struct i915_gem_active *active, *next;
+ struct intel_timeline *timeline;

lockdep_assert_held(&request->i915->drm.struct_mutex);
GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit));
@@ -392,6 +393,12 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
list_del_init(&request->link);
spin_unlock_irq(&engine->timeline->lock);

+ timeline = i915_gem_context_lookup_timeline_class(request->ctx,
+ engine->class);
+ spin_lock_irq(&timeline->lock);
+ list_del(&request->ctx_link);
+ spin_unlock_irq(&timeline->lock);
+
unreserve_engine(request->engine);
advance_ring(request);

@@ -1054,6 +1061,12 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
GEM_BUG_ON(timeline->seqno != request->fence.seqno);
i915_gem_active_set(&timeline->last_request, request);

+ timeline = i915_gem_context_lookup_timeline_class(request->ctx,
+ engine->class);
+ spin_lock_irq(&timeline->lock);
+ list_add(&request->ctx_link, &timeline->requests);
+ spin_unlock_irq(&timeline->lock);
+
list_add_tail(&request->ring_link, &ring->request_list);
request->emitted_jiffies = jiffies;

diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 2236e9188c5c..f8915ff3d62a 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -196,6 +196,8 @@ struct drm_i915_gem_request {
/** engine->request_list entry for this request */
struct list_head link;

+ struct list_head ctx_link;
+
/** ring->request_list entry for this request */
struct list_head ring_link;

diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c
index 1bf48bdb78c4..902eb92b8883 100644
--- a/drivers/gpu/drm/i915/i915_gem_timeline.c
+++ b/drivers/gpu/drm/i915/i915_gem_timeline.c
@@ -75,6 +75,10 @@ static int __i915_gem_timeline_init(struct drm_i915_private *i915,

/* Called during early_init before we know how many engines there are */
fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine));
+ for (i = 0; i < ARRAY_SIZE(timeline->class); i++)
+ __intel_timeline_init(&timeline->class[i],
+ timeline, fences++,
+ lockclass, lockname);
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
__intel_timeline_init(&timeline->engine[i],
timeline, fences++,
@@ -137,6 +141,11 @@ void i915_gem_timelines_park(struct drm_i915_private *i915)
lockdep_assert_held(&i915->drm.struct_mutex);

list_for_each_entry(timeline, &i915->gt.timelines, link) {
+ for (i = 0; i < ARRAY_SIZE(timeline->class); i++) {
+ struct intel_timeline *tl = &timeline->class[i];
+
+ i915_syncmap_free(&tl->sync);
+ }
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) {
struct intel_timeline *tl = &timeline->engine[i];

@@ -157,6 +166,9 @@ void i915_gem_timeline_fini(struct i915_gem_timeline *timeline)

lockdep_assert_held(&timeline->i915->drm.struct_mutex);

+ for (i = 0; i < ARRAY_SIZE(timeline->class); i++)
+ __intel_timeline_fini(&timeline->class[i]);
+
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
__intel_timeline_fini(&timeline->engine[i]);

diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h
index 7ecf0a253d78..f625ef2ad14e 100644
--- a/drivers/gpu/drm/i915/i915_gem_timeline.h
+++ b/drivers/gpu/drm/i915/i915_gem_timeline.h
@@ -30,6 +30,7 @@
#include "i915_utils.h"
#include "i915_gem_request.h"
#include "i915_syncmap.h"
+#include "i915_reg.h"

struct i915_gem_timeline;

@@ -86,6 +87,7 @@ struct i915_gem_timeline {
struct drm_i915_private *i915;
const char *name;

+ struct intel_timeline class[MAX_ENGINE_CLASS];
struct intel_timeline engine[I915_NUM_ENGINES];
};