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

Reply via email to