diff --git a/packages/linux/patches/default/linux-999-drm_i915-interactive-rps-mode.patch b/packages/linux/patches/default/linux-999-drm_i915-interactive-rps-mode.patch index 3dff8206d8..543c94c7ae 100644 --- a/packages/linux/patches/default/linux-999-drm_i915-interactive-rps-mode.patch +++ b/packages/linux/patches/default/linux-999-drm_i915-interactive-rps-mode.patch @@ -1,7 +1,13 @@ -From 77a8e4fee1ad8cf7ec4a8899f76dfb9303b422f8 Mon Sep 17 00:00:00 2001 +From patchwork Thu Jul 12 08:02:24 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4] drm/i915: Interactive RPS mode From: Chris Wilson -Date: Wed, 4 Jul 2018 08:45:48 +0100 -Subject: [PATCH] drm/i915: Interactive RPS mode +X-Patchwork-Id: 10521163 +Message-Id: <20180712080224.29831-1-chris@chris-wilson.co.uk> +To: intel-gfx@lists.freedesktop.org +Date: Thu, 12 Jul 2018 09:02:24 +0100 RPS provides a feedback loop where we use the load during the previous evaluation interval to decide whether to up or down clock the GPU @@ -36,43 +42,48 @@ work back down again. (We still keep the waitboosting mechanism around just in case a dramatic change in system load requires urgent uplocking, faster than we can provide in a few evaluation intervals.) -References: https://bugs.freedesktop.org/show_bug.cgi?id=107111 -References: e9af4ea2b9e7 ("drm/i915: Avoid waitboosting on the active request") +v2: Reduce rps_set_interactive to a boolean parameter to avoid the +confusion of what if they wanted a new power mode after pinning to a +different mode (which to choose?) +v3: Only reprogram RPS while the GT is awake, it will be set when we +wake the GT, and while off warns about being used outside of rpm. +v4: Fix deferred application of interactive mode + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107111 +Fixes: e9af4ea2b9e7 ("drm/i915: Avoid waitboosting on the active request") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Radoslaw Szwichtenberg --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + - drivers/gpu/drm/i915/i915_drv.h | 6 +- - drivers/gpu/drm/i915/intel_display.c | 20 +++++++ + drivers/gpu/drm/i915/i915_drv.h | 4 ++ + drivers/gpu/drm/i915/intel_display.c | 20 ++++++ drivers/gpu/drm/i915/intel_drv.h | 2 + - drivers/gpu/drm/i915/intel_pm.c | 87 ++++++++++++++++++---------- - 5 files changed, 86 insertions(+), 30 deletions(-) + drivers/gpu/drm/i915/intel_pm.c | 91 +++++++++++++++++++--------- + 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c -index 544e5e7f011f..7d974cad1cdf 100644 +index 099f97ef2303..ac019bb927d0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2218,6 +2218,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv)); seq_printf(m, "Boosts outstanding? %d\n", atomic_read(&rps->num_waiters)); -+ seq_printf(m, "Power overrides? %d\n", READ_ONCE(rps->power_override)); ++ seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->interactive)); seq_printf(m, "Frequency requested %d\n", intel_gpu_freq(dev_priv, rps->cur_freq)); seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h -index 09ab12458244..3f9ae1095b98 100644 +index 01dd29837233..f02fbeee553f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h -@@ -783,7 +783,9 @@ struct intel_rps { - u8 down_threshold; /* Current %busy required to downclock */ +@@ -784,6 +784,8 @@ struct intel_rps { int last_adj; -- enum { LOW_POWER, BETWEEN, HIGH_POWER } power; -+ enum { LOW_POWER, BETWEEN, HIGH_POWER, AUTO_POWER } power; -+ unsigned int power_override; + enum { LOW_POWER, BETWEEN, HIGH_POWER } power; ++ unsigned int interactive; + struct mutex power_lock; bool enabled; @@ -81,13 +92,13 @@ index 09ab12458244..3f9ae1095b98 100644 extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val); extern void intel_init_pch_refclk(struct drm_i915_private *dev_priv); extern int intel_set_rps(struct drm_i915_private *dev_priv, u8 val); -+extern void intel_rps_set_power(struct drm_i915_private *dev_priv, -+ int new_power); ++extern void intel_rps_set_interactive(struct drm_i915_private *dev_priv, ++ bool state); extern bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 8f3199b06d1f..acedd9b2d54a 100644 +index 7998e70a3174..5809366ff9f0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13104,6 +13104,19 @@ intel_prepare_plane_fb(struct drm_plane *plane, @@ -102,9 +113,9 @@ index 8f3199b06d1f..acedd9b2d54a 100644 + * that are not quite steady state without resorting to forcing + * maximum clocks following a vblank miss (see do_rps_boost()). + */ -+ if (!intel_state->rps_override) { -+ intel_rps_set_power(dev_priv, HIGH_POWER); -+ intel_state->rps_override = true; ++ if (!intel_state->rps_interactive) { ++ intel_rps_set_interactive(dev_priv, true); ++ intel_state->rps_interactive = true; + } + return 0; @@ -118,29 +129,29 @@ index 8f3199b06d1f..acedd9b2d54a 100644 + to_intel_atomic_state(old_state->state); struct drm_i915_private *dev_priv = to_i915(plane->dev); -+ if (intel_state->rps_override) { -+ intel_rps_set_power(dev_priv, AUTO_POWER); -+ intel_state->rps_override = false; ++ if (intel_state->rps_interactive) { ++ intel_rps_set_interactive(dev_priv, false); ++ intel_state->rps_interactive = false; + } + /* Should only be called after a successful intel_prepare_plane_fb()! */ mutex_lock(&dev_priv->drm.struct_mutex); intel_plane_unpin_fb(to_intel_plane_state(old_state)); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index 61e715ddd0d5..86685c43e1d2 100644 +index 61e715ddd0d5..544812488821 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -482,6 +482,8 @@ struct intel_atomic_state { */ bool skip_intermediate_wm; -+ bool rps_override; ++ bool rps_interactive; + /* Gen9+ only */ struct skl_ddb_values wm_results; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c -index 53aaaa3e6886..0245a90d0fe5 100644 +index 53aaaa3e6886..01475bf3196a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6264,41 +6264,14 @@ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val) @@ -162,7 +173,8 @@ index 53aaaa3e6886..0245a90d0fe5 100644 - val > rps->cur_freq) - new_power = BETWEEN; - break; -- ++ lockdep_assert_held(&rps->power_lock); + - case BETWEEN: - if (val <= rps->efficient_freq && - val < rps->cur_freq) @@ -171,8 +183,7 @@ index 53aaaa3e6886..0245a90d0fe5 100644 - val > rps->cur_freq) - new_power = HIGH_POWER; - break; -+ lockdep_assert_held(&rps->power_lock); - +- - case HIGH_POWER: - if (val < (rps->rp1_freq + rps->rp0_freq) >> 1 && - val < rps->cur_freq) @@ -187,7 +198,7 @@ index 53aaaa3e6886..0245a90d0fe5 100644 if (new_power == rps->power) return; -@@ -6365,9 +6338,64 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) +@@ -6365,9 +6338,68 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) rps->power = new_power; rps->up_threshold = threshold_up; rps->down_threshold = threshold_down; @@ -200,7 +211,6 @@ index 53aaaa3e6886..0245a90d0fe5 100644 + + new_power = rps->power; + switch (rps->power) { -+ case AUTO_POWER: + case LOW_POWER: + if (val > rps->efficient_freq + 1 && + val > rps->cur_freq) @@ -229,22 +239,27 @@ index 53aaaa3e6886..0245a90d0fe5 100644 + new_power = HIGH_POWER; + + mutex_lock(&rps->power_lock); -+ if (!rps->power_override) -+ rps_set_power(dev_priv, new_power); ++ if (rps->interactive) ++ new_power = HIGH_POWER; ++ rps_set_power(dev_priv, new_power); + mutex_unlock(&rps->power_lock); rps->last_adj = 0; } -+void intel_rps_set_power(struct drm_i915_private *dev_priv, int power) ++void intel_rps_set_interactive(struct drm_i915_private *dev_priv, bool state) +{ + struct intel_rps *rps = &dev_priv->gt_pm.rps; + ++ if (INTEL_GEN(dev_priv) < 6) ++ return; ++ + mutex_lock(&rps->power_lock); -+ if (power != AUTO_POWER) { -+ rps->power_override++; -+ rps_set_power(dev_priv, power); ++ if (state) { ++ if (!rps->interactive++ && READ_ONCE(dev_priv->gt.awake)) ++ rps_set_power(dev_priv, HIGH_POWER); + } else { -+ rps->power_override--; ++ GEM_BUG_ON(!rps->interactive); ++ rps->interactive--; + } + mutex_unlock(&rps->power_lock); +} @@ -252,7 +267,7 @@ index 53aaaa3e6886..0245a90d0fe5 100644 static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) { struct intel_rps *rps = &dev_priv->gt_pm.rps; -@@ -9604,6 +9632,7 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) +@@ -9604,6 +9636,7 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) void intel_pm_setup(struct drm_i915_private *dev_priv) { mutex_init(&dev_priv->pcu_lock); @@ -260,6 +275,3 @@ index 53aaaa3e6886..0245a90d0fe5 100644 atomic_set(&dev_priv->gt_pm.rps.num_waiters, 0); --- -2.18.0 -