[Intel-gfx] [PATCH] drm/i915: Always unsuppress down-interrupts when programming a non-min value

Chris Wilson chris at chris-wilson.co.uk
Wed Apr 25 21:22:03 CEST 2012


The GT power programing guide recommends always unsuppressing the down
interrupt when programming any render frequency above the minimum. This
is because the GT unit doesn't emit interrupts whilst it is asleep which
can lead to the down interrupt being lost. Also due to our own
coalescing of interrupts through use of a bottom-half, it looks safer to
always rewrite the limits.

Also note that in the original code we never wrote the Pn value to
suppress down interrupts as the new_delay would never be decremented
past min_delay. Further confusion abounds.

References: https://bugs.freedesktop.org/show_bug.cgi?id=44006
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Jesse Barnes <jbarnes at virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |   31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 13d40a1..274527f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -384,6 +384,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 						    rps_work);
 	u8 new_delay = dev_priv->cur_delay;
 	u32 pm_iir, pm_imr;
+	u32 limits;
 
 	spin_lock_irq(&dev_priv->rps_lock);
 	pm_iir = dev_priv->pm_iir;
@@ -392,36 +393,36 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	I915_WRITE(GEN6_PMIMR, 0);
 	spin_unlock_irq(&dev_priv->rps_lock);
 
-	if (!pm_iir)
+	if ((pm_iir & GEN6_PM_DEFERRED_EVENTS) == 0)
 		return;
 
 	mutex_lock(&dev_priv->dev->struct_mutex);
+
+	gen6_gt_force_wake_get(dev_priv);
+	limits = I915_READ(GEN6_RP_INTERRUPT_LIMITS);
+
+	/* Make sure we continue to get down interrupts
+	 * until we hit the minimum frequency */
+	limits &= ~(0x3f << 16);
+
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
-		if (dev_priv->cur_delay != dev_priv->max_delay)
-			new_delay = dev_priv->cur_delay + 1;
+		new_delay = dev_priv->cur_delay + 1;
 		if (new_delay > dev_priv->max_delay)
 			new_delay = dev_priv->max_delay;
 	} else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) {
-		gen6_gt_force_wake_get(dev_priv);
-		if (dev_priv->cur_delay != dev_priv->min_delay)
-			new_delay = dev_priv->cur_delay - 1;
+		new_delay = dev_priv->cur_delay - 1;
 		if (new_delay < dev_priv->min_delay) {
 			new_delay = dev_priv->min_delay;
-			I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-				   I915_READ(GEN6_RP_INTERRUPT_LIMITS) |
-				   ((new_delay << 16) & 0x3f0000));
-		} else {
-			/* Make sure we continue to get down interrupts
-			 * until we hit the minimum frequency */
-			I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-				   I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000);
+			limits |= (new_delay & 0x3f) << 16;
 		}
-		gen6_gt_force_wake_put(dev_priv);
 	}
 
 	gen6_set_rps(dev_priv->dev, new_delay);
 	dev_priv->cur_delay = new_delay;
 
+	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+	gen6_gt_force_wake_put(dev_priv);
+
 	/*
 	 * rps_lock not held here because clearing is non-destructive. There is
 	 * an *extremely* unlikely race with gen6_rps_enable() that is prevented
-- 
1.7.10




More information about the Intel-gfx mailing list