[PATCH 35/35] single-timeline-per-queue
Chris Wilson
chris at chris-wilson.co.uk
Thu Jan 25 17:56:23 UTC 2018
---
drivers/gpu/drm/i915/i915_gem_context.c | 26 +++++++++++++++++++++-
drivers/gpu/drm/i915/i915_gem_context.h | 3 +++
drivers/gpu/drm/i915/i915_gem_request.c | 10 +++++++--
drivers/gpu/drm/i915/i915_gem_request.h | 5 ++++-
drivers/gpu/drm/i915/i915_sw_fence.c | 39 ++++++++++++++++++++++++++++-----
drivers/gpu/drm/i915/i915_sw_fence.h | 13 +++++++++--
drivers/gpu/drm/i915/intel_lrc.c | 5 ++++-
include/uapi/drm/i915_drm.h | 3 ++-
8 files changed, 91 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index fba180062f69..7e6183b978d5 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -138,6 +138,9 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
__i915_gem_object_release_unless_active(ce->state->obj);
}
+ if (ctx->timeline)
+ i915_timeline_put(ctx->timeline);
+
kfree(ctx->name);
put_pid(ctx->pid);
@@ -313,6 +316,7 @@ static void __destroy_hw_context(struct i915_gem_context *ctx,
}
#define CREATE_VM BIT(0)
+#define CREATE_TIMELINE BIT(1)
/**
* The default context needs to exist per ring that uses contexts. It stores the
@@ -328,6 +332,9 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
lockdep_assert_held(&dev_priv->drm.struct_mutex);
+ if (flags & CREATE_TIMELINE && !HAS_EXECLISTS(dev_priv))
+ return ERR_PTR(-EINVAL);
+
/* Reap the most stale context */
contexts_free_first(dev_priv);
@@ -350,6 +357,18 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
ctx->desc_template = default_desc_template(dev_priv, ppgtt);
}
+ if (flags & CREATE_TIMELINE) {
+ struct i915_timeline *timeline;
+
+ timeline = i915_timeline_create(dev_priv, ctx->name);
+ if (IS_ERR(timeline)) {
+ __destroy_hw_context(ctx, file_priv);
+ return ERR_CAST(timeline);
+ }
+
+ ctx->timeline = timeline;
+ }
+
trace_i915_context_create(ctx);
return ctx;
@@ -635,7 +654,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (args->pad != 0)
return -EINVAL;
- if (args->flags & ~I915_GEM_CONTEXT_SHARE_GTT)
+ if (args->flags &
+ ~(I915_GEM_CONTEXT_SHARE_GTT |
+ I915_GEM_CONTEXT_SINGLE_TIMELINE))
return -EINVAL;
if (client_is_banned(file_priv)) {
@@ -659,6 +680,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
flags &= ~CREATE_VM;
}
+ if (args->flags & I915_GEM_CONTEXT_SINGLE_TIMELINE)
+ flags |= CREATE_TIMELINE;
+
err = i915_mutex_lock_interruptible(dev);
if (err)
goto out;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index 33b1f3c10eea..34945eb6c440 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -37,6 +37,7 @@ struct drm_file;
struct drm_i915_private;
struct drm_i915_file_private;
struct i915_hw_ppgtt;
+struct i915_timeline;
struct i915_vma;
struct intel_ring;
@@ -55,6 +56,8 @@ struct i915_gem_context {
/** file_priv: owning file descriptor */
struct drm_i915_file_private *file_priv;
+ struct i915_timeline *timeline;
+
/**
* @ppgtt: unique address space (GTT)
*
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 9ad4c08522a8..b05e4137cfa9 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -1053,8 +1053,14 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
prev = i915_gem_active_raw(&timeline->last_request,
&request->i915->drm.struct_mutex);
if (prev && !i915_gem_request_completed(prev)) {
- i915_sw_fence_await_sw_fence(&request->submit, &prev->submit,
- &request->submitq);
+ if (prev->engine == engine)
+ i915_sw_fence_await_sw_fence(&request->submit,
+ &prev->submit,
+ &request->submitq);
+ else
+ __i915_sw_fence_await_dma_fence(&request->submit,
+ &prev->fence,
+ &request->dmaq);
if (engine->schedule)
__i915_priotree_add_dependency(&request->priotree,
&prev->priotree,
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index bd48410f84d9..ed13e2591199 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -143,7 +143,10 @@ struct drm_i915_gem_request {
* It is used by the driver to then queue the request for execution.
*/
struct i915_sw_fence submit;
- wait_queue_entry_t submitq;
+ union {
+ wait_queue_entry_t submitq;
+ struct i915_sw_dma_fence_cb dmaq;
+ };
wait_queue_head_t execute;
/* A list of everyone we wait upon, and everyone who waits upon us.
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 1de5173e53a2..11b2f8ce1c3f 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -362,11 +362,6 @@ int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
}
-struct i915_sw_dma_fence_cb {
- struct dma_fence_cb base;
- struct i915_sw_fence *fence;
-};
-
struct i915_sw_dma_fence_cb_timer {
struct i915_sw_dma_fence_cb base;
struct dma_fence *dma;
@@ -482,6 +477,40 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
return ret;
}
+static void __dma_i915_sw_fence_wake(struct dma_fence *dma,
+ struct dma_fence_cb *data)
+{
+ struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
+
+ i915_sw_fence_complete(cb->fence);
+}
+
+int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
+ struct dma_fence *dma,
+ struct i915_sw_dma_fence_cb *cb)
+{
+ int ret;
+
+ debug_fence_assert(fence);
+
+ if (dma_fence_is_signaled(dma))
+ return 0;
+
+ cb->fence = fence;
+ i915_sw_fence_await(fence);
+
+ ret = dma_fence_add_callback(dma, &cb->base, __dma_i915_sw_fence_wake);
+ if (ret == 0) {
+ ret = 1;
+ } else {
+ i915_sw_fence_complete(fence);
+ if (ret == -ENOENT) /* fence already signaled */
+ ret = 0;
+ }
+
+ return ret;
+}
+
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct reservation_object *resv,
const struct dma_fence_ops *exclude,
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index fe2ef4dadfc6..914a734d49bc 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -10,14 +10,13 @@
#ifndef _I915_SW_FENCE_H_
#define _I915_SW_FENCE_H_
+#include <linux/dma-fence.h>
#include <linux/gfp.h>
#include <linux/kref.h>
#include <linux/notifier.h> /* for NOTIFY_DONE */
#include <linux/wait.h>
struct completion;
-struct dma_fence;
-struct dma_fence_ops;
struct reservation_object;
struct i915_sw_fence {
@@ -69,10 +68,20 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
struct i915_sw_fence *after,
gfp_t gfp);
+
+struct i915_sw_dma_fence_cb {
+ struct dma_fence_cb base;
+ struct i915_sw_fence *fence;
+};
+
+int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
+ struct dma_fence *dma,
+ struct i915_sw_dma_fence_cb *cb);
int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
struct dma_fence *dma,
unsigned long timeout,
gfp_t gfp);
+
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct reservation_object *resv,
const struct dma_fence_ops *exclude,
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 4dc909ae15a7..7572162a8ff1 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2274,7 +2274,10 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
WARN_ON(ce->state);
- timeline = i915_timeline_create(ctx->i915, ctx->name);
+ if (ctx->timeline)
+ timeline = i915_timeline_get(ctx->timeline);
+ else
+ timeline = i915_timeline_create(ctx->i915, ctx->name);
if (IS_ERR(timeline))
return PTR_ERR(timeline);
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 3f7c9702a913..6e4eaf3819ff 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1387,7 +1387,8 @@ struct drm_i915_gem_context_create_v2 {
/* output: id of new context*/
__u32 ctx_id;
__u32 flags;
-#define I915_GEM_CONTEXT_SHARE_GTT 0x1
+#define I915_GEM_CONTEXT_SHARE_GTT 0x1
+#define I915_GEM_CONTEXT_SINGLE_TIMELINE 0x2
__u32 share_ctx;
__u32 pad;
};
--
2.15.1
More information about the Intel-gfx-trybot
mailing list