From 3ccfd19dea7c5c85aa4b1f929a97a02b026ab356 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 18 Sep 2013 19:03:18 -0700 Subject: drm/i915: Do remaps for all contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On both Ivybridge and Haswell, row remapping information is saved and restored with context. This means, we never actually properly supported the l3 remapping because our sysfs interface is asynchronous (and not tied to any context), and the known faulty HW would be reused by the next context to run. Not that due to the asynchronous nature of the sysfs entry, there is no point modifying the registers for the existing context. Instead we set a flag for all contexts to load the correct remapping information on the next run. Interested clients can use debugfs to determine whether or not the row has been remapped. One could propose at this point that we just do the remapping in the kernel. I guess since we have to maintain the sysfs interface anyway, I'm not sure how useful it is, and I do like keeping the policy in userspace; (it wasn't my original decision to make the interface the way it is, so I'm not attached). v2: Force a context switch when we have a remap on the next switch. (Ville) Don't let userspace use the interface with disabled contexts. v3: Don't force a context switch, just let it nop Improper context slice remap initialization, 1<<1 instead of 1< Signed-off-by: Ben Widawsky Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_sysfs.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/i915/i915_sysfs.c') diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index b07bdfb8892..deb8787308d 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -118,9 +118,8 @@ i915_l3_read(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; - 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); - - 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); + 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); -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); -- cgit v1.2.3