Use a combination of atomic_t and a spinlocked slow-path to make most writes fast.
Signed-Off-by: Daniel Vetter <daniel.vet...@ffwll.ch> --- drivers/gpu/drm/i915/i915_drv.c | 28 ++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 8 +++++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 548e04b..cefc3b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -377,17 +377,29 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) { - if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { - int loop = 500; - u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); - while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { - udelay(10); + unsigned long irqflags; + int loop; + u32 fifo; + + if (atomic_sub_return(1, &dev_priv->gt_fifo_count) + < GT_FIFO_NUM_RESERVED_ENTRIES) { + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + /* Check whether we've raced with somebody else reading the fifo + * counter for the hw. */ + if (atomic_sub_return(1, &dev_priv->gt_fifo_count) + < GT_FIFO_FREE_ENTRIES) { + loop = 500; fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { + udelay(10); + fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + } + WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES); + fifo = fifo ? fifo - 1 : 0; /* prevent underflow */ + atomic_set(&dev_priv->gt_fifo_count, fifo); } - WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES); - dev_priv->gt_fifo_count = fifo; + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); } - dev_priv->gt_fifo_count--; } static int i915_drm_freeze(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bd98fb3..74cf78e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -276,7 +276,11 @@ typedef struct drm_i915_private { int relative_constants_mode; void __iomem *regs; - u32 gt_fifo_count; + /** Concurrent writes to gt_fifo_count are protected by gt_lock */ + atomic_t gt_fifo_count; + atomic_t forcewake_count; + /** gt_lock is taking in irq contexts. */ + struct spinlock gt_lock; struct intel_gmbus { struct i2c_adapter adapter; @@ -725,8 +729,6 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - - atomic_t forcewake_count; } drm_i915_private_t; enum i915_cache_level { -- 1.7.6.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx