]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/i915/i915_gem_execbuffer.c
drm/i915: relative_constants_mode race fix
[~andy/linux] / drivers / gpu / drm / i915 / i915_gem_execbuffer.c
index 3693e83a97f325f95276b4e9c009ac48569174ed..68e5b41dc7f214cabc91382e7ff4b3c037268c4d 100644 (file)
@@ -32,6 +32,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/dma_remapping.h>
 
 struct change_domains {
        uint32_t invalidate_domains;
@@ -746,6 +747,22 @@ i915_gem_execbuffer_flush(struct drm_device *dev,
        return 0;
 }
 
+static bool
+intel_enable_semaphores(struct drm_device *dev)
+{
+       if (INTEL_INFO(dev)->gen < 6)
+               return 0;
+
+       if (i915_semaphores >= 0)
+               return i915_semaphores;
+
+       /* Enable semaphores on SNB when IO remapping is off */
+       if (INTEL_INFO(dev)->gen == 6)
+               return !intel_iommu_enabled;
+
+       return 1;
+}
+
 static int
 i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
                               struct intel_ring_buffer *to)
@@ -758,7 +775,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
                return 0;
 
        /* XXX gpu semaphores are implicated in various hard hangs on SNB */
-       if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
+       if (!intel_enable_semaphores(obj->base.dev))
                return i915_gem_object_wait_rendering(obj);
 
        idx = intel_ring_sync_index(from, to);
@@ -1016,19 +1033,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                        if (INTEL_INFO(dev)->gen > 5 &&
                            mode == I915_EXEC_CONSTANTS_REL_SURFACE)
                                return -EINVAL;
-
-                       ret = intel_ring_begin(ring, 4);
-                       if (ret)
-                               return ret;
-
-                       intel_ring_emit(ring, MI_NOOP);
-                       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-                       intel_ring_emit(ring, INSTPM);
-                       intel_ring_emit(ring,
-                                       I915_EXEC_CONSTANTS_MASK << 16 | mode);
-                       intel_ring_advance(ring);
-
-                       dev_priv->relative_constants_mode = mode;
                }
                break;
        default:
@@ -1159,6 +1163,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
        }
 
+       if (ring == &dev_priv->ring[RCS] &&
+           mode != dev_priv->relative_constants_mode) {
+               ret = intel_ring_begin(ring, 4);
+               if (ret)
+                               goto err;
+
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit(ring, INSTPM);
+               intel_ring_emit(ring,
+                               I915_EXEC_CONSTANTS_MASK << 16 | mode);
+               intel_ring_advance(ring);
+
+               dev_priv->relative_constants_mode = mode;
+       }
+
        trace_i915_gem_ring_dispatch(ring, seqno);
 
        exec_start = batch_obj->gtt_offset + args->batch_start_offset;