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> --- 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 e2c5ee6..6dc9a91 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 62c85d9..d907326 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2815,8 +2815,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; @@ -2825,7 +2826,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); @@ -2881,6 +2882,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) @@ -2895,6 +2922,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); @@ -2903,6 +2931,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); @@ -2923,7 +2953,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, @@ -3171,6 +3205,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