On Tue, Feb 21, 2017 at 06:22:02PM +0000, Chris Wilson wrote: > On Baytrail, we manually calculate busyness over the evaluation interval > to avoid issues with miscaluations with RC6 enabled. However, it turns > out that the DOWN_EI interrupt generator is completely bust - it > operates in two modes, continuous or never. Neither of which are > conducive to good behaviour. Stop unmask the DOWN_EI interrupt and just > compute everything from the UP_EI which does seem to correspond to the > desired interval. > > Fixes: 43cf3bf084ba ("drm/i915: Improved w/a for rps on Baytrail") > Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> # v4.1+ > --- > drivers/gpu/drm/i915/i915_drv.h | 2 +- > drivers/gpu/drm/i915/i915_irq.c | 28 +++++++++------------------- > drivers/gpu/drm/i915/intel_pm.c | 2 +- > 3 files changed, 11 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 4e7046df1b5e..8190ab500e03 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1359,7 +1359,7 @@ struct intel_gen6_power_mgmt { > unsigned boosts; > > /* manual wa residency calculations */ > - struct intel_rps_ei up_ei, down_ei; > + struct intel_rps_ei ei; > > /* > * Protects RPS/RC6 register access and PCU communication. > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index 57fa1bf78a85..09f6a190d363 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -1048,10 +1048,10 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv, > } > > static bool vlv_c0_above(struct drm_i915_private *dev_priv, > - const struct intel_rps_ei *old, > const struct intel_rps_ei *now, > int threshold) > { > + const struct intel_rps_ei *old = &dev_priv->rps.ei; > u64 time, c0; > unsigned int mul = 100; > > @@ -1077,8 +1077,7 @@ static bool vlv_c0_above(struct drm_i915_private *dev_priv, > > void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) > { > - vlv_c0_read(dev_priv, &dev_priv->rps.down_ei); > - dev_priv->rps.up_ei = dev_priv->rps.down_ei; > + memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei)); > } > > static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) > @@ -1086,28 +1085,19 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) > struct intel_rps_ei now; > u32 events = 0; > > - if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0) > + if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0) > return 0; > > vlv_c0_read(dev_priv, &now); > if (now.cz_clock == 0) > return 0; > > - if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { > - if (!vlv_c0_above(dev_priv, > - &dev_priv->rps.down_ei, &now, > - dev_priv->rps.down_threshold)) > - events |= GEN6_PM_RP_DOWN_THRESHOLD; > - dev_priv->rps.down_ei = now; > - } > + if (vlv_c0_above(dev_priv, &now, dev_priv->rps.up_threshold)) > + events |= GEN6_PM_RP_UP_THRESHOLD; > + else if (!vlv_c0_above(dev_priv, &now, dev_priv->rps.down_threshold)) > + events |= GEN6_PM_RP_DOWN_THRESHOLD; > > - if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { > - if (vlv_c0_above(dev_priv, > - &dev_priv->rps.up_ei, &now, > - dev_priv->rps.up_threshold)) > - events |= GEN6_PM_RP_UP_THRESHOLD; > - dev_priv->rps.up_ei = now; > - } > + dev_priv->rps.ei = now; > > return events; > } > @@ -4248,7 +4238,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) > /* Let's track the enabled rps events */ > if (IS_VALLEYVIEW(dev_priv)) > /* WaGsvRC0ResidencyMethod:vlv */ > - dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; > + dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; > else > dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; We also need to adjust gen6_rps_pm_mask() otherwise if we are at maxfreq we disable GEN6_PM_RP_UP_EI_EXPIRED and rely on GEN6_PM_RP_DOWN_EI_EXPIRED, which is not now used. -Chris -- Chris Wilson, Intel Open Source Technology Centre