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

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

 



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@xxxxxxxxx>
Cc: Ben Widawsky <benjamin.widawsky@xxxxxxxxx>
---
 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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




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