aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-07-10 08:36:24 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-10 09:31:12 -0400
commit46a0b638f35b45fc13d3dc0deb6a7e17988170b2 (patch)
treeb9adaa3d3246579aa8fd4b1d0638145bbddc3afc
parentd18b9619034230b6f945e215276425636ca401fe (diff)
Revert "drm/i915: Workaround incoherence between fences and LLC across multiple CPUs"
This reverts commit 25ff119 and the follow on for Valleyview commit 2dc8aae. commit 25ff1195f8a0b3724541ae7bbe331b4296de9c06 Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu Apr 4 21:31:03 2013 +0100 drm/i915: Workaround incoherence between fences and LLC across multiple CPUs commit 2dc8aae06d53458dd3624dc0accd4f81100ee631 Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed May 22 17:08:06 2013 +0100 drm/i915: Workaround incoherence with fence updates on Valleyview Jon Bloomfield came up with a plausible explanation and cheap fix (drm/i915: Fix incoherence with fence updates on Sandybridge+) for the race condition, so lets run with it. This is a candidate for stable as the old workaround incurs a significant cost (calling wbinvd on all CPUs before performing the register write) for some workloads as noted by Carsten Emde. Link: http://lists.freedesktop.org/archives/intel-gfx/2013-June/028819.html References: https://www.osadl.org/?id=1543#c7602 References: https://bugs.freedesktop.org/show_bug.cgi?id=63825 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jon Bloomfield <jon.bloomfield@intel.com> Cc: Carsten Emde <C.Emde@osadl.org> Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c47
1 files changed, 4 insertions, 43 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a34e8e2ba98a..06d66e09da17 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2829,56 +2829,17 @@ static inline int fence_number(struct drm_i915_private *dev_priv,
2829 return fence - dev_priv->fence_regs; 2829 return fence - dev_priv->fence_regs;
2830} 2830}
2831 2831
2832struct write_fence {
2833 struct drm_device *dev;
2834 struct drm_i915_gem_object *obj;
2835 int fence;
2836};
2837
2838static void i915_gem_write_fence__ipi(void *data)
2839{
2840 struct write_fence *args = data;
2841
2842 /* Required for SNB+ with LLC */
2843 wbinvd();
2844
2845 /* Required for VLV */
2846 i915_gem_write_fence(args->dev, args->fence, args->obj);
2847}
2848
2849static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, 2832static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
2850 struct drm_i915_fence_reg *fence, 2833 struct drm_i915_fence_reg *fence,
2851 bool enable) 2834 bool enable)
2852{ 2835{
2853 struct drm_i915_private *dev_priv = obj->base.dev->dev_private; 2836 struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
2854 struct write_fence args = { 2837 int reg = fence_number(dev_priv, fence);
2855 .dev = obj->base.dev, 2838
2856 .fence = fence_number(dev_priv, fence), 2839 i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
2857 .obj = enable ? obj : NULL,
2858 };
2859
2860 /* In order to fully serialize access to the fenced region and
2861 * the update to the fence register we need to take extreme
2862 * measures on SNB+. In theory, the write to the fence register
2863 * flushes all memory transactions before, and coupled with the
2864 * mb() placed around the register write we serialise all memory
2865 * operations with respect to the changes in the tiler. Yet, on
2866 * SNB+ we need to take a step further and emit an explicit wbinvd()
2867 * on each processor in order to manually flush all memory
2868 * transactions before updating the fence register.
2869 *
2870 * However, Valleyview complicates matter. There the wbinvd is
2871 * insufficient and unlike SNB/IVB requires the serialising
2872 * register write. (Note that that register write by itself is
2873 * conversely not sufficient for SNB+.) To compromise, we do both.
2874 */
2875 if (INTEL_INFO(args.dev)->gen >= 6)
2876 on_each_cpu(i915_gem_write_fence__ipi, &args, 1);
2877 else
2878 i915_gem_write_fence(args.dev, args.fence, args.obj);
2879 2840
2880 if (enable) { 2841 if (enable) {
2881 obj->fence_reg = args.fence; 2842 obj->fence_reg = reg;
2882 fence->obj = obj; 2843 fence->obj = obj;
2883 list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); 2844 list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
2884 } else { 2845 } else {