diff mbox

drm/i915: Change context lifecycle

Message ID 1447085900-29407-1-git-send-email-nicholas.hoath@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Nick Hoath Nov. 9, 2015, 4:18 p.m. UTC
Use the first retired request on a new context to unpin
the old context. This ensures that the hw context remains
bound until it has been saved.
Now that the context is pinned until later in the request/context
lifecycle, it no longer needs to be pinned from context_queue to
retire_requests.
The refcount on the context also has to be extended to cover this
new longer period.

Signed-off-by: Nick Hoath <nicholas.hoath@intel.com>
Issue: VIZ-4277
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: David Gordon <david.s.gordon@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Alex Dai <yu.dai@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  1 +
 drivers/gpu/drm/i915/i915_gem.c  |  7 +++++
 drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_lrc.h |  1 +
 4 files changed, 57 insertions(+), 10 deletions(-)

Comments

Chris Wilson Nov. 10, 2015, 8:49 a.m. UTC | #1
On Mon, Nov 09, 2015 at 04:18:20PM +0000, Nick Hoath wrote:
> Use the first retired request on a new context to unpin
> the old context. This ensures that the hw context remains
> bound until it has been saved.
> Now that the context is pinned until later in the request/context
> lifecycle, it no longer needs to be pinned from context_queue to
> retire_requests.
> The refcount on the context also has to be extended to cover this
> new longer period.

Still not right. You were closer with the active tracking. The code I
sent last year fixed this by unifying the pin/active tracking of legacy
and execlists by calling engine->pin_context() in i915_gem_request_alloc(),
and then in the request commit we released the pin on the
engine->last_context and replaced it with active tracking (or just unpinned
the new context in request cancel).
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 20cd6d8..778b14a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -884,6 +884,7 @@  struct intel_context {
 	struct {
 		struct drm_i915_gem_object *state;
 		struct intel_ringbuffer *ringbuf;
+		bool unsaved;
 		int pin_count;
 	} engine[I915_NUM_RINGS];
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f1e3fde..273946d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1385,6 +1385,13 @@  __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
 		tmp = list_first_entry(&engine->request_list,
 				       typeof(*tmp), list);
 
+		if (i915.enable_execlists) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&engine->execlist_lock, flags);
+			intel_lr_context_complete_check(tmp);
+			spin_unlock_irqrestore(&engine->execlist_lock, flags);
+		}
 		i915_gem_request_retire(tmp);
 	} while (tmp != req);
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 06180dc..d82e903 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -566,13 +566,17 @@  static int execlists_context_queue(struct drm_i915_gem_request *request)
 	struct drm_i915_gem_request *cursor;
 	int num_elements = 0;
 
-	if (request->ctx != ring->default_context)
-		intel_lr_context_pin(request);
-
 	i915_gem_request_reference(request);
 
 	spin_lock_irq(&ring->execlist_lock);
 
+	if (request->ctx != ring->default_context) {
+		if (!request->ctx->engine[ring->id].unsaved) {
+			intel_lr_context_pin(request);
+			request->ctx->engine[ring->id].unsaved = true;
+		}
+	}
+
 	list_for_each_entry(cursor, &ring->execlist_queue, execlist_link)
 		if (++num_elements > 2)
 			break;
@@ -958,12 +962,6 @@  void intel_execlists_retire_requests(struct intel_engine_cs *ring)
 	spin_unlock_irq(&ring->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[ring->id].state;
-
-		if (ctx_obj && (ctx != ring->default_context))
-			intel_lr_context_unpin(req);
 		list_del(&req->execlist_link);
 		i915_gem_request_unreference(req);
 	}
@@ -1073,6 +1071,31 @@  void intel_lr_context_unpin(struct drm_i915_gem_request *rq)
 	}
 }
 
+void intel_lr_context_complete_check(struct drm_i915_gem_request *req)
+{
+	struct intel_engine_cs *ring = req->ring;
+
+	assert_spin_locked(&ring->execlist_lock);
+
+	if (ring->last_context && ring->last_context != req->ctx) {
+		if (req->ctx != ring->default_context
+			&& ring->last_context->engine[ring->id].unsaved) {
+			/* Create fake request for unpinning the old context */
+			struct drm_i915_gem_request tmp;
+
+			tmp.ring = ring;
+			tmp.ctx = ring->last_context;
+			tmp.ringbuf =
+				ring->last_context->engine[ring->id].ringbuf;
+
+			intel_lr_context_unpin(&tmp);
+			ring->last_context->engine[ring->id].unsaved = false;
+			ring->last_context = NULL;
+		}
+	}
+	ring->last_context = req->ctx;
+}
+
 static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
 	int ret, i;
@@ -2390,7 +2413,22 @@  void intel_lr_context_free(struct intel_context *ctx)
 				intel_unpin_ringbuffer_obj(ringbuf);
 				i915_gem_object_ggtt_unpin(ctx_obj);
 			}
-			WARN_ON(ctx->engine[ring->id].pin_count);
+
+			if (ctx->engine[ring->id].unsaved) {
+				/**
+				 * Create fake request for unpinning the old
+				 * context
+				 */
+				struct drm_i915_gem_request tmp;
+
+				tmp.ring = ring;
+				tmp.ctx = ctx;
+				tmp.ringbuf = ringbuf;
+				intel_lr_context_unpin(&tmp);
+				ctx->engine[ring->id].unsaved = false;
+			}
+
+			WARN_ON(ctx->engine[i].pin_count);
 			intel_ringbuffer_free(ringbuf);
 			drm_gem_object_unreference(&ctx_obj->base);
 		}
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 4e60d54..cbc42b8 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -86,6 +86,7 @@  void intel_lr_context_reset(struct drm_device *dev,
 			struct intel_context *ctx);
 uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
 				     struct intel_engine_cs *ring);
+void intel_lr_context_complete_check(struct drm_i915_gem_request *req);
 
 /* Execlists */
 int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);