993,46 → 993,18 |
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); |
1039,22 → 1011,33 |
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; |
} |
|
4342,7 → 4325,7 |
/* Let's track the enabled rps events */ |
if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(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; |
|