[Intel-gfx] [PATCH] drm/i915: fix forcewake counts for gen8

Mika Kuoppala mika.kuoppala at linux.intel.com
Tue Feb 18 16:48:54 CET 2014


Generic driver code gets forcewake explicitly by gen6_gt_force_wake_get(),
which keeps force wake counts before accessing low level fw get.
However the underlying gen8 register write function access low level
accessors directly. This leads to nested fw get from hardware, causing
forcewake ack clear errors and/or hangs.

Fix this by checking the forcewake count in gen8 accessors.
Also implement read accessors for gen8 to gain symmetry for
shadowed register access.

References: https://bugs.freedesktop.org/show_bug.cgi?id=74007
Signed-off-by: Mika Kuoppala <mika.kuoppala at intel.com>
Cc: Ben Widawsky <benjamin.widawsky at intel.com>
---
 drivers/gpu/drm/i915/intel_uncore.c |   74 +++++++++++++++++++++++------------
 1 file changed, 49 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index c628414..089feaa 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -498,6 +498,45 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
 	REG_READ_FOOTER; \
 }
 
+static const u32 gen8_shadowed_regs[] = {
+	FORCEWAKE_MT,
+	GEN6_RPNSWREQ,
+	GEN6_RC_VIDEO_FREQ,
+	RING_TAIL(RENDER_RING_BASE),
+	RING_TAIL(GEN6_BSD_RING_BASE),
+	RING_TAIL(VEBOX_RING_BASE),
+	RING_TAIL(BLT_RING_BASE),
+	/* TODO: Other registers are not yet used */
+};
+
+static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
+		if (reg == gen8_shadowed_regs[i])
+			return true;
+
+	return false;
+}
+
+#define __gen8_read(x) \
+static u##x \
+gen8_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+	bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
+	REG_READ_HEADER(x); \
+	__needs_put &= dev_priv->uncore.forcewake_count == 0; \
+	if (__needs_put) { \
+		dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+							FORCEWAKE_ALL); \
+	} \
+	val = __raw_i915_read##x(dev_priv, reg); \
+	if (__needs_put) { \
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+							FORCEWAKE_ALL); \
+	} \
+	REG_READ_FOOTER; \
+}
+
 #define __vlv_read(x) \
 static u##x \
 vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
@@ -531,6 +570,10 @@ __vlv_read(8)
 __vlv_read(16)
 __vlv_read(32)
 __vlv_read(64)
+__gen8_read(8)
+__gen8_read(16)
+__gen8_read(32)
+__gen8_read(64)
 __gen6_read(8)
 __gen6_read(16)
 __gen6_read(32)
@@ -545,6 +588,7 @@ __gen4_read(32)
 __gen4_read(64)
 
 #undef __vlv_read
+#undef __gen8_read
 #undef __gen6_read
 #undef __gen5_read
 #undef __gen4_read
@@ -610,32 +654,12 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
 	REG_WRITE_FOOTER; \
 }
 
-static const u32 gen8_shadowed_regs[] = {
-	FORCEWAKE_MT,
-	GEN6_RPNSWREQ,
-	GEN6_RC_VIDEO_FREQ,
-	RING_TAIL(RENDER_RING_BASE),
-	RING_TAIL(GEN6_BSD_RING_BASE),
-	RING_TAIL(VEBOX_RING_BASE),
-	RING_TAIL(BLT_RING_BASE),
-	/* TODO: Other registers are not yet used */
-};
-
-static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
-		if (reg == gen8_shadowed_regs[i])
-			return true;
-
-	return false;
-}
-
 #define __gen8_write(x) \
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
 	bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
 	REG_WRITE_HEADER; \
+	__needs_put &= dev_priv->uncore.forcewake_count == 0; \
 	if (__needs_put) { \
 		dev_priv->uncore.funcs.force_wake_get(dev_priv, \
 							FORCEWAKE_ALL); \
@@ -734,10 +758,10 @@ void intel_uncore_init(struct drm_device *dev)
 		dev_priv->uncore.funcs.mmio_writew  = gen8_write16;
 		dev_priv->uncore.funcs.mmio_writel  = gen8_write32;
 		dev_priv->uncore.funcs.mmio_writeq  = gen8_write64;
-		dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-		dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-		dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-		dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+		dev_priv->uncore.funcs.mmio_readb  = gen8_read8;
+		dev_priv->uncore.funcs.mmio_readw  = gen8_read16;
+		dev_priv->uncore.funcs.mmio_readl  = gen8_read32;
+		dev_priv->uncore.funcs.mmio_readq  = gen8_read64;
 		break;
 	case 7:
 	case 6:
-- 
1.7.9.5




More information about the Intel-gfx mailing list