[PATCH] defaults
Chris Wilson
chris at chris-wilson.co.uk
Tue Oct 31 22:17:46 UTC 2017
---
drivers/gpu/drm/i915/intel_lrc.c | 170 +++++++++++++++++++++++++++++---
drivers/gpu/drm/i915/intel_ringbuffer.h | 1 +
2 files changed, 160 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 6840ec8db037..2f7d17927202 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1437,6 +1437,18 @@ static u8 gtiir[] = {
[VECS] = 3,
};
+static void enable_execlists(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+
+ I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
+ I915_WRITE(RING_MODE_GEN7(engine),
+ _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
+ I915_WRITE(RING_HWS_PGA(engine->mmio_base),
+ engine->status_page.ggtt_offset);
+ POSTING_READ(RING_HWS_PGA(engine->mmio_base));
+}
+
static int gen8_init_common_ring(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
@@ -1450,13 +1462,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
intel_engine_reset_breadcrumbs(engine);
intel_engine_init_hangcheck(engine);
- I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
- I915_WRITE(RING_MODE_GEN7(engine),
- _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
- I915_WRITE(RING_HWS_PGA(engine->mmio_base),
- engine->status_page.ggtt_offset);
- POSTING_READ(RING_HWS_PGA(engine->mmio_base));
-
+ enable_execlists(engine);
DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name);
GEM_BUG_ON(engine->id >= ARRAY_SIZE(gtiir));
@@ -1871,6 +1877,12 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
intel_engine_cleanup_common(engine);
lrc_destroy_wa_ctx(engine);
+
+ if (engine->default_state) {
+ i915_gem_object_unpin_map(engine->default_state);
+ i915_gem_object_put(engine->default_state);
+ }
+
engine->i915 = NULL;
dev_priv->engine[engine->id] = NULL;
kfree(engine);
@@ -1918,6 +1930,122 @@ logical_ring_default_irqs(struct intel_engine_cs *engine)
engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
}
+static bool csb_idle(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *i915 = engine->i915;
+ u32 __iomem *status =
+ i915->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0));
+ u32 __iomem *ring =
+ i915->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine));
+ u32 head, tail;
+ bool idle = false;
+
+ head = ioread32(ring);
+ tail = GEN8_CSB_WRITE_PTR(head);
+ head = GEN8_CSB_READ_PTR(head);
+
+ if (head >= GEN8_CSB_ENTRIES || tail >= GEN8_CSB_ENTRIES)
+ return false;
+
+ while (head != tail) {
+ if (++head == GEN8_CSB_ENTRIES)
+ head = 0;
+
+ if (ioread32(status + 2 * head) & GEN8_CTX_STATUS_ACTIVE_IDLE)
+ idle = true;
+ }
+
+ iowrite32(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), ring);
+
+ return idle;
+}
+
+static int lrc_record_defaults(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *i915 = engine->i915;
+ u32 __iomem *elsp =
+ i915->regs + i915_mmio_reg_offset(RING_ELSP(engine));
+ struct i915_gem_context *kctx = i915->kernel_context;
+ struct intel_context *ce = &kctx->engine[engine->id];
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
+ u32 context_size;
+ void *vaddr;
+ u32 *regs;
+ u64 desc;
+ int err;
+
+ /*
+ * As we reset the gpu during very early sanitisation, the current
+ * register state on the GPU should reflect its defaults values.
+ * We load a context onto the hw (with restore-inhibit), then switch
+ * over to a second context to save that default register state. We
+ * then prime every new context with that state so they all start
+ * from defaults.
+ */
+
+ GEM_BUG_ON(engine->default_state);
+
+ intel_runtime_pm_get(i915);
+ intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
+
+ context_size = round_up(engine->context_size, I915_GTT_PAGE_SIZE);
+ obj = i915_gem_object_create_internal(i915, context_size);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto out_rpm;
+ }
+
+ vma = i915_vma_instance(obj, &i915->ggtt.base, NULL);
+ if (IS_ERR(vma)) {
+ err = PTR_ERR(vma);
+ goto out_obj;
+ }
+
+ err = i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, PIN_GLOBAL);
+ if (err)
+ goto out_obj;
+
+ vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
+ if (IS_ERR(vaddr)) {
+ err = PTR_ERR(vaddr);
+ goto out_vma;
+ }
+
+ regs = vaddr + PAGE_SIZE;
+ execlists_init_reg_state(regs, kctx, engine, ce->ring);
+ regs[CTX_CONTEXT_CONTROL+1] |=
+ _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
+
+ desc = kctx->desc_template;
+ desc |= i915_ggtt_offset(vma);
+ desc |= (u64)(MAX_CONTEXT_HW_ID - 1) << GEN8_CTX_ID_SHIFT;
+
+ /* ELSP is programmed backwards. 2nd context first, 1st context last. */
+ enable_execlists(engine);
+ elsp_write(ce->lrc_desc, elsp);
+ elsp_write(desc, elsp);
+
+ msleep(1);
+ if (!wait_for(csb_idle(engine), 1000)) {
+ /* Keep a ref on the pages and owner */
+ engine->default_state = i915_gem_object_get(obj);
+ } else {
+ i915_gem_object_unpin_map(obj);
+ err = -EIO;
+ }
+
+out_vma:
+ i915_vma_unpin(vma);
+out_obj:
+ i915_gem_object_put(obj);
+out_rpm:
+ intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
+ intel_runtime_pm_put(i915);
+
+ return err;
+}
+
static void
logical_ring_setup(struct intel_engine_cs *engine)
{
@@ -1958,6 +2086,10 @@ static int logical_ring_init(struct intel_engine_cs *engine)
if (ret)
goto error;
+ ret = lrc_record_defaults(engine);
+ if (ret)
+ goto error;
+
return 0;
error:
@@ -2100,7 +2232,6 @@ static void execlists_init_reg_state(u32 *regs,
CTX_REG(regs, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(engine),
_MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
- CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
(HAS_RESOURCE_STREAMER(dev_priv) ?
CTX_CTRL_RS_CTX_ENABLE : 0)));
CTX_REG(regs, CTX_RING_HEAD, RING_HEAD(base), 0);
@@ -2177,6 +2308,7 @@ populate_lr_context(struct i915_gem_context *ctx,
struct intel_ring *ring)
{
void *vaddr;
+ u32 *regs;
int ret;
ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true);
@@ -2193,11 +2325,27 @@ populate_lr_context(struct i915_gem_context *ctx,
}
ctx_obj->mm.dirty = true;
+ if (engine->default_state) {
+ void *defaults;
+
+ defaults = i915_gem_object_pin_map(engine->default_state,
+ I915_MAP_WB);
+ if (IS_ERR(defaults))
+ return PTR_ERR(defaults);
+
+ memcpy(vaddr + LRC_HEADER_PAGES * PAGE_SIZE,
+ defaults, engine->context_size);
+ i915_gem_object_unpin_map(engine->default_state);
+ }
+
/* The second page of the context object contains some fields which must
* be set up prior to the first execution. */
-
- execlists_init_reg_state(vaddr + LRC_STATE_PN * PAGE_SIZE,
- ctx, engine, ring);
+ regs = vaddr + LRC_STATE_PN * PAGE_SIZE,
+ execlists_init_reg_state(regs, ctx, engine, ring);
+ if (!engine->default_state) {
+ regs[CTX_CONTEXT_CONTROL+1] |=
+ _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
+ }
i915_gem_object_unpin_map(ctx_obj);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 69ad875fd011..1d752b9a3065 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -303,6 +303,7 @@ struct intel_engine_cs {
struct intel_ring *buffer;
struct intel_timeline *timeline;
+ struct drm_i915_gem_object *default_state;
struct intel_render_state *render_state;
atomic_t irq_count;
--
2.15.0.rc2
More information about the Intel-gfx-trybot
mailing list