From 941604761e7bc23b3182ec84889058b17283d843 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Mar 2013 15:18:16 +0000 Subject: [PATCH] drm/i915: Workaround incoherence between fences and LLC across multiple CPUs Elephant, elephant, elephant. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=62191 Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 19fc21b..33b38bd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -47,8 +47,8 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_i915_gem_pwrite *args, struct drm_file *file); -static void i915_gem_write_fence(struct drm_device *dev, int reg, - struct drm_i915_gem_object *obj); +static void __i915_gem_write_fence(struct drm_device *dev, int reg, + struct drm_i915_gem_object *obj); static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, struct drm_i915_fence_reg *fence, bool enable); @@ -2129,7 +2129,7 @@ static void i915_gem_reset_fences(struct drm_device *dev) for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; - i915_gem_write_fence(dev, i, NULL); + __i915_gem_write_fence(dev, i, NULL); if (reg->obj) i915_gem_object_fence_lost(reg->obj); @@ -2650,8 +2650,8 @@ inline static bool i915_gem_object_needs_mb(struct drm_i915_gem_object *obj) return obj && obj->base.read_domains & I915_GEM_DOMAIN_GTT; } -static void i915_gem_write_fence(struct drm_device *dev, int reg, - struct drm_i915_gem_object *obj) +static void __i915_gem_write_fence(struct drm_device *dev, int reg, + struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2684,17 +2684,35 @@ static inline int fence_number(struct drm_i915_private *dev_priv, return fence - dev_priv->fence_regs; } +struct write_fence { + struct drm_device *dev; + struct drm_i915_gem_object *obj; + int fence; +}; + +static void i915_gem_object_write_fence(void *data) +{ + struct write_fence *args = data; + __i915_gem_write_fence(args->dev, args->fence, args->obj); +} + static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, struct drm_i915_fence_reg *fence, bool enable) { struct drm_i915_private *dev_priv = obj->base.dev->dev_private; - int reg = fence_number(dev_priv, fence); + struct write_fence args = { + .dev = obj->base.dev, + .fence = fence_number(dev_priv, fence), + .obj = enable ? obj : NULL, + }; - i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL); + if (!HAS_LLC(obj->base.dev) || + on_each_cpu(i915_gem_object_write_fence, &args, 1) != 0) + i915_gem_object_write_fence(&args); if (enable) { - obj->fence_reg = reg; + obj->fence_reg = args.fence; fence->obj = obj; list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); } else { -- 1.7.10.4