[Intel-gfx] [PATCH 10/10] drm/i915: move force wake support into intel_pm
Ben Widawsky
ben at bwidawsk.net
Mon Jul 2 20:41:43 CEST 2012
On Mon, 2 Jul 2012 11:51:11 -0300
Eugeni Dodonov <eugeni.dodonov at intel.com> wrote:
> This commit moves force wake support routines into intel_pm modules, and
> exports the gen6_gt_check_fifodbg routine (used in I915_READ).
>
> Signed-off-by: Eugeni Dodonov <eugeni.dodonov at intel.com>
I seem to recall Chris not liking this idea. Did I make that up?
Acked-by: Ben Widawsky <ben at bwidawsk.net>
> ---
> drivers/gpu/drm/i915/i915_drv.c | 191 ---------------------------------------
> drivers/gpu/drm/i915/intel_drv.h | 1 +
> drivers/gpu/drm/i915/intel_pm.c | 191 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 192 insertions(+), 191 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 3ac414f..c7e76e0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -433,197 +433,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
> return 1;
> }
>
> -static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
> -{
> - u32 gt_thread_status_mask;
> -
> - if (IS_HASWELL(dev_priv->dev))
> - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
> - else
> - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
> -
> - /* w/a for a sporadic read returning 0 by waiting for the GT
> - * thread to wake up.
> - */
> - if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
> - DRM_ERROR("GT thread status wait timed out\n");
> -}
> -
> -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
> -{
> - u32 forcewake_ack;
> -
> - if (IS_HASWELL(dev_priv->dev))
> - forcewake_ack = FORCEWAKE_ACK_HSW;
> - else
> - forcewake_ack = FORCEWAKE_ACK;
> -
> - 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);
> -
> - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
> - DRM_ERROR("Force wake wait timed out\n");
> -
> - __gen6_gt_wait_for_thread_c0(dev_priv);
> -}
> -
> -static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
> -{
> - u32 forcewake_ack;
> -
> - if (IS_HASWELL(dev_priv->dev))
> - forcewake_ack = FORCEWAKE_ACK_HSW;
> - else
> - forcewake_ack = FORCEWAKE_MT_ACK;
> -
> - 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_MT, _MASKED_BIT_ENABLE(1));
> -
> - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
> - DRM_ERROR("Force wake wait timed out\n");
> -
> - __gen6_gt_wait_for_thread_c0(dev_priv);
> -}
> -
> -/*
> - * Generally this is called implicitly by the register read function. However,
> - * if some sequence requires the GT to not power down then this function should
> - * be called at the beginning of the sequence followed by a call to
> - * gen6_gt_force_wake_put() at the end of the sequence.
> - */
> -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
> -{
> - unsigned long irqflags;
> -
> - spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
> - if (dev_priv->forcewake_count++ == 0)
> - dev_priv->gt.force_wake_get(dev_priv);
> - spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
> -}
> -
> -static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
> -{
> - u32 gtfifodbg;
> - gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
> - if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
> - "MMIO read or write has been dropped %x\n", gtfifodbg))
> - I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
> -}
> -
> -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);
> -}
> -
> -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 */
> - gen6_gt_check_fifodbg(dev_priv);
> -}
> -
> -/*
> - * see gen6_gt_force_wake_get()
> - */
> -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
> -{
> - unsigned long irqflags;
> -
> - spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
> - if (--dev_priv->forcewake_count == 0)
> - dev_priv->gt.force_wake_put(dev_priv);
> - spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
> -}
> -
> -int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
> -{
> - int ret = 0;
> -
> - if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
> - int loop = 500;
> - u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
> - while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
> - udelay(10);
> - fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
> - }
> - if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
> - ++ret;
> - dev_priv->gt_fifo_count = fifo;
> - }
> - dev_priv->gt_fifo_count--;
> -
> - return ret;
> -}
> -
> -static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
> -{
> - /* Already awake? */
> - if ((I915_READ(0x130094) & 0xa1) == 0xa1)
> - return;
> -
> - I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
> - POSTING_READ(FORCEWAKE_VLV);
> -
> - if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500))
> - DRM_ERROR("Force wake wait timed out\n");
> -
> - __gen6_gt_wait_for_thread_c0(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;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a741a02..6dd25e9 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -533,6 +533,7 @@ extern void intel_gpu_ips_teardown(void);
>
> extern void intel_enable_gt_powersave(struct drm_device *dev);
> extern void intel_disable_gt_powersave(struct drm_device *dev);
> +extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
>
> extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
> extern void intel_ddi_mode_set(struct drm_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 604f9bf..425e7d4 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3946,3 +3946,194 @@ void intel_init_pm(struct drm_device *dev)
> intel_init_power_wells(dev);
> }
>
> +static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
> +{
> + u32 gt_thread_status_mask;
> +
> + if (IS_HASWELL(dev_priv->dev))
> + gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW;
> + else
> + gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK;
> +
> + /* w/a for a sporadic read returning 0 by waiting for the GT
> + * thread to wake up.
> + */
> + if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500))
> + DRM_ERROR("GT thread status wait timed out\n");
> +}
> +
> +static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
> +{
> + u32 forcewake_ack;
> +
> + if (IS_HASWELL(dev_priv->dev))
> + forcewake_ack = FORCEWAKE_ACK_HSW;
> + else
> + forcewake_ack = FORCEWAKE_ACK;
> +
> + 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);
> +
> + if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
> + DRM_ERROR("Force wake wait timed out\n");
> +
> + __gen6_gt_wait_for_thread_c0(dev_priv);
> +}
> +
> +static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
> +{
> + u32 forcewake_ack;
> +
> + if (IS_HASWELL(dev_priv->dev))
> + forcewake_ack = FORCEWAKE_ACK_HSW;
> + else
> + forcewake_ack = FORCEWAKE_MT_ACK;
> +
> + 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_MT, _MASKED_BIT_ENABLE(1));
> +
> + if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
> + DRM_ERROR("Force wake wait timed out\n");
> +
> + __gen6_gt_wait_for_thread_c0(dev_priv);
> +}
> +
> +/*
> + * Generally this is called implicitly by the register read function. However,
> + * if some sequence requires the GT to not power down then this function should
> + * be called at the beginning of the sequence followed by a call to
> + * gen6_gt_force_wake_put() at the end of the sequence.
> + */
> +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
> +{
> + unsigned long irqflags;
> +
> + spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
> + if (dev_priv->forcewake_count++ == 0)
> + dev_priv->gt.force_wake_get(dev_priv);
> + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
> +}
> +
> +void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
> +{
> + u32 gtfifodbg;
> + gtfifodbg = I915_READ_NOTRACE(GTFIFODBG);
> + if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
> + "MMIO read or write has been dropped %x\n", gtfifodbg))
> + I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
> +}
> +
> +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);
> +}
> +
> +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 */
> + gen6_gt_check_fifodbg(dev_priv);
> +}
> +
> +/*
> + * see gen6_gt_force_wake_get()
> + */
> +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
> +{
> + unsigned long irqflags;
> +
> + spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
> + if (--dev_priv->forcewake_count == 0)
> + dev_priv->gt.force_wake_put(dev_priv);
> + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
> +}
> +
> +int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
> +{
> + int ret = 0;
> +
> + if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
> + int loop = 500;
> + u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
> + while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
> + udelay(10);
> + fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
> + }
> + if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
> + ++ret;
> + dev_priv->gt_fifo_count = fifo;
> + }
> + dev_priv->gt_fifo_count--;
> +
> + return ret;
> +}
> +
> +static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
> +{
> + /* Already awake? */
> + if ((I915_READ(0x130094) & 0xa1) == 0xa1)
> + return;
> +
> + I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
> + POSTING_READ(FORCEWAKE_VLV);
> +
> + if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500))
> + DRM_ERROR("Force wake wait timed out\n");
> +
> + __gen6_gt_wait_for_thread_c0(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;
> + }
> + }
> + }
> +}
> +
--
Ben Widawsky, Intel Open Source Technology Center
More information about the Intel-gfx
mailing list