Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46a0b638 authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

Revert "drm/i915: Workaround incoherence between fences and LLC across multiple CPUs"

This reverts commit 25ff1195 and the follow on for Valleyview commit 2dc8aae0.

commit 25ff1195
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 2dc8aae0
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: default avatarChris 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: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent d18b9619
Loading
Loading
Loading
Loading
+4 −43
Original line number Diff line number Diff line
@@ -2829,56 +2829,17 @@ 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_write_fence__ipi(void *data)
{
	struct write_fence *args = data;

	/* Required for SNB+ with LLC */
	wbinvd();

	/* Required for VLV */
	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;
	struct write_fence args = {
		.dev = obj->base.dev,
		.fence = fence_number(dev_priv, fence),
		.obj = enable ? obj : NULL,
	};
	int reg = fence_number(dev_priv, fence);

	/* In order to fully serialize access to the fenced region and
	 * the update to the fence register we need to take extreme
	 * measures on SNB+. In theory, the write to the fence register
	 * flushes all memory transactions before, and coupled with the
	 * mb() placed around the register write we serialise all memory
	 * operations with respect to the changes in the tiler. Yet, on
	 * SNB+ we need to take a step further and emit an explicit wbinvd()
	 * on each processor in order to manually flush all memory
	 * transactions before updating the fence register.
	 *
	 * However, Valleyview complicates matter. There the wbinvd is
	 * insufficient and unlike SNB/IVB requires the serialising
	 * register write. (Note that that register write by itself is
	 * conversely not sufficient for SNB+.) To compromise, we do both.
	 */
	if (INTEL_INFO(args.dev)->gen >= 6)
		on_each_cpu(i915_gem_write_fence__ipi, &args, 1);
	else
		i915_gem_write_fence(args.dev, args.fence, args.obj);
	i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);

	if (enable) {
		obj->fence_reg = args.fence;
		obj->fence_reg = reg;
		fence->obj = obj;
		list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
	} else {