Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80b204bc authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Enable multiple timelines



With the infrastructure converted over to tracking multiple timelines in
the GEM API whilst preserving the efficiency of using a single execution
timeline internally, we can now assign a separate timeline to every
context with full-ppgtt.

v2: Add a comment to indicate the xfer between timelines upon submission.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-35-chris@chris-wilson.co.uk
parent f2d13290
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -3549,6 +3549,16 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx)
	kref_put(&ctx->ref, i915_gem_context_free);
}

static inline struct intel_timeline *
i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
				 struct intel_engine_cs *engine)
{
	struct i915_address_space *vm;

	vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base;
	return &vm->timeline.engine[engine->id];
}

static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
{
	return c->user_handle == DEFAULT_CONTEXT_HANDLE;
+6 −4
Original line number Diff line number Diff line
@@ -2564,12 +2564,9 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
	 * not need an engine->irq_seqno_barrier() before the seqno reads.
	 */
	list_for_each_entry(request, &engine->timeline->requests, link) {
		if (i915_gem_request_completed(request))
		if (__i915_gem_request_completed(request))
			continue;

		if (!i915_sw_fence_done(&request->submit))
			break;

		return request;
	}

@@ -2597,6 +2594,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
{
	struct drm_i915_gem_request *request;
	struct i915_gem_context *incomplete_ctx;
	struct intel_timeline *timeline;
	bool ring_hung;

	if (engine->irq_seqno_barrier)
@@ -2635,6 +2633,10 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
	list_for_each_entry_continue(request, &engine->timeline->requests, link)
		if (request->ctx == incomplete_ctx)
			reset_request(request);

	timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine);
	list_for_each_entry(request, &timeline->requests, link)
		reset_request(request);
}

void i915_gem_reset(struct drm_i915_private *dev_priv)
+2 −2
Original line number Diff line number Diff line
@@ -365,9 +365,9 @@ i915_gem_create_context(struct drm_device *dev,
		return ctx;

	if (USES_FULL_PPGTT(dev)) {
		struct i915_hw_ppgtt *ppgtt =
			i915_ppgtt_create(to_i915(dev), file_priv);
		struct i915_hw_ppgtt *ppgtt;

		ppgtt = i915_ppgtt_create(to_i915(dev), file_priv, ctx->name);
		if (IS_ERR(ppgtt)) {
			DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
					 PTR_ERR(ppgtt));
+7 −4
Original line number Diff line number Diff line
@@ -33,14 +33,17 @@
#include "intel_drv.h"
#include "i915_trace.h"

static bool
gpu_is_idle(struct drm_i915_private *dev_priv)
static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
{
	struct i915_ggtt *ggtt = &dev_priv->ggtt;
	struct intel_engine_cs *engine;
	enum intel_engine_id id;

	for_each_engine(engine, dev_priv, id) {
		if (intel_engine_is_active(engine))
		struct intel_timeline *tl;

		tl = &ggtt->base.timeline.engine[engine->id];
		if (i915_gem_active_isset(&tl->last_request))
			return false;
	}

@@ -154,7 +157,7 @@ i915_gem_evict_something(struct i915_address_space *vm,
	if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
		return -ENOSPC;

	if (gpu_is_idle(dev_priv)) {
	if (ggtt_is_idle(dev_priv)) {
		/* If we still have pending pageflip completions, drop
		 * back to userspace to give our workqueues time to
		 * acquire our locks and unpin the old scanouts.
+13 −6
Original line number Diff line number Diff line
@@ -2185,8 +2185,10 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
}

static void i915_address_space_init(struct i915_address_space *vm,
				    struct drm_i915_private *dev_priv)
				    struct drm_i915_private *dev_priv,
				    const char *name)
{
	i915_gem_timeline_init(dev_priv, &vm->timeline, name);
	drm_mm_init(&vm->mm, vm->start, vm->total);
	INIT_LIST_HEAD(&vm->active_list);
	INIT_LIST_HEAD(&vm->inactive_list);
@@ -2215,14 +2217,15 @@ static void gtt_write_workarounds(struct drm_device *dev)

static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
			   struct drm_i915_private *dev_priv,
			   struct drm_i915_file_private *file_priv)
			   struct drm_i915_file_private *file_priv,
			   const char *name)
{
	int ret;

	ret = __hw_ppgtt_init(ppgtt, dev_priv);
	if (ret == 0) {
		kref_init(&ppgtt->ref);
		i915_address_space_init(&ppgtt->base, dev_priv);
		i915_address_space_init(&ppgtt->base, dev_priv, name);
		ppgtt->base.file = file_priv;
	}

@@ -2258,7 +2261,8 @@ int i915_ppgtt_init_hw(struct drm_device *dev)

struct i915_hw_ppgtt *
i915_ppgtt_create(struct drm_i915_private *dev_priv,
		  struct drm_i915_file_private *fpriv)
		  struct drm_i915_file_private *fpriv,
		  const char *name)
{
	struct i915_hw_ppgtt *ppgtt;
	int ret;
@@ -2267,7 +2271,7 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv,
	if (!ppgtt)
		return ERR_PTR(-ENOMEM);

	ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv);
	ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv, name);
	if (ret) {
		kfree(ppgtt);
		return ERR_PTR(ret);
@@ -2290,6 +2294,7 @@ void i915_ppgtt_release(struct kref *kref)
	WARN_ON(!list_empty(&ppgtt->base.inactive_list));
	WARN_ON(!list_empty(&ppgtt->base.unbound_list));

	i915_gem_timeline_fini(&ppgtt->base.timeline);
	list_del(&ppgtt->base.global_link);
	drm_mm_takedown(&ppgtt->base.mm);

@@ -3232,11 +3237,13 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
	/* Subtract the guard page before address space initialization to
	 * shrink the range used by drm_mm.
	 */
	mutex_lock(&dev_priv->drm.struct_mutex);
	ggtt->base.total -= PAGE_SIZE;
	i915_address_space_init(&ggtt->base, dev_priv);
	i915_address_space_init(&ggtt->base, dev_priv, "[global]");
	ggtt->base.total += PAGE_SIZE;
	if (!HAS_LLC(dev_priv))
		ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
	mutex_unlock(&dev_priv->drm.struct_mutex);

	if (!io_mapping_init_wc(&dev_priv->ggtt.mappable,
				dev_priv->ggtt.mappable_base,
Loading