Commit 6d88064e authored by Paulo Zanoni's avatar Paulo Zanoni Committed by Daniel Vetter

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: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent bb4cdd53
...@@ -298,6 +298,8 @@ static void gen6_force_wake_timer(unsigned long arg) ...@@ -298,6 +298,8 @@ static void gen6_force_wake_timer(unsigned long arg)
if (--dev_priv->uncore.forcewake_count == 0) if (--dev_priv->uncore.forcewake_count == 0)
dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL); dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
intel_runtime_pm_put(dev_priv);
} }
static void intel_uncore_forcewake_reset(struct drm_device *dev) static void intel_uncore_forcewake_reset(struct drm_device *dev)
...@@ -392,23 +394,29 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) ...@@ -392,23 +394,29 @@ 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) void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
{ {
unsigned long irqflags; unsigned long irqflags;
bool delayed = false;
if (!dev_priv->uncore.funcs.force_wake_put) if (!dev_priv->uncore.funcs.force_wake_put)
return; return;
/* Redirect to VLV specific routine */ /* Redirect to VLV specific routine */
if (IS_VALLEYVIEW(dev_priv->dev)) if (IS_VALLEYVIEW(dev_priv->dev)) {
return vlv_force_wake_put(dev_priv, fw_engine); vlv_force_wake_put(dev_priv, fw_engine);
goto out;
}
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (--dev_priv->uncore.forcewake_count == 0) { if (--dev_priv->uncore.forcewake_count == 0) {
dev_priv->uncore.forcewake_count++; dev_priv->uncore.forcewake_count++;
delayed = true;
mod_timer_pinned(&dev_priv->uncore.force_wake_timer, mod_timer_pinned(&dev_priv->uncore.force_wake_timer,
jiffies + 1); jiffies + 1);
} }
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
out:
if (!delayed)
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
} }
......
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