[Intel-gfx] [PATCH] drm/i915: Refactor gen6_gt_force_wake_{get, put}

Dave Gordon david.s.gordon at intel.com
Fri Nov 7 19:14:11 CET 2014


This is largely for the benefit of TDR, which needs to be able to call
the forcewake functions from a context where it must not sleep. Hence
we split the forcewake {get,put} operations into inner core versions
that don't include pm {get,put} calls, and outer wrappers that do.
Callers of the existing interfaces will see no change from this, but
it will enable TDR to safely access the registers it needs to sample.

Signed-off-by: Dave Gordon <david.s.gordon at intel.com>
---
 drivers/gpu/drm/i915/intel_uncore.c |   61 ++++++++++++++++++++++++++++-------
 1 file changed, 49 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 68e722b..c2d3896 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -560,20 +560,19 @@ void intel_uncore_sanitize(struct drm_device *dev)
 }
 
 /*
- * Generally this is called implicitly by the register read function. However,
- * if some sequence requires the GT to not power down then this function should
- * be called at the beginning of the sequence followed by a call to
- * gen6_gt_force_wake_put() at the end of the sequence.
+ * Inner core of the force_wake_get operation, exposed for the
+ * benefit of special cases such as TDR. You should only use
+ * this interface if (a) you need not to sleep, and (b) you know
+ * a priori that PM issues have been handled elsewhere. All other
+ * callers should use the regular version below.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
+void gen6_gt_force_wake_get_no_pm(struct drm_i915_private *dev_priv, int fw_engine)
 {
 	unsigned long irqflags;
 
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
-	intel_runtime_pm_get(dev_priv);
-
 	/* Redirect to Gen9 specific routine */
 	if (IS_GEN9(dev_priv->dev))
 		return gen9_force_wake_get(dev_priv, fw_engine);
@@ -589,9 +588,33 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 }
 
 /*
- * see gen6_gt_force_wake_get()
+ * Generally this is called implicitly by the register read function.
+ * However, if some sequence of accesses requires the GT to not power
+ * down between accesses then this function should be called at the
+ * beginning of the sequence followed by a gen6_gt_force_wake_put() at
+ * the end of the sequence.
  */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
+{
+	/* No forcewake implies no PM either */
+	if (!dev_priv->uncore.funcs.force_wake_get)
+		return;
+
+	intel_runtime_pm_get(dev_priv);
+
+	gen6_gt_force_wake_get_no_pm(dev_priv, fw_engine);
+}
+
+/*
+ * see gen6_gt_force_wake_get_no_pm()
+ *
+ * This function returns true if the refcount would have gone to zero,
+ * but the actual forcewake_put operation has been deferred to a timed
+ * callback, and thus the caller must NOT call intel_runtime_pm_put().
+ * In all other cases (count would not have gone to zero, or it did and
+ * the hardware operation has already completed), it returns false.
+ */
+bool gen6_gt_force_wake_put_no_pm(struct drm_i915_private *dev_priv, int fw_engine)
 {
 	unsigned long irqflags;
 	bool delayed = false;
@@ -602,13 +625,13 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 	/* Redirect to Gen9 specific routine */
 	if (IS_GEN9(dev_priv->dev)) {
 		gen9_force_wake_put(dev_priv, fw_engine);
-		goto out;
+		return false;
 	}
 
 	/* Redirect to VLV specific routine */
 	if (IS_VALLEYVIEW(dev_priv->dev)) {
 		vlv_force_wake_put(dev_priv, fw_engine);
-		goto out;
+		return false;
 	}
 
 
@@ -623,7 +646,21 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 	}
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
-out:
+	return delayed;
+}
+
+/*
+ * see gen6_gt_force_wake_get()
+ */
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
+{
+	bool delayed;
+
+	/* No forcewake implies no PM either */
+	if (!dev_priv->uncore.funcs.force_wake_put)
+		return;
+
+	delayed = gen6_gt_force_wake_put_no_pm(dev_priv, fw_engine);
 	if (!delayed)
 		intel_runtime_pm_put(dev_priv);
 }
-- 
1.7.9.5




More information about the Intel-gfx mailing list