Skip to content

Commit 8cfaf0a

Browse files
icklegregkh
authored andcommitted
drm/i915: Stop using RP_DOWN_EI on Baytrail
commit 8f68d591d4765b2e1ce9d916ac7bc5583285c4ad upstream. 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. v2: Fixup gen6_rps_pm_mask() as well v3: Inline vlv_c0_above() to combine the now identical elapsed calculation for up/down and simplify the threshold testing Fixes: 43cf3bf ("drm/i915: Improved w/a for rps on Baytrail") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170309211232.28878-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170313170617.31564-1-chris@chris-wilson.co.uk (cherry picked from commit e0e8c7cb6eb68e9256de2d8cbeb481d3701c05ac) Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent cb0a2cb commit 8cfaf0a

3 files changed

Lines changed: 32 additions & 48 deletions

File tree

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ struct intel_gen6_power_mgmt {
11591159
struct intel_rps_client semaphores, mmioflips;
11601160

11611161
/* manual wa residency calculations */
1162-
struct intel_rps_ei up_ei, down_ei;
1162+
struct intel_rps_ei ei;
11631163

11641164
/*
11651165
* Protects RPS/RC6 register access and PCU communication.

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -994,68 +994,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,
994994
ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
995995
}
996996

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-
1025997
void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)
1026998
{
1027-
vlv_c0_read(dev_priv, &dev_priv->rps.down_ei);
1028-
dev_priv->rps.up_ei = dev_priv->rps.down_ei;
999+
memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));
10291000
}
10301001

10311002
static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
10321003
{
1004+
const struct intel_rps_ei *prev = &dev_priv->rps.ei;
10331005
struct intel_rps_ei now;
10341006
u32 events = 0;
10351007

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)
10371009
return 0;
10381010

10391011
vlv_c0_read(dev_priv, &now);
10401012
if (now.cz_clock == 0)
10411013
return 0;
10421014

1043-
if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
1044-
if (!vlv_c0_above(dev_priv,
1045-
&dev_priv->rps.down_ei, &now,
1046-
dev_priv->rps.down_threshold))
1047-
events |= GEN6_PM_RP_DOWN_THRESHOLD;
1048-
dev_priv->rps.down_ei = now;
1049-
}
1015+
if (prev->cz_clock) {
1016+
u64 time, c0;
1017+
unsigned int mul;
10501018

1051-
if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
1052-
if (vlv_c0_above(dev_priv,
1053-
&dev_priv->rps.up_ei, &now,
1054-
dev_priv->rps.up_threshold))
1055-
events |= GEN6_PM_RP_UP_THRESHOLD;
1056-
dev_priv->rps.up_ei = now;
1019+
mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
1020+
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
1021+
mul <<= 8;
1022+
1023+
time = now.cz_clock - prev->cz_clock;
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;
10571039
}
10581040

1041+
dev_priv->rps.ei = now;
10591042
return events;
10601043
}
10611044

@@ -4390,7 +4373,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
43904373
/* Let's track the enabled rps events */
43914374
if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
43924375
/* 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;
43944377
else
43954378
dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
43964379

drivers/gpu/drm/i915/intel_pm.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4411,8 +4411,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
44114411
{
44124412
u32 mask = 0;
44134413

4414+
/* We use UP_EI_EXPIRED interupts for both up/down in manual mode */
44144415
if (val > dev_priv->rps.min_freq_softlimit)
4415-
mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
4416+
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
44164417
if (val < dev_priv->rps.max_freq_softlimit)
44174418
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
44184419

@@ -4516,7 +4517,7 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)
45164517
{
45174518
mutex_lock(&dev_priv->rps.hw_lock);
45184519
if (dev_priv->rps.enabled) {
4519-
if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED))
4520+
if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
45204521
gen6_rps_reset_ei(dev_priv);
45214522
I915_WRITE(GEN6_PMINTRMSK,
45224523
gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));

0 commit comments

Comments
 (0)