[Intel-gfx] [PATCH 1/2] drm/i915: properly lock gt_fifo_count

Daniel Vetter daniel.vetter at ffwll.ch
Sun Nov 6 01:41:35 CET 2011


Use a combination of atomic_t and a spinlocked slow-path to make most
writes fast.

v2: Properly initialize the gt_lock.

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/i915_dma.c |    1 +
 drivers/gpu/drm/i915/i915_drv.c |   28 ++++++++++++++++++++--------
 drivers/gpu/drm/i915/i915_drv.h |    8 +++++---
 3 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2eac955..ab3a3fd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2031,6 +2031,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (!IS_I945G(dev) && !IS_I945GM(dev))
 		pci_enable_msi(dev->pdev);
 
+	spin_lock_init(&dev_priv->gt_lock);
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
 	spin_lock_init(&dev_priv->rps_lock);
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




More information about the Intel-gfx mailing list