From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Chris Wilson <chris@chris-wilson.co.uk>
Cc: intel-gfx@lists.freedesktop.org, Mika Kuoppala <mika.kuoppala@intel.com>
Subject: Re: [PATCH 3/3] drm/i915: Skip pipestats for GT operations in chv/vlv irq handler
Date: Thu, 14 Sep 2017 19:02:12 +0300 [thread overview]
Message-ID: <20170914160212.GA4914@intel.com> (raw)
In-Reply-To: <20170913181846.18121-3-chris@chris-wilson.co.uk>
On Wed, Sep 13, 2017 at 07:18:46PM +0100, Chris Wilson wrote:
> When handling context-switch interrupts, we are very latency sensitive;
> every unnecessary mmio (uncached) read contributes toward a large
> decrease in request throughput. An example is gem_exec_whisper, which
> ping-pongs between the engines, where avoiding the pipe underflow
> checking reduces the runtime of the test from 29s to 22s. On the other
> hand, we are now not checking for pipe underflows at 100KHz, more or
> less reducing it to a check every pageflip (60Hz) or modeset at worst.
>
> add/remove: 0/0 grow/shrink: 1/2 up/down: 24/-40 (-16)
> function old new delta
> valleyview_pipestat_irq_ack 259 283 +24
> valleyview_irq_handler 521 517 -4
> cherryview_irq_handler 457 421 -36
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_irq.c | 123 ++++++++++++++++++++++++----------------
> 1 file changed, 73 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index e1d503b7352e..345d73bd4039 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1703,16 +1703,17 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
> }
> }
>
> -static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
> +static bool valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
> u32 iir, u32 pipe_stats[I915_MAX_PIPES])
> {
> + bool handled = false;
> int pipe;
>
> spin_lock(&dev_priv->irq_lock);
>
> if (!dev_priv->display_irqs_enabled) {
> spin_unlock(&dev_priv->irq_lock);
> - return;
> + return false;
> }
>
> for_each_pipe(dev_priv, pipe) {
> @@ -1744,8 +1745,10 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
> if (iir & iir_bit)
> mask |= dev_priv->pipestat_irq_mask[pipe];
>
> - if (!mask)
> + if (!mask) {
> + pipe_stats[pipe] = 0;
> continue;
> + }
>
> reg = PIPESTAT(pipe);
> mask |= PIPESTAT_INT_ENABLE_MASK;
> @@ -1757,8 +1760,12 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
> if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS |
> PIPESTAT_INT_STATUS_MASK))
> I915_WRITE(reg, pipe_stats[pipe]);
> +
> + handled = true;
> }
> spin_unlock(&dev_priv->irq_lock);
> +
> + return handled;
> }
>
> static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
> @@ -1836,8 +1843,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
>
> do {
> u32 iir, gt_iir, pm_iir;
> - u32 pipe_stats[I915_MAX_PIPES] = {};
> + u32 pipe_stats[I915_MAX_PIPES];
> u32 hotplug_status = 0;
> + bool has_pipe_stats;
> u32 ier = 0;
>
> gt_iir = I915_READ(GTIIR);
> @@ -1876,7 +1884,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
>
> /* Call regardless, as some status bits might not be
> * signalled in iir */
> - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
> + has_pipe_stats =
> + valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
>
> if (iir & (I915_LPE_PIPE_A_INTERRUPT |
> I915_LPE_PIPE_B_INTERRUPT))
> @@ -1901,7 +1910,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
> if (hotplug_status)
> i9xx_hpd_irq_handler(dev_priv, hotplug_status);
>
> - valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
> + if (has_pipe_stats)
> + valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
> } while (0);
>
> enable_rpm_wakeref_asserts(dev_priv);
> @@ -1914,27 +1924,14 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
> struct drm_device *dev = arg;
> struct drm_i915_private *dev_priv = to_i915(dev);
> irqreturn_t ret = IRQ_NONE;
> + u32 master_ctl;
>
> if (!intel_irqs_enabled(dev_priv))
> return IRQ_NONE;
>
> - /* IRQs are synced during runtime_suspend, we don't require a wakeref */
> - disable_rpm_wakeref_asserts(dev_priv);
> -
> + master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
> do {
> - u32 master_ctl, iir;
> - u32 gt_iir[4] = {};
> - u32 pipe_stats[I915_MAX_PIPES] = {};
> - u32 hotplug_status = 0;
> - u32 ier = 0;
> -
> - master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
> - iir = I915_READ(VLV_IIR);
> -
> - if (master_ctl == 0 && iir == 0)
> - break;
> -
> - ret = IRQ_HANDLED;
> + u32 iir;
>
> /*
> * Theory on interrupt generation, based on empirical evidence:
> @@ -1949,44 +1946,70 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
> * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL
> * bits this time around.
> */
> - I915_WRITE(GEN8_MASTER_IRQ, 0);
> - ier = I915_READ(VLV_IER);
> - I915_WRITE(VLV_IER, 0);
> + if (master_ctl & ~GEN8_MASTER_IRQ_CONTROL) {
> + u32 gt_iir[4];
>
> - gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir);
> + I915_WRITE_FW(GEN8_MASTER_IRQ, 0);
>
> - if (iir & I915_DISPLAY_PORT_INTERRUPT)
> - hotplug_status = i9xx_hpd_irq_ack(dev_priv);
> + gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir);
>
> - /* Call regardless, as some status bits might not be
> - * signalled in iir */
> - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
> + I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
> + ret = IRQ_HANDLED;
I suspect this won't work correctly. If I'm correct on how the edge
triggering works we really need to have both MASTER_IRQ_CONTROL and IER
disabled at the same time. Otherwise one can prevent the other from
generating an edge to the CPU interrupt logic.
>
> - if (iir & (I915_LPE_PIPE_A_INTERRUPT |
> - I915_LPE_PIPE_B_INTERRUPT |
> - I915_LPE_PIPE_C_INTERRUPT))
> - intel_lpe_audio_irq_handler(dev_priv);
> + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir);
> + master_ctl = 0;
> + }
>
> - /*
> - * VLV_IIR is single buffered, and reflects the level
> - * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
> - */
> - if (iir)
> - I915_WRITE(VLV_IIR, iir);
> + iir = I915_READ_FW(VLV_IIR);
> + if (iir) {
> + u32 pipe_stats[I915_MAX_PIPES];
> + u32 hotplug_status = 0;
> + bool has_pipe_stats = false;
> + u32 ier;
>
> - I915_WRITE(VLV_IER, ier);
> - I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
> - POSTING_READ(GEN8_MASTER_IRQ);
> + /*
> + * IRQs are synced during runtime_suspend,
> + * we don't require a wakeref
> + */
> + disable_rpm_wakeref_asserts(dev_priv);
>
> - gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir);
>
> - if (hotplug_status)
> - i9xx_hpd_irq_handler(dev_priv, hotplug_status);
> + ier = I915_READ_FW(VLV_IER);
> + I915_WRITE_FW(VLV_IER, 0);
>
> - valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
> - } while (0);
> + if (iir & I915_DISPLAY_PORT_INTERRUPT)
> + hotplug_status = i9xx_hpd_irq_ack(dev_priv);
>
> - enable_rpm_wakeref_asserts(dev_priv);
> + if (iir & (I915_LPE_PIPE_A_INTERRUPT |
> + I915_LPE_PIPE_B_INTERRUPT |
> + I915_LPE_PIPE_C_INTERRUPT))
> + intel_lpe_audio_irq_handler(dev_priv);
> +
> + /*
> + * Call regardless, as some status bits might not be
> + * signalled in iir.
> + */
> + has_pipe_stats =
> + valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
> +
> + /*
> + * VLV_IIR is single buffered, and reflects the level
> + * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
> + */
> + I915_WRITE_FW(VLV_IIR, iir);
> + I915_WRITE_FW(VLV_IER, ier);
> + ret = IRQ_HANDLED;
> +
> + if (hotplug_status)
> + i9xx_hpd_irq_handler(dev_priv, hotplug_status);
> +
> + if (has_pipe_stats)
> + valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
> +
> + enable_rpm_wakeref_asserts(dev_priv);
> + master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
> + }
> + } while (master_ctl & ~GEN8_MASTER_IRQ_CONTROL);
>
> return ret;
> }
> --
> 2.14.1
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2017-09-14 16:03 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-13 18:18 [PATCH 1/3] drm/i915: Trim gen8_irq_handler Chris Wilson
2017-09-13 18:18 ` [PATCH 2/3] drm/i915: Remove the extraneous irqreturn_t from gen8 sub handlers Chris Wilson
2017-09-13 18:18 ` [PATCH 3/3] drm/i915: Skip pipestats for GT operations in chv/vlv irq handler Chris Wilson
2017-09-14 16:02 ` Ville Syrjälä [this message]
2017-09-13 18:42 ` ✗ Fi.CI.BAT: warning for series starting with [1/3] drm/i915: Trim gen8_irq_handler Patchwork
2017-09-14 7:20 ` [PATCH 1/3] " Pandiyan, Dhinakaran
2017-09-14 8:37 ` Chris Wilson
2017-09-14 19:46 ` Pandiyan, Dhinakaran
2017-09-14 15:46 ` Ville Syrjälä
2017-09-14 15:54 ` Chris Wilson
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=20170914160212.GA4914@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=chris@chris-wilson.co.uk \
--cc=intel-gfx@lists.freedesktop.org \
--cc=mika.kuoppala@intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.