diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ada095023dad..80bed69fe5b7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -145,6 +145,13 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_printf(m, " (%s)", obj->ring->name); } +static void describe_ctx(struct seq_file *m, struct i915_hw_context *ctx) +{ + seq_putc(m, ctx->is_initialized ? 'I' : 'i'); + seq_putc(m, ctx->remap_slice ? 'R' : 'r'); + seq_putc(m, ' '); +} + static int i915_gem_object_list_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -1463,6 +1470,7 @@ static int i915_context_status(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) { seq_puts(m, "HW context "); + describe_ctx(m, ctx); for_each_ring(ring, dev_priv, i) if (ring->default_context == ctx) seq_printf(m, "(default context %s) ", ring->name); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 179592762537..015df5264dcc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -601,6 +601,7 @@ struct i915_hw_context { struct kref ref; int id; bool is_initialized; + uint8_t remap_slice; struct drm_i915_file_private *file_priv; struct intel_ring_buffer *ring; struct drm_i915_gem_object *obj; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2bbdce821ac3..9af3fe7e42b0 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -181,6 +181,10 @@ create_hw_context(struct drm_device *dev, ctx->file_priv = file_priv; ctx->id = ret; + /* NB: Mark all slices as needing a remap so that when the context first + * loads it will restore whatever remap state already exists. If there + * is no remap info, it will be a NOP. */ + ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; return ctx; @@ -396,11 +400,11 @@ static int do_switch(struct i915_hw_context *to) struct intel_ring_buffer *ring = to->ring; struct i915_hw_context *from = ring->last_context; u32 hw_flags = 0; - int ret; + int ret, i; BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); - if (from == to) + if (from == to && !to->remap_slice) return 0; ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); @@ -423,8 +427,6 @@ static int do_switch(struct i915_hw_context *to) if (!to->is_initialized || is_default_context(to)) hw_flags |= MI_RESTORE_INHIBIT; - else if (WARN_ON_ONCE(from == to)) /* not yet expected */ - hw_flags |= MI_FORCE_RESTORE; ret = mi_set_context(ring, to, hw_flags); if (ret) { @@ -432,6 +434,18 @@ static int do_switch(struct i915_hw_context *to) return ret; } + for (i = 0; i < MAX_L3_SLICES; i++) { + if (!(to->remap_slice & (1<remap_slice &= ~(1<dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; - uint32_t misccpctl; int slice = (int)(uintptr_t)attr->private; - int i, ret; + int ret; count = round_down(count, 4); @@ -134,26 +133,13 @@ i915_l3_read(struct file *filp, struct kobject *kobj, if (ret) return ret; - if (IS_HASWELL(drm_dev)) { - if (dev_priv->l3_parity.remap_info[slice]) - memcpy(buf, - dev_priv->l3_parity.remap_info[slice] + (offset/4), - count); - else - memset(buf, 0, count); + if (dev_priv->l3_parity.remap_info[slice]) + memcpy(buf, + dev_priv->l3_parity.remap_info[slice] + (offset/4), + count); + else + memset(buf, 0, count); - goto out; - } - - misccpctl = I915_READ(GEN7_MISCCPCTL); - I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); - - for (i = 0; i < count; i += 4) - *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + offset + i); - - I915_WRITE(GEN7_MISCCPCTL, misccpctl); - -out: mutex_unlock(&drm_dev->struct_mutex); return count; @@ -168,6 +154,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; + struct i915_hw_context *ctx; u32 *temp = NULL; /* Just here to make handling failures easy */ int slice = (int)(uintptr_t)attr->private; int ret; @@ -176,6 +163,9 @@ i915_l3_write(struct file *filp, struct kobject *kobj, if (ret) return ret; + if (dev_priv->hw_contexts_disabled) + return -ENXIO; + ret = i915_mutex_lock_interruptible(drm_dev); if (ret) return ret; @@ -204,8 +194,9 @@ i915_l3_write(struct file *filp, struct kobject *kobj, memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); - if (i915_gem_l3_remap(&dev_priv->ring[RCS], slice)) - count = 0; + /* NB: We defer the remapping until we switch to the context */ + list_for_each_entry(ctx, &dev_priv->context_list, link) + ctx->remap_slice |= (1<struct_mutex);