[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