From ec55f878029a8d151e7b2e8e9140ab1b407ea2db Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 18 Feb 2014 17:15:44 +0200 Subject: [PATCH] drm/i915: fix forcewake counts for gen8 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 Cc: Ben Widawsky --- 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