summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2014-02-21 17:58:29 -0300
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-03-05 21:30:15 +0100
commit6d88064edcfc5e5893371f7c06b9f3078dc1edf6 (patch)
treee41c7c1f70fa8769359f2cae7f105c94c71fa382
parentbb4cdd5345bf344d978e18835583641f2c156ce5 (diff)
downloadblackbird-op-linux-6d88064edcfc5e5893371f7c06b9f3078dc1edf6.tar.gz
blackbird-op-linux-6d88064edcfc5e5893371f7c06b9f3078dc1edf6.zip
drm/i915: put runtime PM only when we actually release force_wake
When we call gen6_gt_force_wake_put we don't actually put force_wake, we just schedule gen6_force_wake_work through mod_delayed_work, and that will eventually release force_wake. The problem is that we call intel_runtime_pm_put directly at gen6_gt_force_wake_put, so most of the times we put our runtime PM reference before the delayed work happens, so we may runtime suspend while force_wake is still supposed to be enabled if the graphics autosuspend_delay_ms is too small. Now the nice thing about the current code is that after it triggers the delayed work function it gets a refcount, and it only triggers the delayed work function if refcount is zero. This guarantees that when we schedule the funciton, it will run before we try to schedule it again, which simplifies the problem and allows for the current solution to work properly (hopefully!). v2: - Keep the VLV refcounts balanced (Jesse) Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index e5b59ac5151a..4c39e241c98e 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -298,6 +298,8 @@ static void gen6_force_wake_timer(unsigned long arg)
if (--dev_priv->uncore.forcewake_count == 0)
dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+ intel_runtime_pm_put(dev_priv);
}
static void intel_uncore_forcewake_reset(struct drm_device *dev)
@@ -392,24 +394,30 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
{
unsigned long irqflags;
+ bool delayed = false;
if (!dev_priv->uncore.funcs.force_wake_put)
return;
/* Redirect to VLV specific routine */
- if (IS_VALLEYVIEW(dev_priv->dev))
- return vlv_force_wake_put(dev_priv, fw_engine);
+ if (IS_VALLEYVIEW(dev_priv->dev)) {
+ vlv_force_wake_put(dev_priv, fw_engine);
+ goto out;
+ }
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (--dev_priv->uncore.forcewake_count == 0) {
dev_priv->uncore.forcewake_count++;
+ delayed = true;
mod_timer_pinned(&dev_priv->uncore.force_wake_timer,
jiffies + 1);
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
- intel_runtime_pm_put(dev_priv);
+out:
+ if (!delayed)
+ intel_runtime_pm_put(dev_priv);
}
/* We give fast paths for the really cool registers */
OpenPOWER on IntegriCloud