[Intel-gfx] [PATCH] drm/i915: Dump watermark info in i915_display_info, v2.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Tue Oct 24 13:13:29 UTC 2017


Dumping watermark info will make it easier to debug whether
the hardware watermarks match what's calculated for intermediate
and optimal watermarks. This has made it easier to debug certain
SNB underruns, so I've extended it from a hack to something that
will print all atomic watermarks.

Changes since v1:
- Fix WM assignment compiler warning.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 155 ++++++++++++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index c65e381b85f3..f9f9550137c3 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3170,6 +3170,160 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc)
 	}
 }
 
+static void intel_watermark_info(struct seq_file *m,
+				 struct drm_i915_private *dev_priv,
+				 struct intel_crtc *crtc)
+{
+	struct intel_crtc_state *crtc_state =
+		to_intel_crtc_state(crtc->base.state);
+	int i, j;
+	const char *names[3] = {
+		"hardware",
+		"intermediate",
+		"optimal"
+	};
+
+	if (INTEL_GEN(dev_priv) >= 9) {
+		struct skl_pipe_wm *wm = &crtc_state->wm.skl.optimal;
+		struct skl_ddb_entry *entry = &crtc_state->wm.skl.ddb;
+		struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
+
+		seq_printf(m, "\tDDB allocation: start %u end %u, size %u\n",
+			   entry->start, entry->end, skl_ddb_entry_size(entry));
+		for (i = 0; i < ARRAY_SIZE(ddb->plane[crtc->pipe]); i++) {
+			entry = &ddb->plane[crtc->pipe][i];
+
+			if (!skl_ddb_entry_size(entry))
+				continue;
+
+			seq_printf(m, "\t\tplane %d%c DDB allocation: start %u end %u, size %u, ",
+				   i, pipe_name(crtc->pipe), entry->start, entry->end,
+				   skl_ddb_entry_size(entry));
+
+			entry = &ddb->y_plane[crtc->pipe][i];
+			if (!skl_ddb_entry_size(entry))
+				continue;
+
+			seq_printf(m, "\t\tplane %d%c DDB Y allocation: start %u end %u, size %u, ",
+				   i, pipe_name(crtc->pipe), entry->start, entry->end,
+				   skl_ddb_entry_size(entry));
+		}
+
+		seq_printf(m, "\tLinetime: %u\n", wm->linetime);
+
+		for (i = 0; i < ARRAY_SIZE(wm->planes); i++) {
+			struct skl_plane_wm *pwm = &wm->planes[i];
+
+			seq_printf(m, "\tplane %d%c, wm enabled: %s",
+				   i, pipe_name(crtc->pipe),
+				   enableddisabled(pwm->wm[0].plane_en));
+			if (!pwm->wm[0].plane_en)
+				continue;
+
+			seq_printf(m, "\t\tTransition wm: %s, lines %u, blocks %u",
+				   enableddisabled(pwm->trans_wm.plane_en),
+				   pwm->trans_wm.plane_res_b, pwm->trans_wm.plane_res_l);
+
+			for (j = 0; j < ARRAY_SIZE(pwm->wm); j++) {
+				if (!pwm->wm[j].plane_en)
+					break;
+
+				  seq_printf(m, "\t\tLevel[%u]: lines %u, blocks %u",
+					     j, pwm->trans_wm.plane_res_b,
+					     pwm->trans_wm.plane_res_l);
+			}
+		}
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
+		struct intel_pipe_wm *wms[3] = {
+			&crtc->wm.active.ilk,
+			&crtc_state->wm.ilk.intermediate,
+			&crtc_state->wm.ilk.optimal };
+
+		for (j = 0; j < 3; j++) {
+			struct intel_pipe_wm *wm = wms[j];
+
+			seq_printf(m, "\tDumping %s watermarks, post vbl update: %s\n",
+				   names[j], yesno(crtc_state->wm.need_postvbl_update));
+
+			for (i = 0; i < ARRAY_SIZE(wm->wm); i++) {
+				struct intel_wm_level *lvl = &wm->wm[i];
+
+				seq_printf(m, "\t\twm level[%i], enabled: %s, vals: %u, %u, %u, %u\n",
+					  i, yesno(lvl->enable), lvl->pri_val,
+					  lvl->spr_val, lvl->cur_val, lvl->fbc_val);
+			}
+
+			seq_printf(m, "\tLinetime: %u\n", wm->linetime);
+			seq_printf(m, "\tfbc wm enabled: %s, pipe: %s, sprites enabled: %s, scaled: %s\n",
+				  yesno(wm->fbc_wm_enabled), yesno(wm->pipe_enabled),
+				  yesno(wm->sprites_enabled), yesno(wm->sprites_scaled));
+		}
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		struct vlv_wm_state *wms[3] = {
+			&crtc->wm.active.vlv,
+			&crtc_state->wm.vlv.intermediate,
+			&crtc_state->wm.vlv.optimal };
+
+		for (j = 0; j < 3; j++) {
+			struct vlv_wm_state *wm = wms[j];
+
+			seq_printf(m, "\tDumping %s watermarks, CxSR: %s, num levels: %u\n",
+				   names[j], yesno(wm->cxsr), wm->num_levels);
+
+			for (i = 0; i < wm->num_levels; i++) {
+				struct g4x_pipe_wm *pwm = &wm->wm[i];
+				struct g4x_sr_wm *sr = &wm->sr[i];
+				int k;
+
+				seq_printf(m, "\tLevel %u allocations:\n", i);
+				for (k = 0; k < ARRAY_SIZE(pwm->plane); k++)
+					seq_printf(m, "\t\tPlane %u: %u\n", k, pwm->plane[k]);
+				seq_printf(m, "\t\tFBC: %u\n", pwm->fbc);
+
+				if (!wm->cxsr)
+					continue;
+
+				seq_printf(m, "\t\tSR: plane %u, cursor %u, FBC %u\n",
+					   sr->plane, sr->cursor, sr->fbc);
+			}
+		}
+	} else if (IS_G4X(dev_priv)) {
+		struct g4x_wm_state *wms[3] = {
+			&crtc->wm.active.g4x,
+			&crtc_state->wm.g4x.intermediate,
+			&crtc_state->wm.g4x.optimal };
+
+		for (j = 0; j < 3; j++) {
+			struct g4x_wm_state *wm = wms[j];
+			struct g4x_pipe_wm *pwm = &wm->wm;
+			struct g4x_sr_wm *sr = &wm->sr;
+			struct g4x_sr_wm *hpll = &wm->hpll;
+
+			seq_printf(m, "\tDumping %s watermarks, CxSR: %s, HPLL: %s, fbc: %s\n",
+				   names[j], yesno(wm->cxsr), yesno(wm->hpll_en),
+				   yesno(wm->fbc_en));
+
+			for (i = 0; i < ARRAY_SIZE(pwm->plane); i++)
+				seq_printf(m, "\t\tPlane %u: %u\n", i, pwm->plane[i]);
+
+			if (wm->fbc_en)
+				seq_printf(m, "\t\tFBC: %u\n", pwm->fbc);
+
+			if (wm->cxsr)
+				seq_printf(m, "\t\tSR: plane %u, cursor %u, FBC %u\n",
+					   sr->plane, sr->cursor, sr->fbc);
+
+			if (wm->hpll_en)
+				seq_printf(m, "\t\tHPLL: plane %u, cursor %u, FBC %u\n",
+					   hpll->plane, hpll->cursor, hpll->fbc);
+		}
+	}
+
+	if (dev_priv->display.optimize_watermarks)
+		seq_printf(m, "\tNeed post vblank update: %s\n",
+			   yesno(crtc_state->wm.need_postvbl_update));
+}
+
 static int i915_display_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -3208,6 +3362,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
 				   cursor->cursor.base);
 			intel_scaler_info(m, crtc);
 			intel_plane_info(m, crtc);
+			intel_watermark_info(m, dev_priv, crtc);
 		}
 
 		seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
-- 
2.14.1



More information about the Intel-gfx mailing list