]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/i915: Revoke fenced GTT mmapings across GPU reset
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 4 Jan 2017 14:51:10 +0000 (14:51 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 4 Jan 2017 18:44:30 +0000 (18:44 +0000)
The fence registers are clobbered by a GPU reset. If there is concurrent
user access to a fenced region via a GTT mmaping, the access will not be
fenced during the reset (until we restore the fences afterwards). In order
to prevent invalid access during the reset, before we clobber the fences
first we must invalidate the GTT mmapings. Access to the mmap will then
be forced to fault in the page, and in handling the fault, i915_gem_fault()
will take the struct_mutex and wait upon the reset to complete.

v2: Fix up commentary.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99274
Testcase: igt/gem_mmap_gtt/hang
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170104145110.1486-1-chris@chris-wilson.co.uk
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_fence_reg.c

index 2c020eafada62be1b46d50af386b0560ab06e1d5..4d22b4b479b89948dde2740f3f3d08cf5f28cb7c 100644 (file)
@@ -1776,6 +1776,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
        error->reset_count++;
 
        pr_notice("drm/i915: Resetting chip after gpu hang\n");
+       i915_gem_reset_prepare(dev_priv);
 
        disable_engines_irq(dev_priv);
        ret = intel_gpu_reset(dev_priv, ALL_ENGINES);
@@ -1789,7 +1790,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
                goto error;
        }
 
-       i915_gem_reset(dev_priv);
+       i915_gem_reset_finish(dev_priv);
        intel_overlay_reset(dev_priv);
 
        /* Ok, now get things going again... */
index 0ea63d6acf4cf0c7806c537cb50da8322ea87ac5..7b436621d038c755aafcb5c25bdb824153cfccad 100644 (file)
@@ -3334,7 +3334,8 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
        return READ_ONCE(error->reset_count);
 }
 
-void i915_gem_reset(struct drm_i915_private *dev_priv);
+void i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
+void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
 void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
 int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
@@ -3418,6 +3419,7 @@ i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
 
+void i915_gem_revoke_fences(struct drm_i915_private *dev_priv);
 void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
 
 void i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv);
index d8760acf800183b6b8edb383977327944bd24d47..37107448a42b976b613896b003846c47b8bd215f 100644 (file)
@@ -2726,6 +2726,11 @@ static void reset_request(struct drm_i915_gem_request *request)
        memset(vaddr + head, 0, request->postfix - head);
 }
 
+void i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
+{
+       i915_gem_revoke_fences(dev_priv);
+}
+
 static void i915_gem_reset_engine(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *request;
@@ -2791,7 +2796,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
        spin_unlock_irqrestore(&engine->timeline->lock, flags);
 }
 
-void i915_gem_reset(struct drm_i915_private *dev_priv)
+void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
index e039839732526dead680eff31bf8e7e4d7d8894a..775059e19ab9d2b72fa42f09f3741f9a91cb7aad 100644 (file)
@@ -366,6 +366,30 @@ i915_vma_get_fence(struct i915_vma *vma)
        return fence_update(fence, set);
 }
 
+/**
+ * i915_gem_revoke_fences - revoke fence state
+ * @dev_priv: i915 device private
+ *
+ * Removes all GTT mmappings via the fence registers. This forces any user
+ * of the fence to reacquire that fence before continuing with their access.
+ * One use is during GPU reset where the fence register is lost and we need to
+ * revoke concurrent userspace access via GTT mmaps until the hardware has been
+ * reset and the fence registers have been restored.
+ */
+void i915_gem_revoke_fences(struct drm_i915_private *dev_priv)
+{
+       int i;
+
+       lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+       for (i = 0; i < dev_priv->num_fence_regs; i++) {
+               struct drm_i915_fence_reg *fence = &dev_priv->fence_regs[i];
+
+               if (fence->vma)
+                       i915_gem_release_mmap(fence->vma->obj);
+       }
+}
+
 /**
  * i915_gem_restore_fences - restore fence state
  * @dev_priv: i915 device private