Re: [PATCH 3/9] drm/i915: Refactor execlists default context pinning

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 19/04/16 07:49, Chris Wilson wrote:
Refactor pinning and unpinning of contexts, such that the default
context for an engine is pinned during initialisation and unpinned
during teardown (pinning of the context handles the reference counting).
Thus we can eliminate the special case handling of the default context
that was required to mask that it was not being pinned normally.

v2: Rebalance context_queue after rebasing.

Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
---
  drivers/gpu/drm/i915/i915_debugfs.c     |   5 +-
  drivers/gpu/drm/i915/i915_gem_request.c |   6 +-
  drivers/gpu/drm/i915/intel_lrc.c        | 103 ++++++++++++--------------------
  3 files changed, 41 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index bd409bfa6e61..a07c3478f0d8 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2108,9 +2108,8 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
  		return ret;

  	list_for_each_entry(ctx, &dev_priv->context_list, link)
-		if (ctx != dev_priv->kernel_context)
-			for_each_engine(engine, dev_priv)
-				i915_dump_lrc_obj(m, ctx, engine);
+		for_each_engine(engine, dev_priv)
+			i915_dump_lrc_obj(m, ctx, engine);

  	mutex_unlock(&dev->struct_mutex);

diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index a6f3e6e53b3b..33aacf1725dd 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -644,10 +644,8 @@ void i915_gem_request_free(struct kref *req_ref)
  		i915_gem_request_remove_from_client(req);

  	if (ctx) {
-		if (i915.enable_execlists) {
-			if (ctx != to_i915(req)->kernel_context)
-				intel_lr_context_unpin(ctx, req->engine);
-		}
+		if (i915.enable_execlists)
+			intel_lr_context_unpin(ctx, req->engine);

  		i915_gem_context_unreference(ctx);
  	}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index cec112449b31..79ac6f06a502 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -585,9 +585,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request)
  	struct drm_i915_gem_request *cursor;
  	int num_elements = 0;

-	if (request->ctx != to_i915(request)->kernel_context)
-		intel_lr_context_pin(request->ctx, engine);
-
+	intel_lr_context_pin(request->ctx, request->engine);
  	i915_gem_request_reference(request);

  	spin_lock_bh(&engine->execlist_lock);
@@ -688,10 +686,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
  			return ret;
  	}

-	if (request->ctx != to_i915(request)->kernel_context)
-		ret = intel_lr_context_pin(request->ctx, request->engine);
-
-	return ret;
+	return intel_lr_context_pin(request->ctx, request->engine);
  }

  static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
@@ -768,12 +763,8 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
  	if (engine->last_context != request->ctx) {
  		if (engine->last_context)
  			intel_lr_context_unpin(engine->last_context, engine);
-		if (request->ctx != to_i915(request)->kernel_context) {
-			intel_lr_context_pin(request->ctx, engine);
-			engine->last_context = request->ctx;
-		} else {
-			engine->last_context = NULL;
-		}
+		intel_lr_context_pin(request->ctx, engine);
+		engine->last_context = request->ctx;
  	}

  	if (dev_priv->guc.execbuf_client)
@@ -996,12 +987,7 @@ void intel_execlists_retire_requests(struct intel_engine_cs *engine)
  	spin_unlock_bh(&engine->execlist_lock);

  	list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
-		struct intel_context *ctx = req->ctx;
-		struct drm_i915_gem_object *ctx_obj =
-				ctx->engine[engine->id].state;
-
-		if (ctx_obj && (ctx != to_i915(req)->kernel_context))
-			intel_lr_context_unpin(ctx, engine);
+		intel_lr_context_unpin(req->ctx, engine);

  		list_del(&req->execlist_link);
  		i915_gem_request_unreference(req);
@@ -1046,22 +1032,25 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
  	return 0;
  }

-static int intel_lr_context_do_pin(struct intel_context *ctx,
-				   struct intel_engine_cs *engine)
+static int intel_lr_context_pin(struct intel_context *ctx,
+				struct intel_engine_cs *engine)
  {
  	struct drm_i915_private *dev_priv = ctx->i915;
-	struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
-	struct intel_ringbuffer *ringbuf = ctx->engine[engine->id].ringbuf;
+	struct drm_i915_gem_object *ctx_obj;
+	struct intel_ringbuffer *ringbuf;
  	void *vaddr;
-	u32 *lrc_reg_state;
+	uint32_t *lrc_reg_state;

I prefer u32, and you preferred u64 in "drm/i915: Replace the pinned context address with its unique ID". :) Doesn't matter really, it is too late for consistency anyway.

  	int ret;

-	WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex));
+	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	if (ctx->engine[engine->id].pin_count++)
+		return 0;

+	ctx_obj = ctx->engine[engine->id].state;
  	ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
  			PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
  	if (ret)
-		return ret;
+		goto err;

  	vaddr = i915_gem_object_pin_map(ctx_obj);
  	if (IS_ERR(vaddr)) {
@@ -1071,10 +1060,12 @@ static int intel_lr_context_do_pin(struct intel_context *ctx,

  	lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;

+	ringbuf = ctx->engine[engine->id].ringbuf;
  	ret = intel_pin_and_map_ringbuffer_obj(engine->dev, ringbuf);
  	if (ret)
  		goto unpin_map;

+	i915_gem_context_reference(ctx);
  	ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
  	intel_lr_context_descriptor_update(ctx, engine);
  	lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start;
@@ -1085,31 +1076,13 @@ static int intel_lr_context_do_pin(struct intel_context *ctx,
  	if (i915.enable_guc_submission)
  		I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);

-	return ret;
+	return 0;

  unpin_map:
  	i915_gem_object_unpin_map(ctx_obj);
  unpin_ctx_obj:
  	i915_gem_object_ggtt_unpin(ctx_obj);
-
-	return ret;
-}
-
-static int intel_lr_context_pin(struct intel_context *ctx,
-				struct intel_engine_cs *engine)
-{
-	int ret = 0;
-
-	if (ctx->engine[engine->id].pin_count++ == 0) {
-		ret = intel_lr_context_do_pin(ctx, engine);
-		if (ret)
-			goto reset_pin_count;
-
-		i915_gem_context_reference(ctx);
-	}
-	return ret;
-
-reset_pin_count:
+err:
  	ctx->engine[engine->id].pin_count = 0;
  	return ret;
  }
@@ -1119,17 +1092,21 @@ void intel_lr_context_unpin(struct intel_context *ctx,
  {
  	struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;

-	WARN_ON(!mutex_is_locked(&ctx->i915->dev->struct_mutex));
-	if (--ctx->engine[engine->id].pin_count == 0) {
-		i915_gem_object_unpin_map(ctx_obj);
-		intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf);
-		i915_gem_object_ggtt_unpin(ctx_obj);
-		ctx->engine[engine->id].lrc_vma = NULL;
-		ctx->engine[engine->id].lrc_desc = 0;
-		ctx->engine[engine->id].lrc_reg_state = NULL;
+	lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+	GEM_BUG_ON(ctx->engine[engine->id].pin_count == 0);

I thought it is more readable to leave space between asserts and code. And in pin as well if you decide to do it.

+	if (--ctx->engine[engine->id].pin_count)
+		return;

-		i915_gem_context_unreference(ctx);
-	}

Could move ctx_obj assignment just before use here.

+	i915_gem_object_unpin_map(ctx_obj);
+	intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf);
+
+	i915_gem_object_ggtt_unpin(ctx_obj);
+
+	ctx->engine[engine->id].lrc_vma = NULL;
+	ctx->engine[engine->id].lrc_desc = 0;
+	ctx->engine[engine->id].lrc_reg_state = NULL;
+
+	i915_gem_context_unreference(ctx);
  }

  static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
@@ -1982,6 +1959,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
  		i915_gem_object_unpin_map(engine->status_page.obj);
  		engine->status_page.obj = NULL;
  	}
+	intel_lr_context_unpin(engine->i915->kernel_context, engine);

I don't see engine->i915 upstream yet unless I am missing something. dev_priv is already there on the other hand.


  	engine->idle_lite_restore_wa = 0;
  	engine->disable_lite_restore_wa = false;
@@ -2104,11 +2082,10 @@ logical_ring_init(struct intel_engine_cs *engine)
  		goto error;

  	/* As this is the default context, always pin it */
-	ret = intel_lr_context_do_pin(dctx, engine);
+	ret = intel_lr_context_pin(dctx, engine);
  	if (ret) {
-		DRM_ERROR(
-			"Failed to pin and map ringbuffer %s: %d\n",
-			engine->name, ret);
+		DRM_ERROR("Failed to pin context for %s: %d\n",
+			  engine->name, ret);
  		goto error;
  	}

@@ -2505,12 +2482,6 @@ void intel_lr_context_free(struct intel_context *ctx)
  		if (!ctx_obj)
  			continue;

-		if (ctx == ctx->i915->kernel_context) {
-			intel_unpin_ringbuffer_obj(ringbuf);
-			i915_gem_object_ggtt_unpin(ctx_obj);
-			i915_gem_object_unpin_map(ctx_obj);
-		}
-
  		WARN_ON(ctx->engine[i].pin_count);
  		intel_ringbuffer_free(ringbuf);
  		drm_gem_object_unreference(&ctx_obj->base);


Just some minors then and correct rebase. Otherwise I think it is correct.

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux