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

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Wed Oct 9 18:18:08 CEST 2013


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>
---
 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




More information about the Intel-gfx mailing list