diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-02 11:51:02 -0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-03 22:08:46 +0200 |
commit | 990bbdadabaa51828e475eda86ee5720a4910cc3 (patch) | |
tree | 596748f31e6f00d21d59cd6c0cdcf9f08a28a219 /drivers/gpu/drm/i915/i915_drv.c | |
parent | 146937e5828ede495e11ba3a6f4a01b36b7166dc (diff) | |
download | linux-990bbdadabaa51828e475eda86ee5720a4910cc3.tar.gz linux-990bbdadabaa51828e475eda86ee5720a4910cc3.tar.bz2 linux-990bbdadabaa51828e475eda86ee5720a4910cc3.zip |
drm/i915: Group the GT routines together in both code and vtable
Tidy up the routines for interacting with the GT (in particular the
forcewake dance) which are scattered throughout the code in a single
structure.
v2: use wait_for_atomic for polling.
v3: *really* use wait_for_atomic for polling.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 101 |
1 files changed, 64 insertions, 37 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 79be8799ea6c..928b6677759d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -32,6 +32,7 @@ #include "drm.h" #include "i915_drm.h" #include "i915_drv.h" +#include "i915_trace.h" #include "intel_drv.h" #include <linux/console.h> @@ -432,36 +433,26 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) return 1; } -void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { - int count; - - count = 0; - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) - udelay(10); + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0, 500)) + DRM_ERROR("Force wake wait timed out\n"); I915_WRITE_NOTRACE(FORCEWAKE, 1); - POSTING_READ(FORCEWAKE); - count = 0; - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) - udelay(10); + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK) & 1), 500)) + DRM_ERROR("Force wake wait timed out\n"); } -void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) { - int count; - - count = 0; - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) - udelay(10); + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0, 500)) + DRM_ERROR("Force wake wait timed out\n"); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); - POSTING_READ(FORCEWAKE_MT); - count = 0; - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) - udelay(10); + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1), 500)) + DRM_ERROR("Force wake wait timed out\n"); } /* @@ -476,7 +467,7 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) spin_lock_irqsave(&dev_priv->gt_lock, irqflags); if (dev_priv->forcewake_count++ == 0) - dev_priv->display.force_wake_get(dev_priv); + dev_priv->gt.force_wake_get(dev_priv); spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); } @@ -489,14 +480,14 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); } -void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); /* The below doubles as a POSTING_READ */ gen6_gt_check_fifodbg(dev_priv); } -void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); /* The below doubles as a POSTING_READ */ @@ -512,7 +503,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) spin_lock_irqsave(&dev_priv->gt_lock, irqflags); if (--dev_priv->forcewake_count == 0) - dev_priv->display.force_wake_put(dev_priv); + dev_priv->gt.force_wake_put(dev_priv); spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); } @@ -536,12 +527,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) return ret; } -void vlv_force_wake_get(struct drm_i915_private *dev_priv) +static void vlv_force_wake_get(struct drm_i915_private *dev_priv) { - int count; - - count = 0; - /* Already awake? */ if ((I915_READ(0x130094) & 0xa1) == 0xa1) return; @@ -549,18 +536,58 @@ void vlv_force_wake_get(struct drm_i915_private *dev_priv) I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); POSTING_READ(FORCEWAKE_VLV); - count = 0; - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0) - udelay(10); + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500)) + DRM_ERROR("Force wake wait timed out\n"); } -void vlv_force_wake_put(struct drm_i915_private *dev_priv) +static void vlv_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); /* FIXME: confirm VLV behavior with Punit folks */ POSTING_READ(FORCEWAKE_VLV); } +void intel_gt_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + spin_lock_init(&dev_priv->gt_lock); + + if (IS_VALLEYVIEW(dev)) { + dev_priv->gt.force_wake_get = vlv_force_wake_get; + dev_priv->gt.force_wake_put = vlv_force_wake_put; + } else if (INTEL_INFO(dev)->gen >= 6) { + dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; + + /* IVB configs may use multi-threaded forcewake */ + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { + u32 ecobus; + + /* A small trick here - if the bios hasn't configured + * MT forcewake, and if the device is in RC6, then + * force_wake_mt_get will not wake the device and the + * ECOBUS read will return zero. Which will be + * (correctly) interpreted by the test below as MT + * forcewake being disabled. + */ + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ_NOTRACE(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + DRM_DEBUG_KMS("Using MT version of forcewake\n"); + dev_priv->gt.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->gt.force_wake_put = + __gen6_gt_force_wake_mt_put; + } + } + } +} + static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -797,9 +824,9 @@ static int gen6_do_reset(struct drm_device *dev) /* If reset with a user forcewake, try to restore, otherwise turn it off */ if (dev_priv->forcewake_count) - dev_priv->display.force_wake_get(dev_priv); + dev_priv->gt.force_wake_get(dev_priv); else - dev_priv->display.force_wake_put(dev_priv); + dev_priv->gt.force_wake_put(dev_priv); /* Restore fifo count */ dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); @@ -1248,10 +1275,10 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ unsigned long irqflags; \ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ if (dev_priv->forcewake_count == 0) \ - dev_priv->display.force_wake_get(dev_priv); \ + dev_priv->gt.force_wake_get(dev_priv); \ val = read##y(dev_priv->regs + reg); \ if (dev_priv->forcewake_count == 0) \ - dev_priv->display.force_wake_put(dev_priv); \ + dev_priv->gt.force_wake_put(dev_priv); \ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ val = read##y(dev_priv->regs + reg + 0x180000); \ |