[RFC] drm/i915/lrc: Update PDPx registers with lri commands

Submitted by Michel Thierry on June 5, 2015, 3:42 p.m.

Details

Message ID 1433518969-778-1-git-send-email-michel.thierry@intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Michel Thierry June 5, 2015, 3:42 p.m.
A safer way to update the PDPx registers is sending lri commands, added in
the ring before the batchbuffer start. Otherwise, the ctx must be idle before
trying to change anything (but the ring-tail) in the ctx image. An
example where the ctx won't be idle is lite-restore.

This patch depends on [1], and has the advantage that it doesn't require
to pre-allocate the top pdps like here [2].

[1] http://mid.gmane.org/1432314314-23530-2-git-send-email-mika.kuoppala@intel.com
[2] http://mid.gmane.org/1432314314-23530-3-git-send-email-mika.kuoppala@intel.com

Cc: Dave Gordon <david.s.gordon@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Michel Thierry <michel.thierry@intel.com>
---
 drivers/gpu/drm/i915/intel_lrc.c | 57 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 44ddb4d..0cf2f2c 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1124,13 +1124,70 @@  static int gen9_init_render_ring(struct intel_engine_cs *ring)
 	return init_workarounds_ring(ring);
 }
 
+static int intel_logical_ring_write_pdp(struct intel_engine_cs *ring,
+					struct intel_context *ctx,
+					unsigned entry,
+					dma_addr_t addr)
+{
+	struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
+	int ret;
+
+	WARN_ON(entry >= 4);
+
+	ret = intel_logical_ring_begin(ringbuf, ctx, 6);
+	if (ret)
+		return ret;
+
+	intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
+	intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_UDW(ring, entry));
+	intel_logical_ring_emit(ringbuf, upper_32_bits(addr));
+	intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
+	intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_LDW(ring, entry));
+	intel_logical_ring_emit(ringbuf, lower_32_bits(addr));
+	intel_logical_ring_advance(ringbuf);
+
+	return 0;
+}
+
+static int intel_logical_ring_emit_pdps(struct intel_engine_cs *ring,
+					struct intel_context *ctx)
+{
+	struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
+	int i, ret;
+
+	for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
+		const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
+
+		ret = intel_logical_ring_write_pdp(ring, ctx, i, pd_daddr);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int gen8_emit_bb_start(struct intel_ringbuffer *ringbuf,
 			      struct intel_context *ctx,
 			      u64 offset, unsigned dispatch_flags)
 {
+	struct intel_engine_cs *ring = ringbuf->ring;
 	bool ppgtt = !(dispatch_flags & I915_DISPATCH_SECURE);
 	int ret;
 
+	/* Don't rely in hw updating PDPs, specially in lite-restore.
+	 * Ideally, we should set Force PD Restore in ctx descriptor,
+	 * but we can't. Force Restore would be a second option, but
+	 * it is unsafe in case of lite-restore (because the ctx is
+	 * not idle). */
+	if (ctx->ppgtt &&
+	    (intel_ring_flag(ring) & ctx->ppgtt->pd_dirty_rings)) {
+		ret = intel_logical_ring_emit_pdps(ring, ctx);
+		if (ret)
+			return ret;
+
+		ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring);
+	}
+
 	ret = intel_logical_ring_begin(ringbuf, ctx, 4);
 	if (ret)
 		return ret;