|
@@ -1082,68 +1082,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,
|
|
|
ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
|
|
|
}
|
|
|
|
|
|
-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)
|
|
|
-{
|
|
|
- u64 time, c0;
|
|
|
- unsigned int mul = 100;
|
|
|
-
|
|
|
- if (old->cz_clock == 0)
|
|
|
- return false;
|
|
|
-
|
|
|
- if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
|
|
- mul <<= 8;
|
|
|
-
|
|
|
- time = now->cz_clock - old->cz_clock;
|
|
|
- time *= threshold * dev_priv->czclk_freq;
|
|
|
-
|
|
|
- /* Workload can be split between render + media, e.g. SwapBuffers
|
|
|
- * being blitted in X after being rendered in mesa. To account for
|
|
|
- * this we need to combine both engines into our activity counter.
|
|
|
- */
|
|
|
- c0 = now->render_c0 - old->render_c0;
|
|
|
- c0 += now->media_c0 - old->media_c0;
|
|
|
- c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
|
|
|
-
|
|
|
- return c0 >= time;
|
|
|
-}
|
|
|
-
|
|
|
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)
|
|
|
{
|
|
|
+ const struct intel_rps_ei *prev = &dev_priv->rps.ei;
|
|
|
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 (prev->cz_clock) {
|
|
|
+ u64 time, c0;
|
|
|
+ unsigned int mul;
|
|
|
|
|
|
- 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;
|
|
|
+ mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
|
|
|
+ if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
|
|
+ mul <<= 8;
|
|
|
+
|
|
|
+ time = now.cz_clock - prev->cz_clock;
|
|
|
+ time *= dev_priv->czclk_freq;
|
|
|
+
|
|
|
+ /* Workload can be split between render + media,
|
|
|
+ * e.g. SwapBuffers being blitted in X after being rendered in
|
|
|
+ * mesa. To account for this we need to combine both engines
|
|
|
+ * into our activity counter.
|
|
|
+ */
|
|
|
+ c0 = now.render_c0 - prev->render_c0;
|
|
|
+ c0 += now.media_c0 - prev->media_c0;
|
|
|
+ c0 *= mul;
|
|
|
+
|
|
|
+ if (c0 > time * dev_priv->rps.up_threshold)
|
|
|
+ events = GEN6_PM_RP_UP_THRESHOLD;
|
|
|
+ else if (c0 < time * dev_priv->rps.down_threshold)
|
|
|
+ events = GEN6_PM_RP_DOWN_THRESHOLD;
|
|
|
}
|
|
|
|
|
|
+ dev_priv->rps.ei = now;
|
|
|
return events;
|
|
|
}
|
|
|
|
|
@@ -4283,7 +4266,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;
|
|
|
|