[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