public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Ben Widawsky <ben@bwidawsk.net>
To: deepak.s@linux.intel.com
Cc: intel-gfx@lists.freedesktop.org,
	Ben Widawsky <benjamin.widawsky@intel.com>
Subject: Re: [PATCH 01/10] drm/i915/bdw: Implement a basic PM interrupt handler
Date: Fri, 25 Apr 2014 14:08:17 -0700	[thread overview]
Message-ID: <20140425210816.GA4167@bwidawsk.net> (raw)
In-Reply-To: <1398067454-7581-2-git-send-email-deepak.s@linux.intel.com>

On Mon, Apr 21, 2014 at 01:34:05PM +0530, deepak.s@linux.intel.com wrote:
> From: Ben Widawsky <benjamin.widawsky@intel.com>
> 
> Almost all of it is reusable from the existing code. The primary
> difference is we need to do even less in the interrupt handler, since
> interrupts are not shared in the same way.
> 
> The patch is mostly a copy-paste of the existing snb+ code, with updates
> to the relevant parts requiring changes to the interrupt handling. As
> such it /should/ be relatively trivial. It's highly likely that I missed
> some places where I need a gen8 version of the PM interrupts, but it has
> become invisible to me by now.
> 
> This patch could probably be split into adding the new functions,
> followed by actually handling the interrupts. Since the code is
> currently disabled (and broken) I think the patch stands better by
> itself.
> 
> v2: Move the commit about not touching the ringbuffer interrupt to the
> snb_* function where it belongs (Rodrigo)
> 
> v3: Rebased on Paulo's runtime PM changes
> 
> v4: Not well validated, but rebase on
> commit 730488b2eddded4497f63f70867b1256cd9e117c
> Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Date:   Fri Mar 7 20:12:32 2014 -0300
> 
>     drm/i915: kill dev_priv->pm.regsave
> 
> v5: Rebased on latest code base. (Deepak)
> 
> v6: Remove conflict markers, Unnecessary empty line and use right
> IIR interrupt (Ville)
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> Signed-off-by: Deepak S <deepak.s@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c  | 75 ++++++++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>  drivers/gpu/drm/i915/intel_drv.h |  2 ++
>  drivers/gpu/drm/i915/intel_pm.c  | 38 ++++++++++++++++++--
>  4 files changed, 112 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 7a4d3ae..cf29668 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -248,6 +248,49 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
>  	return true;
>  }
>  
> +/**
> +  * bdw_update_pm_irq - update GT interrupt 2
> +  * @dev_priv: driver private
> +  * @interrupt_mask: mask of interrupt bits to update
> +  * @enabled_irq_mask: mask of interrupt bits to enable
> +  *
> +  * Copied from the snb function, updated with relevant register offsets
> +  */
> +static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
> +			      uint32_t interrupt_mask,
> +			      uint32_t enabled_irq_mask)
> +{
> +	uint32_t new_val;
> +
> +	assert_spin_locked(&dev_priv->irq_lock);
> +
> +	if (dev_priv->pm.irqs_disabled) {
> +		WARN(1, "IRQs disabled\n");
> +		return;
> +	}

If you end up needing to rev again:
if (WARN(dev_priv->pm.irqs_disabled, "IRQs disabled\n"))
	return;

> +
> +	new_val = dev_priv->pm_irq_mask;
> +	new_val &= ~interrupt_mask;
> +	new_val |= (~enabled_irq_mask & interrupt_mask);
> +
> +	if (new_val != dev_priv->pm_irq_mask) {
> +		dev_priv->pm_irq_mask = new_val;
> +		I915_WRITE(GEN8_GT_IMR(2), I915_READ(GEN8_GT_IMR(2)) |
> +					   dev_priv->pm_irq_mask);
> +		POSTING_READ(GEN8_GT_IMR(2));
> +	}
> +}
> +
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +	bdw_update_pm_irq(dev_priv, mask, mask);
> +}
> +
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
> +{
> +	bdw_update_pm_irq(dev_priv, mask, 0);
> +}
> +
>  static bool cpt_can_enable_serr_int(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -1126,8 +1169,12 @@ static void gen6_pm_rps_work(struct work_struct *work)
>  	spin_lock_irq(&dev_priv->irq_lock);
>  	pm_iir = dev_priv->rps.pm_iir;
>  	dev_priv->rps.pm_iir = 0;
> -	/* Make sure not to corrupt PMIMR state used by ringbuffer code */
> -	snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
> +	if (IS_BROADWELL(dev_priv->dev))
> +		bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
> +	else {
> +		/* Make sure not to corrupt PMIMR state used by ringbuffer */
> +		snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
> +	}
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
>  	/* Make sure we didn't queue anything we're not going to process. */
> @@ -1324,6 +1371,19 @@ static void snb_gt_irq_handler(struct drm_device *dev,
>  		ivybridge_parity_error_irq_handler(dev, gt_iir);
>  }
>  
> +static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
> +{
> +	if ((pm_iir & dev_priv->pm_rps_events) == 0)
> +		return;
> +
> +	spin_lock(&dev_priv->irq_lock);
> +	dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
> +	bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
> +	spin_unlock(&dev_priv->irq_lock);
> +
> +	queue_work(dev_priv->wq, &dev_priv->rps.work);
> +}
> +
>  static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>  				       struct drm_i915_private *dev_priv,
>  				       u32 master_ctl)
> @@ -1359,6 +1419,17 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
>  			DRM_ERROR("The master control interrupt lied (GT1)!\n");
>  	}
>  
> +	if (master_ctl & GEN8_GT_PM_IRQ) {
> +		tmp = I915_READ(GEN8_GT_IIR(2));
> +		if (tmp & dev_priv->pm_rps_events) {
> +			ret = IRQ_HANDLED;
> +			gen8_rps_irq_handler(dev_priv, tmp);
> +			I915_WRITE(GEN8_GT_IIR(2),
> +				   tmp & dev_priv->pm_rps_events);
> +		} else
> +			DRM_ERROR("The master control interrupt lied (PM)!\n");
> +	}
> +
>  	if (master_ctl & GEN8_GT_VECS_IRQ) {
>  		tmp = I915_READ(GEN8_GT_IIR(3));
>  		if (tmp) {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8f84555..c2dd436 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4193,6 +4193,7 @@ enum punit_power_well {
>  #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
>  #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+pipe))
>  #define  GEN8_GT_VECS_IRQ		(1<<6)
> +#define  GEN8_GT_PM_IRQ			(1<<4)
>  #define  GEN8_GT_VCS2_IRQ		(1<<3)
>  #define  GEN8_GT_VCS1_IRQ		(1<<2)
>  #define  GEN8_GT_BCS_IRQ		(1<<1)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c551472..932c042 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -650,6 +650,8 @@ void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> +void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
> +void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
>  void intel_runtime_pm_disable_interrupts(struct drm_device *dev);
>  void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 75c1c76..3dccee6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3210,6 +3210,26 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
>  	trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
>  }
>  
> +static void gen8_disable_rps_interrupts(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
> +	I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) &
> +				   ~dev_priv->pm_rps_events);
> +	/* Complete PM interrupt masking here doesn't race with the rps work
> +	 * item again unmasking PM interrupts because that is using a different
> +	 * register (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in
> +	 * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which
> +	 * gen8_enable_rps will clean up. */
> +
> +	spin_lock_irq(&dev_priv->irq_lock);
> +	dev_priv->rps.pm_iir = 0;
> +	spin_unlock_irq(&dev_priv->irq_lock);
> +
> +	I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
> +}
> +
>  static void gen6_disable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3236,7 +3256,10 @@ static void gen6_disable_rps(struct drm_device *dev)
>  	I915_WRITE(GEN6_RC_CONTROL, 0);
>  	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
>  
> -	gen6_disable_rps_interrupts(dev);
> +	if (IS_BROADWELL(dev))
> +		gen8_disable_rps_interrupts(dev);
> +	else
> +		gen6_disable_rps_interrupts(dev);
>  }
>  
>  static void valleyview_disable_rps(struct drm_device *dev)
> @@ -3276,6 +3299,17 @@ int intel_enable_rc6(const struct drm_device *dev)
>  	return INTEL_RC6_ENABLE;
>  }
>  
> +static void gen8_enable_rps_interrupts(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	spin_lock_irq(&dev_priv->irq_lock);
> +	WARN_ON(dev_priv->rps.pm_iir);
> +	bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
> +	I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
> +	spin_unlock_irq(&dev_priv->irq_lock);
> +}
> +
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3378,7 +3412,7 @@ static void gen8_enable_rps(struct drm_device *dev)
>  
>  	gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8);
>  
> -	gen6_enable_rps_interrupts(dev);
> +	gen8_enable_rps_interrupts(dev);
>  
>  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }

lgtm
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>

-- 
Ben Widawsky, Intel Open Source Technology Center

  parent reply	other threads:[~2014-04-25 21:08 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-21  8:04 [PATCH 01/10] drm/i915/bdw: Implement a basic PM interrupt handler deepak.s
2014-04-21  8:04 ` [PATCH 02/10] drm/i915: Enable PM Interrupts target via Display Interface deepak.s
2014-04-25 21:33   ` Ben Widawsky
2014-04-21  8:04 ` [PATCH 03/10] drm/i915/chv: Enable Render Standby (RC6) for Cheeryview deepak.s
2014-04-25 21:42   ` Ben Widawsky
2014-04-25 21:44     ` Ben Widawsky
2014-04-28 15:11     ` Deepak S
2014-04-28 14:29   ` Imre Deak
2014-04-28 14:45     ` Daniel Vetter
2014-04-28 15:02       ` Deepak S
2014-04-28 15:10     ` Deepak S
2014-04-21  8:04 ` [PATCH 04/10] drm/i915/chv: Added CHV specific register read and write deepak.s
2014-04-25 21:54   ` Ben Widawsky
2014-05-05  5:55     ` Deepak S
2014-04-21  8:04 ` [PATCH 05/10] drm/i915/chv: Enable RPS (Turbo) for Cheeryview deepak.s
2014-04-25 22:17   ` Ben Widawsky
2014-04-21  8:04 ` [PATCH 06/10] drm/i915/chv: Streamline CHV forcewake stuff deepak.s
2014-04-25 22:24   ` Ben Widawsky
2014-04-21  8:04 ` [PATCH 07/10] drm/i915/chv: CHV doesn't need WaRsForcewakeWaitTC0 deepak.s
2014-04-21  8:04 ` [PATCH 08/10] drm/i915/chv: Skip gen6_gt_check_fifodbg() on CHV deepak.s
2014-04-25 22:26   ` Ben Widawsky
2014-04-21  8:04 ` [PATCH 09/10] drm/i915/chv: Added CHV specific DDR fetch into init_clock_gating deepak.s
2014-04-25 22:28   ` Ben Widawsky
2014-04-21  8:04 ` [PATCH 10/10] drm/i915/chv: Freq(opcode) request value for CHV deepak.s
2014-04-25 22:32   ` Ben Widawsky
2014-04-25 21:08 ` Ben Widawsky [this message]
  -- strict thread matches above, loose matches on Subject: below --
2014-05-05 12:47 [PATCH 00/10] Enable RC6/Turbo on CHV deepak.s
2014-05-05 12:47 ` [PATCH 01/10] drm/i915/bdw: Implement a basic PM interrupt handler deepak.s
2014-05-07 13:58   ` Ville Syrjälä

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140425210816.GA4167@bwidawsk.net \
    --to=ben@bwidawsk.net \
    --cc=benjamin.widawsky@intel.com \
    --cc=deepak.s@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox