diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gem/i915_gem_clflush.c')
-rw-r--r-- | drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 144 |
1 files changed, 60 insertions, 84 deletions
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index 5295285d5843..0512afdd20d8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -4,100 +4,83 @@ * Copyright © 2016 Intel Corporation */ +#include <drm/drm_cache.h> + #include "display/intel_frontbuffer.h" #include "i915_drv.h" #include "i915_gem_clflush.h" - -static DEFINE_SPINLOCK(clflush_lock); +#include "i915_sw_fence_work.h" +#include "i915_trace.h" struct clflush { - struct dma_fence dma; /* Must be first for dma_fence_free() */ - struct i915_sw_fence wait; - struct work_struct work; + struct dma_fence_work base; struct drm_i915_gem_object *obj; }; -static const char *i915_clflush_get_driver_name(struct dma_fence *fence) +static void __do_clflush(struct drm_i915_gem_object *obj) { - return DRIVER_NAME; + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); + drm_clflush_sg(obj->mm.pages); + + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); } -static const char *i915_clflush_get_timeline_name(struct dma_fence *fence) +static void clflush_work(struct dma_fence_work *base) { - return "clflush"; + struct clflush *clflush = container_of(base, typeof(*clflush), base); + + __do_clflush(clflush->obj); } -static void i915_clflush_release(struct dma_fence *fence) +static void clflush_release(struct dma_fence_work *base) { - struct clflush *clflush = container_of(fence, typeof(*clflush), dma); - - i915_sw_fence_fini(&clflush->wait); + struct clflush *clflush = container_of(base, typeof(*clflush), base); - BUILD_BUG_ON(offsetof(typeof(*clflush), dma)); - dma_fence_free(&clflush->dma); + i915_gem_object_unpin_pages(clflush->obj); + i915_gem_object_put(clflush->obj); } -static const struct dma_fence_ops i915_clflush_ops = { - .get_driver_name = i915_clflush_get_driver_name, - .get_timeline_name = i915_clflush_get_timeline_name, - .release = i915_clflush_release, +static const struct dma_fence_work_ops clflush_ops = { + .name = "clflush", + .work = clflush_work, + .release = clflush_release, }; -static void __i915_do_clflush(struct drm_i915_gem_object *obj) +static struct clflush *clflush_work_create(struct drm_i915_gem_object *obj) { - GEM_BUG_ON(!i915_gem_object_has_pages(obj)); - drm_clflush_sg(obj->mm.pages); - intel_fb_obj_flush(obj, ORIGIN_CPU); -} - -static void i915_clflush_work(struct work_struct *work) -{ - struct clflush *clflush = container_of(work, typeof(*clflush), work); - struct drm_i915_gem_object *obj = clflush->obj; - - if (i915_gem_object_pin_pages(obj)) { - DRM_ERROR("Failed to acquire obj->pages for clflushing\n"); - goto out; - } - - __i915_do_clflush(obj); - - i915_gem_object_unpin_pages(obj); - -out: - i915_gem_object_put(obj); - - dma_fence_signal(&clflush->dma); - dma_fence_put(&clflush->dma); -} + struct clflush *clflush; -static int __i915_sw_fence_call -i915_clflush_notify(struct i915_sw_fence *fence, - enum i915_sw_fence_notify state) -{ - struct clflush *clflush = container_of(fence, typeof(*clflush), wait); + GEM_BUG_ON(!obj->cache_dirty); - switch (state) { - case FENCE_COMPLETE: - schedule_work(&clflush->work); - break; + clflush = kmalloc(sizeof(*clflush), GFP_KERNEL); + if (!clflush) + return NULL; - case FENCE_FREE: - dma_fence_put(&clflush->dma); - break; + if (__i915_gem_object_get_pages(obj) < 0) { + kfree(clflush); + return NULL; } - return NOTIFY_DONE; + dma_fence_work_init(&clflush->base, &clflush_ops); + clflush->obj = i915_gem_object_get(obj); /* obj <-> clflush cycle */ + + return clflush; } bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, unsigned int flags) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct clflush *clflush; assert_object_held(obj); + if (IS_DGFX(i915)) { + WARN_ON_ONCE(obj->cache_dirty); + return false; + } + /* * Stolen memory is always coherent with the GPU as it is explicitly * marked as wc by the system, or the system is cache-coherent. @@ -125,38 +108,31 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, trace_i915_gem_object_clflush(obj); clflush = NULL; - if (!(flags & I915_CLFLUSH_SYNC)) - clflush = kmalloc(sizeof(*clflush), GFP_KERNEL); + if (!(flags & I915_CLFLUSH_SYNC) && + dma_resv_reserve_fences(obj->base.resv, 1) == 0) + clflush = clflush_work_create(obj); if (clflush) { - GEM_BUG_ON(!obj->cache_dirty); - - dma_fence_init(&clflush->dma, - &i915_clflush_ops, - &clflush_lock, - to_i915(obj->base.dev)->mm.unordered_timeline, - 0); - i915_sw_fence_init(&clflush->wait, i915_clflush_notify); - - clflush->obj = i915_gem_object_get(obj); - INIT_WORK(&clflush->work, i915_clflush_work); - - dma_fence_get(&clflush->dma); - - i915_sw_fence_await_reservation(&clflush->wait, - obj->base.resv, NULL, - true, I915_FENCE_TIMEOUT, + i915_sw_fence_await_reservation(&clflush->base.chain, + obj->base.resv, NULL, true, + i915_fence_timeout(i915), I915_FENCE_GFP); - - reservation_object_add_excl_fence(obj->base.resv, - &clflush->dma); - - i915_sw_fence_commit(&clflush->wait); + dma_resv_add_fence(obj->base.resv, &clflush->base.dma, + DMA_RESV_USAGE_KERNEL); + dma_fence_work_commit(&clflush->base); + /* + * We must have successfully populated the pages(since we are + * holding a pin on the pages as per the flush worker) to reach + * this point, which must mean we have already done the required + * flush-on-acquire, hence resetting cache_dirty here should be + * safe. + */ + obj->cache_dirty = false; } else if (obj->mm.pages) { - __i915_do_clflush(obj); + __do_clflush(obj); + obj->cache_dirty = false; } else { GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); } - obj->cache_dirty = false; return true; } |