Merge tag 'drm-intel-next-2015-09-11' of git://anongit.freedesktop.org/drm-intel...
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / i915_gem.c
index 4d631a94648194957512d096e89da0e5242bd822..22071cbc206f720c95c58ec072f574778e9834bc 100644 (file)
@@ -1005,12 +1005,14 @@ out:
                if (!needs_clflush_after &&
                    obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
                        if (i915_gem_clflush_object(obj, obj->pin_display))
-                               i915_gem_chipset_flush(dev);
+                               needs_clflush_after = true;
                }
        }
 
        if (needs_clflush_after)
                i915_gem_chipset_flush(dev);
+       else
+               obj->cache_dirty = true;
 
        intel_fb_obj_flush(obj, false, ORIGIN_CPU);
        return ret;
@@ -3228,10 +3230,6 @@ int i915_vma_unbind(struct i915_vma *vma)
        ret = i915_gem_object_wait_rendering(obj, false);
        if (ret)
                return ret;
-       /* Continue on if we fail due to EIO, the GPU is hung so we
-        * should be safe and we need to cleanup or else we might
-        * cause memory corruption through use-after-free.
-        */
 
        if (i915_is_ggtt(vma->vm) &&
            vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
@@ -3355,7 +3353,8 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 size, fence_size, fence_alignment, unfenced_alignment;
+       u32 fence_alignment, unfenced_alignment;
+       u64 size, fence_size;
        u64 start =
                flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
        u64 end =
@@ -3414,7 +3413,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
         * attempt to find space.
         */
        if (size > end) {
-               DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%u > %s aperture=%llu\n",
+               DRM_DEBUG("Attempting to bind an object (view type=%u) larger than the aperture: size=%llu > %s aperture=%llu\n",
                          ggtt_view ? ggtt_view->type : 0,
                          size,
                          flags & PIN_MAPPABLE ? "mappable" : "total",
@@ -3638,10 +3637,10 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 {
        struct drm_device *dev = obj->base.dev;
        struct i915_vma *vma, *next;
-       int ret;
+       int ret = 0;
 
        if (obj->cache_level == cache_level)
-               return 0;
+               goto out;
 
        if (i915_gem_obj_is_pinned(obj)) {
                DRM_DEBUG("can not change the cache level of pinned objects\n");
@@ -3686,6 +3685,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
                vma->node.color = cache_level;
        obj->cache_level = cache_level;
 
+out:
        if (obj->cache_dirty &&
            obj->base.write_domain != I915_GEM_DOMAIN_CPU &&
            cpu_write_needs_clflush(obj)) {
@@ -3738,6 +3738,15 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                level = I915_CACHE_NONE;
                break;
        case I915_CACHING_CACHED:
+               /*
+                * Due to a HW issue on BXT A stepping, GPU stores via a
+                * snooped mapping may leave stale data in a corresponding CPU
+                * cacheline, whereas normally such cachelines would get
+                * invalidated.
+                */
+               if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)
+                       return -ENODEV;
+
                level = I915_CACHE_LLC;
                break;
        case I915_CACHING_DISPLAY:
@@ -4011,15 +4020,13 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
                        return -EBUSY;
 
                if (i915_vma_misplaced(vma, alignment, flags)) {
-                       unsigned long offset;
-                       offset = ggtt_view ? i915_gem_obj_ggtt_offset_view(obj, ggtt_view) :
-                                            i915_gem_obj_offset(obj, vm);
                        WARN(vma->pin_count,
                             "bo is already pinned in %s with incorrect alignment:"
-                            " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
+                            " offset=%08x %08x, req.alignment=%x, req.map_and_fenceable=%d,"
                             " obj->map_and_fenceable=%d\n",
                             ggtt_view ? "ggtt" : "ppgtt",
-                            offset,
+                            upper_32_bits(vma->node.start),
+                            lower_32_bits(vma->node.start),
                             alignment,
                             !!(flags & PIN_MAPPABLE),
                             obj->map_and_fenceable);
@@ -4679,6 +4686,22 @@ i915_gem_init_hw(struct drm_device *dev)
                        goto out;
        }
 
+       /* We can't enable contexts until all firmware is loaded */
+       ret = intel_guc_ucode_load(dev);
+       if (ret) {
+               /*
+                * If we got an error and GuC submission is enabled, map
+                * the error to -EIO so the GPU will be declared wedged.
+                * OTOH, if we didn't intend to use the GuC anyway, just
+                * discard the error and carry on.
+                */
+               DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret,
+                       i915.enable_guc_submission ? "" : " (ignored)");
+               ret = i915.enable_guc_submission ? -EIO : 0;
+               if (ret)
+                       goto out;
+       }
+
        /* Now it is safe to go back round and do everything else: */
        for_each_ring(ring, dev_priv, i) {
                struct drm_i915_gem_request *req;
@@ -4974,9 +4997,8 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
 }
 
 /* All the new VM stuff */
-unsigned long
-i915_gem_obj_offset(struct drm_i915_gem_object *o,
-                   struct i915_address_space *vm)
+u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
+                       struct i915_address_space *vm)
 {
        struct drm_i915_private *dev_priv = o->base.dev->dev_private;
        struct i915_vma *vma;
@@ -4996,9 +5018,8 @@ i915_gem_obj_offset(struct drm_i915_gem_object *o,
        return -1;
 }
 
-unsigned long
-i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
-                             const struct i915_ggtt_view *view)
+u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
+                                 const struct i915_ggtt_view *view)
 {
        struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
        struct i915_vma *vma;