From 623dca70d74b3f3dd4e32c97600b461e762d0a67 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Mon, 4 Aug 2014 17:41:24 +0300 Subject: [PATCH] drm/i915: Use raw access from inside interrupt handlers Based on work by Chris Wilson. Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ drivers/gpu/drm/i915/i915_irq.c | 7 ++++++ drivers/gpu/drm/i915/intel_uncore.c | 40 ++++++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5a8dc80..5806e4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1397,6 +1397,7 @@ struct drm_i915_private { int relative_constants_mode; void __iomem *regs; + bool raw_io_mode; struct intel_uncore uncore; @@ -2731,6 +2732,10 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, struct drm_device *dev, struct intel_display_error_state *error); + +void i915_raw_io_get(struct drm_i915_private *dev_priv); +void i915_raw_io_put(struct drm_i915_private *dev_priv); + /* On SNB platform, before reading ring registers forcewake bit * must be set to prevent GT core from power down and stale values being * returned. diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 98abc22..fa289a9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1595,6 +1595,7 @@ static void snb_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 gt_iir) { + i915_raw_io_get(dev_priv); if (gt_iir & (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) @@ -1613,6 +1614,8 @@ static void snb_gt_irq_handler(struct drm_device *dev, if (gt_iir & GT_PARITY_ERROR(dev)) ivybridge_parity_error_irq_handler(dev, gt_iir); + + i915_raw_io_put(dev_priv); } static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) @@ -1636,6 +1639,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, uint32_t tmp = 0; irqreturn_t ret = IRQ_NONE; + i915_raw_io_get(dev_priv); + if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { tmp = I915_READ(GEN8_GT_IIR(0)); if (tmp) { @@ -1689,6 +1694,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, DRM_ERROR("The master control interrupt lied (GT3)!\n"); } + i915_raw_io_put(dev_priv); + return ret; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 4506cdf..3a6fcb2 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -40,6 +40,21 @@ #define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__) +void i915_raw_io_get(struct drm_i915_private *dev_priv) +{ + WARN_ON(dev_priv->raw_io_mode); + + dev_priv->raw_io_mode = true; + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); +} + +void i915_raw_io_put(struct drm_i915_private *dev_priv) +{ + WARN_ON(!dev_priv->raw_io_mode); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); + dev_priv->raw_io_mode = false; +} + static void assert_device_not_suspended(struct drm_i915_private *dev_priv) { @@ -546,6 +561,11 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) unsigned long irqflags; \ u##x val = 0; \ assert_device_not_suspended(dev_priv); \ + if (dev_priv->raw_io_mode) { \ + val = __raw_i915_read##x(dev_priv, reg); \ + trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ + return val; \ + } \ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) #define REG_READ_FOOTER \ @@ -573,7 +593,7 @@ gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ #define __gen6_read(x) \ static u##x \ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ - REG_READ_HEADER(x); \ + REG_READ_HEADER(x); \ hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ if (dev_priv->uncore.forcewake_count == 0 && \ NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ @@ -663,10 +683,14 @@ __gen4_read(64) #undef REG_READ_FOOTER #undef REG_READ_HEADER -#define REG_WRITE_HEADER \ +#define REG_WRITE_HEADER(x) \ unsigned long irqflags; \ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ assert_device_not_suspended(dev_priv); \ + if (dev_priv->raw_io_mode) { \ + __raw_i915_write##x(dev_priv, reg, val); \ + return; \ + } \ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) #define REG_WRITE_FOOTER \ @@ -675,7 +699,7 @@ __gen4_read(64) #define __gen4_write(x) \ static void \ gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ __raw_i915_write##x(dev_priv, reg, val); \ REG_WRITE_FOOTER; \ } @@ -683,7 +707,7 @@ gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace #define __gen5_write(x) \ static void \ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ ilk_dummy_write(dev_priv); \ __raw_i915_write##x(dev_priv, reg, val); \ REG_WRITE_FOOTER; \ @@ -693,7 +717,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace static void \ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ u32 __fifo_ret = 0; \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ @@ -708,7 +732,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace static void \ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ u32 __fifo_ret = 0; \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ @@ -746,7 +770,7 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg) #define __gen8_write(x) \ static void \ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) { \ if (dev_priv->uncore.forcewake_count == 0) \ @@ -769,7 +793,7 @@ static void \ chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ unsigned fwengine = 0; \ bool shadowed = is_gen8_shadowed(dev_priv, reg); \ - REG_WRITE_HEADER; \ + REG_WRITE_HEADER(x); \ if (!shadowed) { \ if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \ if (dev_priv->uncore.fw_rendercount == 0) \ -- 1.7.9.5