]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/gpu/drm/i915/intel_uncore.c
Merge tag 'drm-intel-fixes-2015-08-14' into drm-intel-next-fixes
[linux-beck.git] / drivers / gpu / drm / i915 / intel_uncore.c
index 260389acfb7752d01ce0ebd59597f06a671b2ea1..9d3c2e420d2b68611d52e9c6395d35721da19447 100644 (file)
@@ -1467,20 +1467,80 @@ static int gen6_do_reset(struct drm_device *dev)
        return ret;
 }
 
-int intel_gpu_reset(struct drm_device *dev)
+static int wait_for_register(struct drm_i915_private *dev_priv,
+                            const u32 reg,
+                            const u32 mask,
+                            const u32 value,
+                            const unsigned long timeout_ms)
+{
+       return wait_for((I915_READ(reg) & mask) == value, timeout_ms);
+}
+
+static int gen8_do_reset(struct drm_device *dev)
 {
-       if (INTEL_INFO(dev)->gen >= 6)
-               return gen6_do_reset(dev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_engine_cs *engine;
+       int i;
+
+       for_each_ring(engine, dev_priv, i) {
+               I915_WRITE(RING_RESET_CTL(engine->mmio_base),
+                          _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
+
+               if (wait_for_register(dev_priv,
+                                     RING_RESET_CTL(engine->mmio_base),
+                                     RESET_CTL_READY_TO_RESET,
+                                     RESET_CTL_READY_TO_RESET,
+                                     700)) {
+                       DRM_ERROR("%s: reset request timeout\n", engine->name);
+                       goto not_ready;
+               }
+       }
+
+       return gen6_do_reset(dev);
+
+not_ready:
+       for_each_ring(engine, dev_priv, i)
+               I915_WRITE(RING_RESET_CTL(engine->mmio_base),
+                          _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
+
+       return -EIO;
+}
+
+static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
+{
+       if (!i915.reset)
+               return NULL;
+
+       if (INTEL_INFO(dev)->gen >= 8)
+               return gen8_do_reset;
+       else if (INTEL_INFO(dev)->gen >= 6)
+               return gen6_do_reset;
        else if (IS_GEN5(dev))
-               return ironlake_do_reset(dev);
+               return ironlake_do_reset;
        else if (IS_G4X(dev))
-               return g4x_do_reset(dev);
+               return g4x_do_reset;
        else if (IS_G33(dev))
-               return g33_do_reset(dev);
+               return g33_do_reset;
        else if (INTEL_INFO(dev)->gen >= 3)
-               return i915_do_reset(dev);
+               return i915_do_reset;
        else
+               return NULL;
+}
+
+int intel_gpu_reset(struct drm_device *dev)
+{
+       int (*reset)(struct drm_device *);
+
+       reset = intel_get_gpu_reset(dev);
+       if (reset == NULL)
                return -ENODEV;
+
+       return reset(dev);
+}
+
+bool intel_has_gpu_reset(struct drm_device *dev)
+{
+       return intel_get_gpu_reset(dev) != NULL;
 }
 
 void intel_uncore_check_errors(struct drm_device *dev)