diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9976bedfb273..34c084b24353 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -938,6 +938,9 @@ struct intel_gen6_power_mgmt { u8 rp0_delay; u8 hw_max; + bool rp_up_masked; + bool rp_down_masked; + int last_adj; enum { LOW_POWER, BETWEEN, HIGH_POWER } power; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 72ade87a7154..b226ae674647 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -986,6 +986,43 @@ static void notify_ring(struct drm_device *dev, i915_queue_hangcheck(dev); } +static void gen6_set_pm_mask(struct drm_i915_private *dev_priv, + u32 pm_iir, int new_delay) +{ + if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { + if (new_delay >= dev_priv->rps.max_delay) { + /* Mask UP THRESHOLD Interrupts */ + I915_WRITE(GEN6_PMINTRMSK, + I915_READ(GEN6_PMINTRMSK) | + GEN6_PM_RP_UP_THRESHOLD); + dev_priv->rps.rp_up_masked = true; + } + if (dev_priv->rps.rp_down_masked) { + /* UnMask DOWN THRESHOLD Interrupts */ + I915_WRITE(GEN6_PMINTRMSK, + I915_READ(GEN6_PMINTRMSK) & + ~GEN6_PM_RP_DOWN_THRESHOLD); + dev_priv->rps.rp_down_masked = false; + } + } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { + if (new_delay <= dev_priv->rps.min_delay) { + /* Mask DOWN THRESHOLD Interrupts */ + I915_WRITE(GEN6_PMINTRMSK, + I915_READ(GEN6_PMINTRMSK) | + GEN6_PM_RP_DOWN_THRESHOLD); + dev_priv->rps.rp_down_masked = true; + } + + if (dev_priv->rps.rp_up_masked) { + /* UnMask UP THRESHOLD Interrupts */ + I915_WRITE(GEN6_PMINTRMSK, + I915_READ(GEN6_PMINTRMSK) & + ~GEN6_PM_RP_UP_THRESHOLD); + dev_priv->rps.rp_up_masked = false; + } + } +} + static void gen6_pm_rps_work(struct work_struct *work) { drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, @@ -1043,6 +1080,8 @@ static void gen6_pm_rps_work(struct work_struct *work) */ new_delay = clamp_t(int, new_delay, dev_priv->rps.min_delay, dev_priv->rps.max_delay); + + gen6_set_pm_mask(dev_priv, pm_iir, new_delay); dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay; if (IS_VALLEYVIEW(dev_priv->dev)) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index afcb7f4d9116..4876ba56494b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3618,6 +3618,9 @@ static void valleyview_enable_rps(struct drm_device *dev) valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); + dev_priv->rps.rp_up_masked = false; + dev_priv->rps.rp_down_masked = false; + gen6_enable_rps_interrupts(dev); gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);