[Intel-gfx] [PATCH 14/16] drm/i915: Add watermark tracepoints

Paulo Zanoni przanoni at gmail.com
Fri Oct 11 21:40:24 CEST 2013


2013/10/9  <ville.syrjala at linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> We may want to know what kind of watermarks got computed and programmed
> into the hardware. Using tracepoints is much leaner than debug prints.
>
> Also add trace call for the watermark state we read out of the
> hardware during init, though I;m not sure there's any way to see that
> trace as the events aren't available until the module is loaded.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

I never worked with these things before, but on a quick look it all sounds sane.

Acked-by: Paulo Zanoni <paulo.r.zanoni at intel.com>

> ---
>  drivers/gpu/drm/i915/i915_trace.h | 181 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_pm.c   |  42 ++++++++-
>  2 files changed, 220 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
> index 6e580c9..d021b4f 100644
> --- a/drivers/gpu/drm/i915/i915_trace.h
> +++ b/drivers/gpu/drm/i915/i915_trace.h
> @@ -14,6 +14,187 @@
>  #define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
>  #define TRACE_INCLUDE_FILE i915_trace
>
> +/* watermark */
> +
> +TRACE_EVENT(i915_wm_update_start,
> +           TP_PROTO(enum pipe pipe),
> +           TP_ARGS(pipe),
> +
> +           TP_STRUCT__entry(
> +                            __field(enum pipe, pipe)
> +                            ),
> +
> +           TP_fast_assign(
> +                          __entry->pipe = pipe;
> +                          ),
> +
> +           TP_printk("pipe %c", pipe_name(__entry->pipe))
> +);
> +
> +TRACE_EVENT(i915_wm_update_end,
> +           TP_PROTO(enum pipe pipe, bool changed),
> +           TP_ARGS(pipe, changed),
> +
> +           TP_STRUCT__entry(
> +                            __field(enum pipe, pipe)
> +                            __field(bool, changed)
> +                            ),
> +
> +           TP_fast_assign(
> +                          __entry->pipe = pipe;
> +                          __entry->changed = changed;
> +                          ),
> +
> +           TP_printk("pipe %c, changed=%s",
> +                     pipe_name(__entry->pipe), __entry->changed ? "yes" : "no")
> +);
> +
> +TRACE_EVENT_CONDITION(i915_wm_misc,
> +       TP_PROTO(const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(hw, trace),
> +
> +       TP_CONDITION(trace),
> +
> +       TP_STRUCT__entry(
> +               __field(bool, enable_fbc_wm)
> +               __field(enum intel_ddb_partitioning, partitioning)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->enable_fbc_wm = hw->enable_fbc_wm;
> +               __entry->partitioning = hw->partitioning;
> +               ),
> +
> +       TP_printk("fbc=%s, ddb partitioning=%s",
> +               __entry->enable_fbc_wm ? "yes" : "no",
> +               __entry->partitioning == INTEL_DDB_PART_5_6 ? "5/6" : "1/2")
> +);
> +
> +TRACE_EVENT_CONDITION(i915_wm_pipe,
> +       TP_PROTO(struct drm_device *dev, enum pipe pipe, const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(dev, pipe, hw, trace),
> +
> +       TP_CONDITION(pipe < INTEL_INFO(dev)->num_pipes && trace),
> +
> +       TP_STRUCT__entry(
> +               __field(enum pipe, pipe)
> +               __field(uint32_t, wm_pipe)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->pipe = pipe;
> +               __entry->wm_pipe = hw->wm_pipe[pipe];
> +               ),
> +
> +       TP_printk("pipe %c: pri=%u, spr=%u, cur=%u",
> +               pipe_name(__entry->pipe),
> +               (__entry->wm_pipe & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT,
> +               (__entry->wm_pipe & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT,
> +               __entry->wm_pipe & WM0_PIPE_CURSOR_MASK)
> +);
> +
> +TRACE_EVENT_CONDITION(i915_wm_linetime,
> +       TP_PROTO(struct drm_device *dev, enum pipe pipe, const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(dev, pipe, hw, trace),
> +
> +       TP_CONDITION(IS_HASWELL(dev) && pipe < INTEL_INFO(dev)->num_pipes && trace),
> +
> +       TP_STRUCT__entry(
> +               __field(enum pipe, pipe)
> +               __field(uint32_t, wm_linetime)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->pipe = pipe;
> +               __entry->wm_linetime = hw->wm_linetime[pipe];
> +               ),
> +
> +       TP_printk("pipe %c: linetime=%u, ips linetime=%u",
> +               pipe_name(__entry->pipe),
> +               __entry->wm_linetime & PIPE_WM_LINETIME_MASK,
> +               (__entry->wm_linetime & PIPE_WM_LINETIME_IPS_LINETIME_MASK) >> 16)
> +);
> +
> +
> +TRACE_EVENT_CONDITION(i915_wm_lp1_ilk,
> +       TP_PROTO(struct drm_device *dev, const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(dev, hw, trace),
> +
> +       TP_CONDITION(INTEL_INFO(dev)->gen <= 6 && trace),
> +
> +       TP_STRUCT__entry(
> +               __field(uint32_t, wm_lp)
> +               __field(uint32_t, wm_lp_spr)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->wm_lp = hw->wm_lp[0];
> +               __entry->wm_lp_spr = hw->wm_lp_spr[0];
> +               ),
> +
> +       TP_printk("LP1: en=%s, lat=%u, fbc=%u, pri=%u, cur=%u, spr=%u, spr en=%s",
> +               __entry->wm_lp & WM1_LP_SR_EN ? "yes" : "no",
> +               (__entry->wm_lp & WM1_LP_LATENCY_MASK) >> WM1_LP_LATENCY_SHIFT,
> +               (__entry->wm_lp & WM1_LP_FBC_MASK) >> WM1_LP_FBC_SHIFT,
> +               (__entry->wm_lp & WM1_LP_SR_MASK) >> WM1_LP_SR_SHIFT,
> +               __entry->wm_lp & WM1_LP_CURSOR_MASK,
> +               __entry->wm_lp_spr & ~WM1S_LP_EN,
> +               __entry->wm_lp_spr & WM1S_LP_EN ? "yes" : "no")
> +);
> +
> +TRACE_EVENT_CONDITION(i915_wm_lp_ilk,
> +       TP_PROTO(struct drm_device *dev, int lp, const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(dev, lp, hw, trace),
> +
> +       TP_CONDITION(INTEL_INFO(dev)->gen <= 6 && trace),
> +
> +       TP_STRUCT__entry(
> +               __field(int, lp)
> +               __field(uint32_t, wm_lp)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->lp = lp;
> +               __entry->wm_lp = hw->wm_lp[lp - 1];
> +               ),
> +
> +       TP_printk("LP%d: en=%s, lat=%u, fbc=%u, pri=%u, cur=%u",
> +               __entry->lp,
> +               __entry->wm_lp & WM1_LP_SR_EN ? "yes" : "no",
> +               (__entry->wm_lp & WM1_LP_LATENCY_MASK) >> WM1_LP_LATENCY_SHIFT,
> +               (__entry->wm_lp & WM1_LP_FBC_MASK) >> WM1_LP_FBC_SHIFT,
> +               (__entry->wm_lp & WM1_LP_SR_MASK) >> WM1_LP_SR_SHIFT,
> +               __entry->wm_lp & WM1_LP_CURSOR_MASK)
> +);
> +
> +TRACE_EVENT_CONDITION(i915_wm_lp_ivb,
> +       TP_PROTO(struct drm_device *dev, int lp, const struct hsw_wm_values *hw, bool trace),
> +       TP_ARGS(dev, lp, hw, trace),
> +
> +       TP_CONDITION(INTEL_INFO(dev)->gen >= 7 && trace),
> +
> +       TP_STRUCT__entry(
> +               __field(int, lp)
> +               __field(uint32_t, wm_lp)
> +               __field(uint32_t, wm_lp_spr)
> +               ),
> +
> +       TP_fast_assign(
> +               __entry->lp = lp;
> +               __entry->wm_lp = hw->wm_lp[lp - 1];
> +               __entry->wm_lp_spr = hw->wm_lp_spr[lp - 1];
> +               ),
> +
> +       TP_printk("LP%d: en=%s, lat=%u, fbc=%u, pri=%u, cur=%u, spr=%u",
> +               __entry->lp,
> +               __entry->wm_lp & WM1_LP_SR_EN ? "yes" : "no",
> +               (__entry->wm_lp & WM1_LP_LATENCY_MASK) >> WM1_LP_LATENCY_SHIFT,
> +               (__entry->wm_lp & WM1_LP_FBC_MASK) >> WM1_LP_FBC_SHIFT,
> +               (__entry->wm_lp & WM1_LP_SR_MASK) >> WM1_LP_SR_SHIFT,
> +               __entry->wm_lp & WM1_LP_CURSOR_MASK,
> +               __entry->wm_lp_spr)
> +);
> +
>  /* object tracking */
>
>  TRACE_EVENT(i915_gem_object_create,
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 0450260..022cd5b 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2834,8 +2834,9 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>  /*
>   * The spec says we shouldn't write when we don't need, because every write
>   * causes WMs to be re-evaluated, expending some power.
> + * Returns true if some watermarks were changed.
>   */
> -static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> +static bool hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                                 struct hsw_wm_values *results)
>  {
>         struct hsw_wm_values *previous = &dev_priv->wm.hw;
> @@ -2844,7 +2845,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>
>         dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
>         if (!dirty)
> -               return;
> +               return false;
>
>         if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, 0);
> @@ -2900,6 +2901,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
>
>         dev_priv->wm.hw = *results;
> +
> +       return true;
> +}
> +
> +static void ilk_wm_trace(struct drm_device *dev, bool trace)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       const struct hsw_wm_values *hw = &dev_priv->wm.hw;
> +
> +       trace_i915_wm_misc(hw, trace);
> +
> +       trace_i915_wm_pipe(dev, PIPE_A, hw, trace);
> +       trace_i915_wm_pipe(dev, PIPE_B, hw, trace);
> +       trace_i915_wm_pipe(dev, PIPE_C, hw, trace);
> +
> +       trace_i915_wm_linetime(dev, PIPE_A, hw, trace);
> +       trace_i915_wm_linetime(dev, PIPE_B, hw, trace);
> +       trace_i915_wm_linetime(dev, PIPE_C, hw, trace);
> +
> +       trace_i915_wm_lp1_ilk(dev, hw, trace);
> +       trace_i915_wm_lp_ilk(dev, 2, hw, trace);
> +       trace_i915_wm_lp_ilk(dev, 3, hw, trace);
> +
> +       trace_i915_wm_lp_ivb(dev, 1, hw, trace);
> +       trace_i915_wm_lp_ivb(dev, 2, hw, trace);
> +       trace_i915_wm_lp_ivb(dev, 3, hw, trace);
>  }
>
>  static void haswell_update_wm(struct drm_crtc *crtc)
> @@ -2914,6 +2941,7 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         struct intel_pipe_wm pipe_wm = {};
>         struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
>         struct intel_wm_config config = {};
> +       bool changed;
>
>         hsw_compute_wm_parameters(crtc, &params, &config);
>
> @@ -2922,6 +2950,8 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
>                 return;
>
> +       trace_i915_wm_update_start(intel_crtc->pipe);
> +
>         intel_crtc->wm.active = pipe_wm;
>
>         ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
> @@ -2942,7 +2972,11 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>
>         hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results);
>
> -       hsw_write_wm_values(dev_priv, &results);
> +       changed = hsw_write_wm_values(dev_priv, &results);
> +
> +       trace_i915_wm_update_end(intel_crtc->pipe, changed);
> +
> +       ilk_wm_trace(dev, changed);
>  }
>
>  static void haswell_update_sprite_wm(struct drm_plane *plane,
> @@ -3190,6 +3224,8 @@ void ilk_init_wm(struct drm_device *dev)
>
>         hw->enable_fbc_wm =
>                 !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +
> +       ilk_wm_trace(dev, true);
>  }
>
>  /**
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni



More information about the Intel-gfx mailing list