2013/10/9 <ville.syrjala@xxxxxxxxxxxxxxx>: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > 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@xxxxxxxxxxxxxxx> I never worked with these things before, but on a quick look it all sounds sane. Acked-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > --- > 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, ¶ms, &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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Paulo Zanoni _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx