[PATCH 12/21] drm/i915: support Haswell-style force waking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Haswell, there is a different register for reading force wake ACKs, and
all the writes should go into the multi-threaded register, even for the
legacy force wake.

Also, we have a theorical possibility for the force wake sequence to
awaken the GT, but return while it hasn't finished bringing up the queue.
So we properly check those bits as well, to ensure we won't end up in
half-woken situation.

Signed-off-by: Eugeni Dodonov <eugeni.dodonov at intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 36 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_drv.h |  3 +++
 drivers/gpu/drm/i915/i915_reg.h |  1 +
 drivers/gpu/drm/i915/intel_pm.c |  4 +++-
 4 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 79be879..73fd38a 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -536,6 +536,39 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 	return ret;
 }
 
+static inline void __hsw_wait_gt_awake(struct drm_i915_private *dev_priv)
+{
+	int count = 0;
+
+	while (count++ < 50) {
+		u32 tmp = I915_READ_NOTRACE(FORCEWAKE_ACK_HSW);
+		if ((tmp & 1) && !(tmp & _MASKED_BIT_ENABLE(~7)))
+			break;
+		udelay(10);
+	}
+}
+
+
+void hsw_gt_force_wake_get(struct drm_i915_private *dev_priv)
+{
+	__hsw_wait_gt_awake(dev_priv);
+
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
+	POSTING_READ(FORCEWAKE_MT);
+
+	__hsw_wait_gt_awake(dev_priv);
+}
+
+void hsw_gt_force_wake_put(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
+
+	__hsw_wait_gt_awake(dev_priv);
+
+	/* The below doubles as a POSTING_READ */
+	gen6_gt_check_fifodbg(dev_priv);
+}
+
 void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	int count;
@@ -1161,7 +1194,8 @@ MODULE_LICENSE("GPL and additional rights");
 #define NEEDS_FORCE_WAKE(dev_priv, reg) \
 	((HAS_FORCE_WAKE((dev_priv)->dev)) && \
 	 ((reg) < 0x40000) &&            \
-	 ((reg) != FORCEWAKE))
+	 ((reg) != FORCEWAKE) &&         \
+	 ((reg) != FORCEWAKE_MT))
 
 static bool IS_DISPLAYREG(u32 reg)
 {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a0c15ab..e4916a0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1525,6 +1525,9 @@ extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
 extern void vlv_force_wake_get(struct drm_i915_private *dev_priv);
 extern void vlv_force_wake_put(struct drm_i915_private *dev_priv);
 
+extern void hsw_gt_force_wake_get(struct drm_i915_private *dev_priv);
+extern void hsw_gt_force_wake_put(struct drm_i915_private *dev_priv);
+
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 284965b..2c4be2e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4070,6 +4070,7 @@
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_VLV				0x1300b0
 #define  FORCEWAKE_ACK_VLV			0x1300b4
+#define  FORCEWAKE_ACK_HSW			0x130044
 #define  FORCEWAKE_ACK				0x130090
 #define  FORCEWAKE_MT				0xa188 /* multi-threaded */
 #define  FORCEWAKE_MT_ACK			0x130040
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 99bc1f3..0334e42 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3769,7 +3769,7 @@ void intel_init_pm(struct drm_device *dev)
 		dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
 
 		/* IVB configs may use multi-threaded forcewake */
-		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+		if (IS_IVYBRIDGE(dev)) {
 			u32	ecobus;
 
 			/* A small trick here - if the bios hasn't configured MT forcewake,
@@ -3842,6 +3842,8 @@ void intel_init_pm(struct drm_device *dev)
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
 			dev_priv->display.sanitize_pm = gen6_sanitize_pm;
+			dev_priv->display.force_wake_get = hsw_gt_force_wake_get;
+			dev_priv->display.force_wake_put = hsw_gt_force_wake_put;
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_VALLEYVIEW(dev)) {
-- 
1.7.11.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux