diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 73 |
1 files changed, 28 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0f42a2782afc..b7b0a38acd67 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -994,68 +994,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv, | |||
994 | ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT); | 994 | ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT); |
995 | } | 995 | } |
996 | 996 | ||
997 | static bool vlv_c0_above(struct drm_i915_private *dev_priv, | ||
998 | const struct intel_rps_ei *old, | ||
999 | const struct intel_rps_ei *now, | ||
1000 | int threshold) | ||
1001 | { | ||
1002 | u64 time, c0; | ||
1003 | unsigned int mul = 100; | ||
1004 | |||
1005 | if (old->cz_clock == 0) | ||
1006 | return false; | ||
1007 | |||
1008 | if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) | ||
1009 | mul <<= 8; | ||
1010 | |||
1011 | time = now->cz_clock - old->cz_clock; | ||
1012 | time *= threshold * dev_priv->czclk_freq; | ||
1013 | |||
1014 | /* Workload can be split between render + media, e.g. SwapBuffers | ||
1015 | * being blitted in X after being rendered in mesa. To account for | ||
1016 | * this we need to combine both engines into our activity counter. | ||
1017 | */ | ||
1018 | c0 = now->render_c0 - old->render_c0; | ||
1019 | c0 += now->media_c0 - old->media_c0; | ||
1020 | c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC; | ||
1021 | |||
1022 | return c0 >= time; | ||
1023 | } | ||
1024 | |||
1025 | void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) | 997 | void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) |
1026 | { | 998 | { |
1027 | vlv_c0_read(dev_priv, &dev_priv->rps.down_ei); | 999 | memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei)); |
1028 | dev_priv->rps.up_ei = dev_priv->rps.down_ei; | ||
1029 | } | 1000 | } |
1030 | 1001 | ||
1031 | static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) | 1002 | static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) |
1032 | { | 1003 | { |
1004 | const struct intel_rps_ei *prev = &dev_priv->rps.ei; | ||
1033 | struct intel_rps_ei now; | 1005 | struct intel_rps_ei now; |
1034 | u32 events = 0; | 1006 | u32 events = 0; |
1035 | 1007 | ||
1036 | if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0) | 1008 | if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0) |
1037 | return 0; | 1009 | return 0; |
1038 | 1010 | ||
1039 | vlv_c0_read(dev_priv, &now); | 1011 | vlv_c0_read(dev_priv, &now); |
1040 | if (now.cz_clock == 0) | 1012 | if (now.cz_clock == 0) |
1041 | return 0; | 1013 | return 0; |
1042 | 1014 | ||
1043 | if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { | 1015 | if (prev->cz_clock) { |
1044 | if (!vlv_c0_above(dev_priv, | 1016 | u64 time, c0; |
1045 | &dev_priv->rps.down_ei, &now, | 1017 | unsigned int mul; |
1046 | dev_priv->rps.down_threshold)) | ||
1047 | events |= GEN6_PM_RP_DOWN_THRESHOLD; | ||
1048 | dev_priv->rps.down_ei = now; | ||
1049 | } | ||
1050 | 1018 | ||
1051 | if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { | 1019 | mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */ |
1052 | if (vlv_c0_above(dev_priv, | 1020 | if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) |
1053 | &dev_priv->rps.up_ei, &now, | 1021 | mul <<= 8; |
1054 | dev_priv->rps.up_threshold)) | 1022 | |
1055 | events |= GEN6_PM_RP_UP_THRESHOLD; | 1023 | time = now.cz_clock - prev->cz_clock; |
1056 | dev_priv->rps.up_ei = now; | 1024 | time *= dev_priv->czclk_freq; |
1025 | |||
1026 | /* Workload can be split between render + media, | ||
1027 | * e.g. SwapBuffers being blitted in X after being rendered in | ||
1028 | * mesa. To account for this we need to combine both engines | ||
1029 | * into our activity counter. | ||
1030 | */ | ||
1031 | c0 = now.render_c0 - prev->render_c0; | ||
1032 | c0 += now.media_c0 - prev->media_c0; | ||
1033 | c0 *= mul; | ||
1034 | |||
1035 | if (c0 > time * dev_priv->rps.up_threshold) | ||
1036 | events = GEN6_PM_RP_UP_THRESHOLD; | ||
1037 | else if (c0 < time * dev_priv->rps.down_threshold) | ||
1038 | events = GEN6_PM_RP_DOWN_THRESHOLD; | ||
1057 | } | 1039 | } |
1058 | 1040 | ||
1041 | dev_priv->rps.ei = now; | ||
1059 | return events; | 1042 | return events; |
1060 | } | 1043 | } |
1061 | 1044 | ||
@@ -4390,7 +4373,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) | |||
4390 | /* Let's track the enabled rps events */ | 4373 | /* Let's track the enabled rps events */ |
4391 | if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) | 4374 | if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) |
4392 | /* WaGsvRC0ResidencyMethod:vlv */ | 4375 | /* WaGsvRC0ResidencyMethod:vlv */ |
4393 | dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; | 4376 | dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; |
4394 | else | 4377 | else |
4395 | dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; | 4378 | dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; |
4396 | 4379 | ||