Commit c9e0c6da authored by Chris Wilson's avatar Chris Wilson

drm/i915: Keep the forcewake timer alive for 1ms past the most recent use

Currently the timer is armed for 1ms after the first use and is killed
immediately, dropping the forcewake as early as possible. However, for
very frequent operations the forcewake dance has a large impact on
latency and keeping the timer alive until we are idle is preferred. To
achieve this, if we call intel_uncore_forcewake_get whilst the timer is
alive (repeated use), then set a flag to restart the timer on expiry
rather than drop the forcewake usage count. The timer is racy, the
consequence of the race is to expire the timer earlier than is now
desired but does not impact on correct behaviour. The offset the race
slightly, we set the active flag again on intel_uncore_forcewake_put.

The effect should be to reduce the jitter of reacquiring the fw every
1ms on a busy system. However, the cost is to keep the timer alive for
an extra 1ms on a nearly idle system. We chose to incur the jitter
previously to keep the timer off for as much as possible.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170526132209.14640-1-chris@chris-wilson.co.uk
parent ac58d2ab
...@@ -214,6 +214,9 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) ...@@ -214,6 +214,9 @@ intel_uncore_fw_release_timer(struct hrtimer *timer)
assert_rpm_device_not_suspended(dev_priv); assert_rpm_device_not_suspended(dev_priv);
if (xchg(&domain->active, false))
return HRTIMER_RESTART;
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (WARN_ON(domain->wake_count == 0)) if (WARN_ON(domain->wake_count == 0))
domain->wake_count++; domain->wake_count++;
...@@ -244,6 +247,7 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, ...@@ -244,6 +247,7 @@ static void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv,
active_domains = 0; active_domains = 0;
for_each_fw_domain(domain, dev_priv, tmp) { for_each_fw_domain(domain, dev_priv, tmp) {
smp_store_mb(domain->active, false);
if (hrtimer_cancel(&domain->timer) == 0) if (hrtimer_cancel(&domain->timer) == 0)
continue; continue;
...@@ -451,9 +455,12 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, ...@@ -451,9 +455,12 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
fw_domains &= dev_priv->uncore.fw_domains; fw_domains &= dev_priv->uncore.fw_domains;
for_each_fw_domain_masked(domain, fw_domains, dev_priv, tmp) for_each_fw_domain_masked(domain, fw_domains, dev_priv, tmp) {
if (domain->wake_count++) if (domain->wake_count++) {
fw_domains &= ~domain->mask; fw_domains &= ~domain->mask;
domain->active = true;
}
}
if (fw_domains) if (fw_domains)
dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
...@@ -518,8 +525,10 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, ...@@ -518,8 +525,10 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv,
if (WARN_ON(domain->wake_count == 0)) if (WARN_ON(domain->wake_count == 0))
continue; continue;
if (--domain->wake_count) if (--domain->wake_count) {
domain->active = true;
continue; continue;
}
fw_domain_arm_timer(domain); fw_domain_arm_timer(domain);
} }
......
...@@ -96,6 +96,7 @@ struct intel_uncore { ...@@ -96,6 +96,7 @@ struct intel_uncore {
enum forcewake_domain_id id; enum forcewake_domain_id id;
enum forcewake_domains mask; enum forcewake_domains mask;
unsigned int wake_count; unsigned int wake_count;
bool active;
struct hrtimer timer; struct hrtimer timer;
i915_reg_t reg_set; i915_reg_t reg_set;
i915_reg_t reg_ack; i915_reg_t reg_ack;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment