diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2013-07-04 09:49:01 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2013-07-04 09:49:01 +0000 |
commit | 74897b0fb7b61f8a1968bb922245a6e4ebabb9f6 (patch) | |
tree | 87dde47e671cad296dacf3726eb84efba0accd10 /sys/dev | |
parent | e1aada3a39aae8b4fc94078d06ef69a6eeed84b4 (diff) |
Workaround incoherence between fences and LLC across multiple CPUs
from linux 3.8.13
this does not currently do the ipi to run wbinvd() on all processors
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/drm/i915/i915_gem.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/sys/dev/pci/drm/i915/i915_gem.c b/sys/dev/pci/drm/i915/i915_gem.c index 4fbc43047ec..6c15b56f2d8 100644 --- a/sys/dev/pci/drm/i915/i915_gem.c +++ b/sys/dev/pci/drm/i915/i915_gem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_gem.c,v 1.25 2013/06/12 14:28:40 kettenis Exp $ */ +/* $OpenBSD: i915_gem.c,v 1.26 2013/07/04 09:49:00 jsg Exp $ */ /* * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> * @@ -1925,18 +1925,43 @@ fence_number(drm_i915_private_t *dev_priv, return fence - dev_priv->fence_regs; } +#ifdef __linux__ +void +i915_gem_write_fence__ipi(void *data) +{ + wbinvd(); +} +#endif + 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); - - i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL); + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int fence_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. + */ + if (HAS_LLC(obj->base.dev)) +#ifdef __linux__ + on_each_cpu(i915_gem_write_fence__ipi, NULL, 1); +#else + wbinvd(); +#endif + i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL); if (enable) { - obj->fence_reg = reg; + obj->fence_reg = fence_reg; fence->obj = obj; list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); } else { |