summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2014-11-19 15:30:03 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-19 15:03:17 +0100
commit3cc134e3ee09055d5a87193fc7eb0ecf4a59eaa1 (patch)
treee5d0f75d9657edf1596426d58e988195cf74663e /drivers/gpu/drm/i915/i915_irq.c
parente534770addd798e17b95372b4cd61682d1bf9296 (diff)
drm/i915: sanitize rps irq enabling
Atm we first enable the RPS interrupts then we clear any pending ones. By this we could lose an interrupt arriving after we unmasked it. This may not be a problem as the caller should handle such a race, but logic still calls for the opposite order. Also we can delay enabling the interrupts until after all the RPS initialization is ready with the following order: 1. disable left-over RPS (earlier via intel_uncore_sanitize) 2. clear any pending RPS interrupts 3. initialize RPS 4. enable RPS interrupts This also allows us to do the 2. and 4. step the same way for all platforms, so let's follow this order to simplifying things. Also make sure any queued interrupts are also cleared. v2: - rebase on the GEN9 patches where we don't support RPS yet, so we musn't enable RPS interrupts on it (Paulo) v3: - avoid enabling RPS interrupts on GEN>9 too (Paulo) - clarify the RPS init sequence in the log message (Chris) - add POSTING_READ to gen6_reset_rps_interrupts() (Paulo) - WARN if any PM_IIR bits are set in gen6_enable_rps_interrupts() (Paulo) Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 21c579e74451..56b30534176a 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -255,14 +255,26 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
snb_update_pm_irq(dev_priv, mask, 0);
}
+void gen6_reset_rps_interrupts(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t reg = gen6_pm_iir(dev_priv);
+
+ spin_lock_irq(&dev_priv->irq_lock);
+ I915_WRITE(reg, dev_priv->pm_rps_events);
+ I915_WRITE(reg, dev_priv->pm_rps_events);
+ POSTING_READ(reg);
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
void gen6_enable_rps_interrupts(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
spin_lock_irq(&dev_priv->irq_lock);
WARN_ON(dev_priv->rps.pm_iir);
+ WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events);
gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
- I915_WRITE(gen6_pm_iir(dev_priv), dev_priv->pm_rps_events);
spin_unlock_irq(&dev_priv->irq_lock);
}