diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4d631a946481..22071cbc206f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -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; |
