All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] drm/i915: More HSW watermark prep work v2
@ 2013-10-09 16:17 ville.syrjala
  2013-10-09 16:17 ` [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute ville.syrjala
                   ` (15 more replies)
  0 siblings, 16 replies; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

Here are the remaning patches from the last watermark series.

I did a few changes to the first one which caused some ripples
throughout the series. I also spotted a small future proofing opportunity 
in patch 13, and I added a few function rename patches to the end.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
@ 2013-10-09 16:17 ` ville.syrjala
  2013-10-10 21:43   ` Paulo Zanoni
  2013-10-09 16:17 ` [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe ville.syrjala
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Introduce a new struct intel_pipe_wm which contains all the
watermarks for a single pipe. Use it to unify the LP0 and LP1+
watermark computations so that we can just iterate through the
watermark levels neatly and call ilk_compute_wm_level() for each.

Also add another tool ilk_wm_merge() that merges the LP1+ watermarks
from all pipes. For that, embed one intel_pipe_wm inside intel_crtc that
contains the currently valid watermarks for each pipe.

This is mainly preparatory work for pre-computing the watermarks for
each pipe and merging them at a later time. For now the merging still
happens immediately.

v2: Add some comments about level 0 DDB split and intel_wm_config
    Add WARN_ON for level 0 being disabled
    s/lp_wm/merged

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h |  12 +++
 drivers/gpu/drm/i915/intel_pm.c  | 192 +++++++++++++++++++++++----------------
 2 files changed, 128 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 71cfabd..3325b0b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -309,6 +309,12 @@ struct intel_crtc_config {
 	bool double_wide;
 };
 
+struct intel_pipe_wm {
+	struct intel_wm_level wm[5];
+	uint32_t linetime;
+	bool fbc_wm_enabled;
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -349,6 +355,12 @@ struct intel_crtc {
 	/* Access to these should be protected by dev_priv->irq_lock. */
 	bool cpu_fifo_underrun_disabled;
 	bool pch_fifo_underrun_disabled;
+
+	/* per-pipe watermark state */
+	struct {
+		/* watermarks currently being used  */
+		struct intel_pipe_wm active;
+	} wm;
 };
 
 struct intel_plane_wm_parameters {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5e743ec..30b380c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2458,53 +2458,6 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
 	result->enable = true;
 }
 
-static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
-			      int level, const struct hsw_wm_maximums *max,
-			      const struct hsw_pipe_wm_parameters *params,
-			      struct intel_wm_level *result)
-{
-	enum pipe pipe;
-	struct intel_wm_level res[3];
-
-	for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
-		ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
-
-	result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
-	result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
-	result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
-	result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
-	result->enable = true;
-
-	return ilk_check_wm(level, max, result);
-}
-
-
-static uint32_t hsw_compute_wm_pipe(struct drm_device *dev,
-				    const struct hsw_pipe_wm_parameters *params)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_wm_config config = {
-		.num_pipes_active = 1,
-		.sprites_enabled = params->spr.enabled,
-		.sprites_scaled = params->spr.scaled,
-	};
-	struct hsw_wm_maximums max;
-	struct intel_wm_level res;
-
-	if (!params->active)
-		return 0;
-
-	ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
-	ilk_compute_wm_level(dev_priv, 0, params, &res);
-
-	ilk_check_wm(0, &max, &res);
-
-	return (res.pri_val << WM0_PIPE_PLANE_SHIFT) |
-	       (res.spr_val << WM0_PIPE_SPRITE_SHIFT) |
-	       res.cur_val;
-}
-
 static uint32_t
 hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
 {
@@ -2687,44 +2640,123 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		*lp_max_5_6 = *lp_max_1_2;
 }
 
+/* Compute new watermarks for the pipe */
+static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
+				  const struct hsw_pipe_wm_parameters *params,
+				  struct intel_pipe_wm *pipe_wm)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int level, max_level = ilk_wm_max_level(dev);
+	/* LP0 watermark maximums depend on this pipe alone */
+	struct intel_wm_config config = {
+		.num_pipes_active = 1,
+		.sprites_enabled = params->spr.enabled,
+		.sprites_scaled = params->spr.scaled,
+	};
+	struct hsw_wm_maximums max;
+
+	memset(pipe_wm, 0, sizeof(*pipe_wm));
+
+	/* LP0 watermarks always use 1/2 DDB partitioning */
+	ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
+	for (level = 0; level <= max_level; level++)
+		ilk_compute_wm_level(dev_priv, level, params,
+				     &pipe_wm->wm[level]);
+
+	pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+
+	/* At least LP0 must be valid */
+	return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
+}
+
+/*
+ * Merge the watermarks from all active pipes for a specific level.
+ */
+static void ilk_merge_wm_level(struct drm_device *dev,
+			       int level,
+			       struct intel_wm_level *ret_wm)
+{
+	const struct intel_crtc *intel_crtc;
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		const struct intel_wm_level *wm =
+			&intel_crtc->wm.active.wm[level];
+
+		if (!wm->enable)
+			return;
+
+		ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
+		ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
+		ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
+		ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
+	}
+
+	ret_wm->enable = true;
+}
+
+/*
+ * Merge all low power watermarks for all active pipes.
+ */
+static void ilk_wm_merge(struct drm_device *dev,
+			 const struct hsw_wm_maximums *max,
+			 struct intel_pipe_wm *merged)
+{
+	int level, max_level = ilk_wm_max_level(dev);
+
+	merged->fbc_wm_enabled = true;
+
+	/* merge each WM1+ level */
+	for (level = 1; level <= max_level; level++) {
+		struct intel_wm_level *wm = &merged->wm[level];
+
+		ilk_merge_wm_level(dev, level, wm);
+
+		if (!ilk_check_wm(level, max, wm))
+			break;
+
+		/*
+		 * The spec says it is preferred to disable
+		 * FBC WMs instead of disabling a WM level.
+		 */
+		if (wm->fbc_val > max->fbc) {
+			merged->fbc_wm_enabled = false;
+			wm->fbc_val = 0;
+		}
+	}
+}
+
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   const struct hsw_pipe_wm_parameters *params,
 				   const struct hsw_wm_maximums *lp_maximums,
 				   struct hsw_wm_values *results)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct intel_wm_level lp_results[4] = {};
-	enum pipe pipe;
-	int level, max_level, wm_lp;
+	struct intel_crtc *intel_crtc;
+	int level, wm_lp;
+	struct intel_pipe_wm merged = {};
 
-	for (level = 1; level <= 4; level++)
-		if (!hsw_compute_lp_wm(dev_priv, level,
-				       lp_maximums, params,
-				       &lp_results[level - 1]))
-			break;
-	max_level = level - 1;
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
+		intel_compute_pipe_wm(&intel_crtc->base,
+				      &params[intel_crtc->pipe],
+				      &intel_crtc->wm.active);
+
+	ilk_wm_merge(dev, lp_maximums, &merged);
 
 	memset(results, 0, sizeof(*results));
 
-	/* The spec says it is preferred to disable FBC WMs instead of disabling
-	 * a WM level. */
-	results->enable_fbc_wm = true;
-	for (level = 1; level <= max_level; level++) {
-		if (lp_results[level - 1].fbc_val > lp_maximums->fbc) {
-			results->enable_fbc_wm = false;
-			lp_results[level - 1].fbc_val = 0;
-		}
-	}
+	results->enable_fbc_wm = merged.fbc_wm_enabled;
 
+	/* LP1+ register values */
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
 		const struct intel_wm_level *r;
 
-		level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
-		if (level > max_level)
+		level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
+
+		r = &merged.wm[level];
+		if (!r->enable)
 			break;
 
-		r = &lp_results[level - 1];
 		results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
 							  r->fbc_val,
 							  r->pri_val,
@@ -2732,13 +2764,21 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 		results->wm_lp_spr[wm_lp - 1] = r->spr_val;
 	}
 
-	for_each_pipe(pipe)
-		results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev,
-							     &params[pipe]);
+	/* LP0 register values */
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		enum pipe pipe = intel_crtc->pipe;
+		const struct intel_wm_level *r =
+			&intel_crtc->wm.active.wm[0];
 
-	for_each_pipe(pipe) {
-		crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-		results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
+		if (WARN_ON(!r->enable))
+			continue;
+
+		results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
+
+		results->wm_pipe[pipe] =
+			(r->pri_val << WM0_PIPE_PLANE_SHIFT) |
+			(r->spr_val << WM0_PIPE_SPRITE_SHIFT) |
+			r->cur_val;
 	}
 }
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
  2013-10-09 16:17 ` [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute ville.syrjala
@ 2013-10-09 16:17 ` ville.syrjala
  2013-10-10 21:57   ` Paulo Zanoni
  2013-10-09 16:17 ` [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results() ville.syrjala
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

No point in re-computing the watermarks for all pipes, when only one
pipe has changed. The watermarks stored under intel_crtc.wm.active are
still valid for the other pipes. We just need to redo the merging.

We can also skip the merge/update procedure completely if the new
watermarks for the affected pipe come out unchanged.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 67 +++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 30b380c..7eea69d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2584,29 +2584,19 @@ static void intel_setup_wm_latency(struct drm_device *dev)
 	intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
 }
 
-static void hsw_compute_wm_parameters(struct drm_device *dev,
-				      struct hsw_pipe_wm_parameters *params,
+static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
+				      struct hsw_pipe_wm_parameters *p,
 				      struct hsw_wm_maximums *lp_max_1_2,
 				      struct hsw_wm_maximums *lp_max_5_6)
 {
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
-	enum pipe pipe;
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
 	struct intel_wm_config config = {};
+	struct drm_plane *plane;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		struct hsw_pipe_wm_parameters *p;
-
-		pipe = intel_crtc->pipe;
-		p = &params[pipe];
-
-		p->active = intel_crtc_active(crtc);
-		if (!p->active)
-			continue;
-
-		config.num_pipes_active++;
-
+	p->active = intel_crtc_active(crtc);
+	if (p->active) {
 		p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
 		p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
 		p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
@@ -2618,17 +2608,17 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
 		p->cur.enabled = true;
 	}
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		config.num_pipes_active += intel_crtc_active(crtc);
+
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 		struct intel_plane *intel_plane = to_intel_plane(plane);
-		struct hsw_pipe_wm_parameters *p;
-
-		pipe = intel_plane->pipe;
-		p = &params[pipe];
 
-		p->spr = intel_plane->wm;
+		if (intel_plane->pipe == pipe)
+			p->spr = intel_plane->wm;
 
-		config.sprites_enabled |= p->spr.enabled;
-		config.sprites_scaled |= p->spr.scaled;
+		config.sprites_enabled |= intel_plane->wm.enabled;
+		config.sprites_scaled |= intel_plane->wm.scaled;
 	}
 
 	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
@@ -2656,8 +2646,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	};
 	struct hsw_wm_maximums max;
 
-	memset(pipe_wm, 0, sizeof(*pipe_wm));
-
 	/* LP0 watermarks always use 1/2 DDB partitioning */
 	ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
@@ -2728,7 +2716,6 @@ static void ilk_wm_merge(struct drm_device *dev,
 }
 
 static void hsw_compute_wm_results(struct drm_device *dev,
-				   const struct hsw_pipe_wm_parameters *params,
 				   const struct hsw_wm_maximums *lp_maximums,
 				   struct hsw_wm_values *results)
 {
@@ -2736,11 +2723,6 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	int level, wm_lp;
 	struct intel_pipe_wm merged = {};
 
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
-		intel_compute_pipe_wm(&intel_crtc->base,
-				      &params[intel_crtc->pipe],
-				      &intel_crtc->wm.active);
-
 	ilk_wm_merge(dev, lp_maximums, &merged);
 
 	memset(results, 0, sizeof(*results));
@@ -2907,20 +2889,27 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 
 static void haswell_update_wm(struct drm_crtc *crtc)
 {
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
-	struct hsw_pipe_wm_parameters params[3];
+	struct hsw_pipe_wm_parameters params = {};
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
 	enum intel_ddb_partitioning partitioning;
+	struct intel_pipe_wm pipe_wm = {};
+
+	hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
+
+	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
+
+	if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
+		return;
 
-	hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
+	intel_crtc->wm.active = pipe_wm;
 
-	hsw_compute_wm_results(dev, params,
-			       &lp_max_1_2, &results_1_2);
+	hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, params,
-				       &lp_max_5_6, &results_5_6);
+		hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6);
 		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
 	} else {
 		best_results = &results_1_2;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results()
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
  2013-10-09 16:17 ` [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute ville.syrjala
  2013-10-09 16:17 ` [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe ville.syrjala
@ 2013-10-09 16:17 ` ville.syrjala
  2013-10-10 22:04   ` Paulo Zanoni
  2013-10-09 16:17 ` [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results ville.syrjala
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

I want to convert hsw_find_best_result() to use intel_pipe_wm, so we
need to move the merging to happen outside hsw_compute_wm_results().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7eea69d..c2d439f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2716,26 +2716,23 @@ static void ilk_wm_merge(struct drm_device *dev,
 }
 
 static void hsw_compute_wm_results(struct drm_device *dev,
-				   const struct hsw_wm_maximums *lp_maximums,
+				   const struct intel_pipe_wm *merged,
 				   struct hsw_wm_values *results)
 {
 	struct intel_crtc *intel_crtc;
 	int level, wm_lp;
-	struct intel_pipe_wm merged = {};
-
-	ilk_wm_merge(dev, lp_maximums, &merged);
 
 	memset(results, 0, sizeof(*results));
 
-	results->enable_fbc_wm = merged.fbc_wm_enabled;
+	results->enable_fbc_wm = merged->fbc_wm_enabled;
 
 	/* LP1+ register values */
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
 		const struct intel_wm_level *r;
 
-		level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
+		level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
 
-		r = &merged.wm[level];
+		r = &merged->wm[level];
 		if (!r->enable)
 			break;
 
@@ -2897,6 +2894,7 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	struct hsw_wm_values results_1_2, results_5_6, *best_results;
 	enum intel_ddb_partitioning partitioning;
 	struct intel_pipe_wm pipe_wm = {};
+	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {};
 
 	hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
 
@@ -2907,9 +2905,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 
 	intel_crtc->wm.active = pipe_wm;
 
-	hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2);
+	ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
+	ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
+
+	hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6);
+		hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6);
 		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
 	} else {
 		best_results = &results_1_2;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (2 preceding siblings ...)
  2013-10-09 16:17 ` [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results() ville.syrjala
@ 2013-10-09 16:17 ` ville.syrjala
  2013-10-10 22:20   ` Paulo Zanoni
  2013-10-09 16:17 ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() ville.syrjala
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Let's try to keep using the intermediate intel_pipe_wm representation
for as long as possible. It avoids subtle knowledge about the
internals of the hardware registers when trying to choose the
best watermark configuration.

While at it replace the memset() w/ zero initialization.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 42 ++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c2d439f..b09715f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2722,8 +2722,6 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	struct intel_crtc *intel_crtc;
 	int level, wm_lp;
 
-	memset(results, 0, sizeof(*results));
-
 	results->enable_fbc_wm = merged->fbc_wm_enabled;
 
 	/* LP1+ register values */
@@ -2763,24 +2761,26 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 
 /* Find the result with the highest level enabled. Check for enable_fbc_wm in
  * case both are at the same level. Prefer r1 in case they're the same. */
-static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
-						  struct hsw_wm_values *r2)
+static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
+						  struct intel_pipe_wm *r1,
+						  struct intel_pipe_wm *r2)
 {
-	int i, val_r1 = 0, val_r2 = 0;
+	int level, max_level = ilk_wm_max_level(dev);
+	int level1 = 0, level2 = 0;
 
-	for (i = 0; i < 3; i++) {
-		if (r1->wm_lp[i] & WM3_LP_EN)
-			val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK;
-		if (r2->wm_lp[i] & WM3_LP_EN)
-			val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK;
+	for (level = 1; level <= max_level; level++) {
+		if (r1->wm[level].enable)
+			level1 = level;
+		if (r2->wm[level].enable)
+			level2 = level;
 	}
 
-	if (val_r1 == val_r2) {
-		if (r2->enable_fbc_wm && !r1->enable_fbc_wm)
+	if (level1 == level2) {
+		if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled)
 			return r2;
 		else
 			return r1;
-	} else if (val_r1 > val_r2) {
+	} else if (level1 > level2) {
 		return r1;
 	} else {
 		return r2;
@@ -2891,10 +2891,10 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
 	struct hsw_pipe_wm_parameters params = {};
-	struct hsw_wm_values results_1_2, results_5_6, *best_results;
+	struct hsw_wm_values results = {};
 	enum intel_ddb_partitioning partitioning;
 	struct intel_pipe_wm pipe_wm = {};
-	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {};
+	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 
 	hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
 
@@ -2908,18 +2908,18 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
 	ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
 
-	hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2);
 	if (lp_max_1_2.pri != lp_max_5_6.pri) {
-		hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6);
-		best_results = hsw_find_best_result(&results_1_2, &results_5_6);
+		best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
 	} else {
-		best_results = &results_1_2;
+		best_lp_wm = &lp_wm_1_2;
 	}
 
-	partitioning = (best_results == &results_1_2) ?
+	hsw_compute_wm_results(dev, best_lp_wm, &results);
+
+	partitioning = (best_lp_wm == &lp_wm_1_2) ?
 		       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
-	hsw_write_wm_values(dev_priv, best_results, partitioning);
+	hsw_write_wm_values(dev_priv, &results, partitioning);
 }
 
 static void haswell_update_sprite_wm(struct drm_plane *plane,
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters()
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (3 preceding siblings ...)
  2013-10-09 16:17 ` [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results ville.syrjala
@ 2013-10-09 16:17 ` ville.syrjala
  2013-10-10 22:34   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes ville.syrjala
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:17 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the watermark max computations into haswell_update_wm(). This
allows keeping the 1/2 vs. 5/6 split code in one place, and avoid having
to pass around so many things. We also save a bit of stack space by only
requiring one copy of struct hsw_wm_maximums.

Also move the intel_wm_config out from hsw_compute_wm_parameters() and
pass it it. We'll have some need for it in haswell_update_wm() later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b09715f..0fe6c36 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2586,13 +2586,11 @@ static void intel_setup_wm_latency(struct drm_device *dev)
 
 static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 				      struct hsw_pipe_wm_parameters *p,
-				      struct hsw_wm_maximums *lp_max_1_2,
-				      struct hsw_wm_maximums *lp_max_5_6)
+				      struct intel_wm_config *config)
 {
 	struct drm_device *dev = crtc->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum pipe pipe = intel_crtc->pipe;
-	struct intel_wm_config config = {};
 	struct drm_plane *plane;
 
 	p->active = intel_crtc_active(crtc);
@@ -2609,7 +2607,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 	}
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		config.num_pipes_active += intel_crtc_active(crtc);
+		config->num_pipes_active += intel_crtc_active(crtc);
 
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 		struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -2617,17 +2615,9 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 		if (intel_plane->pipe == pipe)
 			p->spr = intel_plane->wm;
 
-		config.sprites_enabled |= intel_plane->wm.enabled;
-		config.sprites_scaled |= intel_plane->wm.scaled;
+		config->sprites_enabled |= intel_plane->wm.enabled;
+		config->sprites_scaled |= intel_plane->wm.scaled;
 	}
-
-	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
-
-	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1)
-		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
-	else
-		*lp_max_5_6 = *lp_max_1_2;
 }
 
 /* Compute new watermarks for the pipe */
@@ -2889,14 +2879,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
+	struct hsw_wm_maximums max;
 	struct hsw_pipe_wm_parameters params = {};
 	struct hsw_wm_values results = {};
 	enum intel_ddb_partitioning partitioning;
 	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 = {};
 
-	hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
+	hsw_compute_wm_parameters(crtc, &params, &config);
 
 	intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
@@ -2905,10 +2896,14 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 
 	intel_crtc->wm.active = pipe_wm;
 
-	ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
-	ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
+	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
+	ilk_wm_merge(dev, &max, &lp_wm_1_2);
+
+	/* 5/6 split only in single pipe config on IVB+ */
+	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {
+		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
+		ilk_wm_merge(dev, &max, &lp_wm_5_6);
 
-	if (lp_max_1_2.pri != lp_max_5_6.pri) {
 		best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
 	} else {
 		best_lp_wm = &lp_wm_1_2;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (4 preceding siblings ...)
  2013-10-09 16:17 ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-10 22:38   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation ville.syrjala
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

When there are zero active pipes, all the watermarks should be zero
also. No point in wasting time w/ computing the 5/6 split watermark
config.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0fe6c36..c17518d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2900,7 +2900,7 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	ilk_wm_merge(dev, &max, &lp_wm_1_2);
 
 	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {
+	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {
 		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
 		ilk_wm_merge(dev, &max, &lp_wm_5_6);
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (5 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-10 22:42   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config ville.syrjala
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

On HSW the LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4. We make the
conversion from LPn to to the level at one point current. Later we're
going to do it in a few places, so move it to a separate function.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c17518d..d307039 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2705,6 +2705,12 @@ static void ilk_wm_merge(struct drm_device *dev,
 	}
 }
 
+static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
+{
+	/* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4 */
+	return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable);
+}
+
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   const struct intel_pipe_wm *merged,
 				   struct hsw_wm_values *results)
@@ -2718,7 +2724,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
 		const struct intel_wm_level *r;
 
-		level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
+		level = ilk_wm_lp_to_level(wm_lp, merged);
 
 		r = &merged->wm[level];
 		if (!r->enable)
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (6 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-10 22:45   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm ville.syrjala
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The fbc_wm_enabled member in intel_wm_config is useless for the time
being. The original idea for it was that we'd pre-compute it and so
that the WM merging process could know whether it needs to worry
about FBC watermarks at all.

But we don't have a convenient way to pre-check for the possibility
of FBC being used. intel_update_fbc() should be split up for that.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d307039..e81221d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2213,7 +2213,6 @@ struct intel_wm_config {
 	unsigned int num_pipes_active;
 	bool sprites_enabled;
 	bool sprites_scaled;
-	bool fbc_wm_enabled;
 };
 
 /*
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (7 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 14:21   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 10/16] drm/i915: Improve watermark dirtyness checks ville.syrjala
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

To make it easier to check what watermark updates are actually
necessary, keep copies of the relevant bits that match the current
hardware state.

Also add DDB partitioning into hsw_wm_values as that's another piece
of state we want to track.

We don't read out the hardware state on init yet, so we can't really
start using this yet, but it will be used later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 12 +++++++++++
 drivers/gpu/drm/i915/intel_pm.c | 46 ++++++++++++++---------------------------
 2 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9cac93c..478d17c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1140,6 +1140,15 @@ struct intel_wm_level {
 	uint32_t fbc_val;
 };
 
+struct hsw_wm_values {
+	uint32_t wm_pipe[3];
+	uint32_t wm_lp[3];
+	uint32_t wm_lp_spr[3];
+	uint32_t wm_linetime[3];
+	bool enable_fbc_wm;
+	enum intel_ddb_partitioning partitioning;
+};
+
 /*
  * This struct tracks the state needed for the Package C8+ feature.
  *
@@ -1399,6 +1408,9 @@ typedef struct drm_i915_private {
 		uint16_t spr_latency[5];
 		/* cursor */
 		uint16_t cur_latency[5];
+
+		/* current hardware state */
+		struct hsw_wm_values hw;
 	} wm;
 
 	struct i915_package_c8 pc8;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e81221d..bed96fb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2200,14 +2200,6 @@ struct hsw_wm_maximums {
 	uint16_t fbc;
 };
 
-struct hsw_wm_values {
-	uint32_t wm_pipe[3];
-	uint32_t wm_lp[3];
-	uint32_t wm_lp_spr[3];
-	uint32_t wm_linetime[3];
-	bool enable_fbc_wm;
-};
-
 /* used in computing the new watermarks state */
 struct intel_wm_config {
 	unsigned int num_pipes_active;
@@ -2712,12 +2704,14 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
 
 static void hsw_compute_wm_results(struct drm_device *dev,
 				   const struct intel_pipe_wm *merged,
+				   enum intel_ddb_partitioning partitioning,
 				   struct hsw_wm_values *results)
 {
 	struct intel_crtc *intel_crtc;
 	int level, wm_lp;
 
 	results->enable_fbc_wm = merged->fbc_wm_enabled;
+	results->partitioning = partitioning;
 
 	/* LP1+ register values */
 	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
@@ -2787,13 +2781,10 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
  * causes WMs to be re-evaluated, expending some power.
  */
 static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
-				struct hsw_wm_values *results,
-				enum intel_ddb_partitioning partitioning)
+				struct hsw_wm_values *results)
 {
 	struct hsw_wm_values previous;
 	uint32_t val;
-	enum intel_ddb_partitioning prev_partitioning;
-	bool prev_enable_fbc_wm;
 
 	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
 	previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
@@ -2808,21 +2799,12 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 	previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
 	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
 
-	prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
+	previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
 				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
-	prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
-
-	if (memcmp(results->wm_pipe, previous.wm_pipe,
-		   sizeof(results->wm_pipe)) == 0 &&
-	    memcmp(results->wm_lp, previous.wm_lp,
-		   sizeof(results->wm_lp)) == 0 &&
-	    memcmp(results->wm_lp_spr, previous.wm_lp_spr,
-		   sizeof(results->wm_lp_spr)) == 0 &&
-	    memcmp(results->wm_linetime, previous.wm_linetime,
-		   sizeof(results->wm_linetime)) == 0 &&
-	    partitioning == prev_partitioning &&
-	    results->enable_fbc_wm == prev_enable_fbc_wm)
+	previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
+
+	if (memcmp(results, &previous, sizeof(*results)) == 0)
 		return;
 
 	if (previous.wm_lp[2] != 0)
@@ -2846,16 +2828,16 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 	if (previous.wm_linetime[2] != results->wm_linetime[2])
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
-	if (prev_partitioning != partitioning) {
+	if (previous.partitioning != results->partitioning) {
 		val = I915_READ(WM_MISC);
-		if (partitioning == INTEL_DDB_PART_1_2)
+		if (results->partitioning == INTEL_DDB_PART_1_2)
 			val &= ~WM_MISC_DATA_PARTITION_5_6;
 		else
 			val |= WM_MISC_DATA_PARTITION_5_6;
 		I915_WRITE(WM_MISC, val);
 	}
 
-	if (prev_enable_fbc_wm != results->enable_fbc_wm) {
+	if (previous.enable_fbc_wm != results->enable_fbc_wm) {
 		val = I915_READ(DISP_ARB_CTL);
 		if (results->enable_fbc_wm)
 			val &= ~DISP_FBC_WM_DIS;
@@ -2877,6 +2859,8 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
 	if (results->wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
+
+	dev_priv->wm.hw = *results;
 }
 
 static void haswell_update_wm(struct drm_crtc *crtc)
@@ -2914,12 +2898,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 		best_lp_wm = &lp_wm_1_2;
 	}
 
-	hsw_compute_wm_results(dev, best_lp_wm, &results);
-
 	partitioning = (best_lp_wm == &lp_wm_1_2) ?
 		       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
-	hsw_write_wm_values(dev_priv, &results, partitioning);
+	hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results);
+
+	hsw_write_wm_values(dev_priv, &results);
 }
 
 static void haswell_update_sprite_wm(struct drm_plane *plane,
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (8 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 15:02   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state() ville.syrjala
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently hsw_write_vm_values() may write to certain watermark
registers needlessly. For instance it will disable LP1+ watermarks
around WM_PIPE changes even though that's not needed. Also if only,
say, LP3 changes, the current code will again disable all LP1+
watermarks even though only LP3 needs to be reconfigured.

Add an easy to read function that will compute the dirtyness of the
watermarks, and use that information to further optimize the watermark
programming.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 95 +++++++++++++++++++++++++++++++++--------
 1 file changed, 77 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index bed96fb..5bd8c73 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2776,6 +2776,63 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
 	}
 }
 
+/* dirty bits used to track which watermarks need changes */
+#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
+#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
+#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
+#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
+#define WM_DIRTY_FBC (1 << 24)
+#define WM_DIRTY_DDB (1 << 25)
+
+static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
+					 const struct hsw_wm_values *old,
+					 const struct hsw_wm_values *new)
+{
+	unsigned int dirty = 0;
+	enum pipe pipe;
+	int wm_lp;
+
+	for_each_pipe(pipe) {
+		if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
+			dirty |= WM_DIRTY_LINETIME(pipe);
+			/* Must disable LP1+ watermarks too */
+			dirty |= WM_DIRTY_LP_ALL;
+		}
+
+		if (old->wm_pipe[pipe] != new->wm_pipe[pipe])
+			dirty |= WM_DIRTY_PIPE(pipe);
+	}
+
+	if (old->enable_fbc_wm != new->enable_fbc_wm) {
+		dirty |= WM_DIRTY_FBC;
+		/* Must disable LP1+ watermarks too */
+		dirty |= WM_DIRTY_LP_ALL;
+	}
+
+	if (old->partitioning != new->partitioning) {
+		dirty |= WM_DIRTY_DDB;
+		/* Must disable LP1+ watermarks too */
+		dirty |= WM_DIRTY_LP_ALL;
+	}
+
+	/* LP1+ watermarks already deemed dirty, no need to continue */
+	if (dirty & WM_DIRTY_LP_ALL)
+		return dirty;
+
+	/* Find the lowest numbered LP1+ watermark in need of an update... */
+	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
+		if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
+		    old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
+			break;
+	}
+
+	/* ...and mark it and all higher numbered LP1+ watermarks as dirty */
+	for (; wm_lp <= 3; wm_lp++)
+		dirty |= WM_DIRTY_LP(wm_lp);
+
+	return dirty;
+}
+
 /*
  * The spec says we shouldn't write when we don't need, because every write
  * causes WMs to be re-evaluated, expending some power.
@@ -2784,6 +2841,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results)
 {
 	struct hsw_wm_values previous;
+	unsigned int dirty;
 	uint32_t val;
 
 	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
@@ -2804,31 +2862,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 
 	previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
 
-	if (memcmp(results, &previous, sizeof(*results)) == 0)
+	dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
+	if (!dirty)
 		return;
 
-	if (previous.wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, 0);
-	if (previous.wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, 0);
-	if (previous.wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, 0);
 
-	if (previous.wm_pipe[0] != results->wm_pipe[0])
+	if (dirty & WM_DIRTY_PIPE(PIPE_A))
 		I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
-	if (previous.wm_pipe[1] != results->wm_pipe[1])
+	if (dirty & WM_DIRTY_PIPE(PIPE_B))
 		I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
-	if (previous.wm_pipe[2] != results->wm_pipe[2])
+	if (dirty & WM_DIRTY_PIPE(PIPE_C))
 		I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
 
-	if (previous.wm_linetime[0] != results->wm_linetime[0])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_A))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
-	if (previous.wm_linetime[1] != results->wm_linetime[1])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_B))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
-	if (previous.wm_linetime[2] != results->wm_linetime[2])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_C))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
-	if (previous.partitioning != results->partitioning) {
+	if (dirty & WM_DIRTY_DDB) {
 		val = I915_READ(WM_MISC);
 		if (results->partitioning == INTEL_DDB_PART_1_2)
 			val &= ~WM_MISC_DATA_PARTITION_5_6;
@@ -2837,7 +2896,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM_MISC, val);
 	}
 
-	if (previous.enable_fbc_wm != results->enable_fbc_wm) {
+	if (dirty & WM_DIRTY_FBC) {
 		val = I915_READ(DISP_ARB_CTL);
 		if (results->enable_fbc_wm)
 			val &= ~DISP_FBC_WM_DIS;
@@ -2846,18 +2905,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(DISP_ARB_CTL, val);
 	}
 
-	if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
+	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
 		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-	if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
+	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
 		I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-	if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
+	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
 		I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
-	if (results->wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
-	if (results->wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
-	if (results->wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 
 	dev_priv->wm.hw = *results;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (9 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 10/16] drm/i915: Improve watermark dirtyness checks ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 16:45   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code ville.syrjala
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Fill out the HSW watermark s/w tracking structures with the current
hardware state in intel_modeset_setup_hw_state(). This allows us to skip
the HW state readback during watermark programming and just use the values
we keep around in dev_priv->wm. Reduces the overhead of the watermark
programming quite a bit.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   3 +
 drivers/gpu/drm/i915/intel_drv.h     |   1 +
 drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
 3 files changed, 82 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 27f98bc..194f933 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 		pll->on = false;
 	}
 
+	if (IS_HASWELL(dev))
+		ilk_init_wm(dev);
+
 	if (force_restore) {
 		i915_redisable_vga(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3325b0b..bdb1708 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void ilk_init_wm(struct drm_device *dev);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5bd8c73..cebd9b4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
 static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results)
 {
-	struct hsw_wm_values previous;
+	struct hsw_wm_values *previous = &dev_priv->wm.hw;
 	unsigned int dirty;
 	uint32_t val;
 
-	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
-	previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
-	previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
-	previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
-	previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
-	previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
-	previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-	previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
-	previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
-	previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
-	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
-
-	previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-
-	previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
-
-	dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
+	dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
 	if (!dirty)
 		return;
 
-	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, 0);
-	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, 0);
-	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, 0);
 
 	if (dirty & WM_DIRTY_PIPE(PIPE_A))
@@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(DISP_ARB_CTL, val);
 	}
 
-	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
+	if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
 		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
+	if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
 		I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
+	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
 		I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
 	if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
@@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
 	I915_WRITE(WM3S_LP_IVB, sprite_wm);
 }
 
+static void ilk_init_pipe_wm(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct hsw_wm_values *hw = &dev_priv->wm.hw;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_pipe_wm *active = &intel_crtc->wm.active;
+	enum pipe pipe = intel_crtc->pipe;
+	static const unsigned int wm0_pipe_reg[] = {
+		[PIPE_A] = WM0_PIPEA_ILK,
+		[PIPE_B] = WM0_PIPEB_ILK,
+		[PIPE_C] = WM0_PIPEC_IVB,
+	};
+
+	hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
+	hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+
+	/* Assume sprites are disabled */
+
+	if (intel_crtc_active(crtc)) {
+		u32 tmp = hw->wm_pipe[pipe];
+
+		/*
+		 * For active pipes LP0 watermark is marked as
+		 * enabled, and LP1+ watermaks as disabled since
+		 * we can't really reverse compute them in case
+		 * multiple pipes are active.
+		 */
+		active->wm[0].enable = true;
+		active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
+		active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
+		active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
+		active->linetime = hw->wm_linetime[pipe];
+	} else {
+		int level, max_level = ilk_wm_max_level(dev);
+
+		/*
+		 * For inactive pipes, all watermark levels
+		 * should be marked as enabled but zeroed,
+		 * which is what we'd comoute them to.
+		 */
+		for (level = 0; level <= max_level; level++)
+			active->wm[level].enable = true;
+	}
+}
+
+void ilk_init_wm(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct hsw_wm_values *hw = &dev_priv->wm.hw;
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		ilk_init_pipe_wm(crtc);
+
+	hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
+	hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
+	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
+
+	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
+	hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
+	hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+
+	hw->partitioning =
+		!!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
+
+	hw->enable_fbc_wm =
+		!(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
+}
+
 /**
  * intel_update_watermarks - update FIFO watermark values based on current modes
  *
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (10 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state() ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 16:48   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH v2 13/16] drm/i915: Adjust watermark register masks ville.syrjala
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

This debug print just adds overhead to the watermark merging process,
and doesn't really give enough information to be useful. Just kill
and let's add something much better a bit later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index cebd9b4..0450260 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2421,8 +2421,6 @@ static bool ilk_check_wm(int level,
 		result->enable = true;
 	}
 
-	DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
-
 	return ret;
 }
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v2 13/16] drm/i915: Adjust watermark register masks
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (11 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 17:02   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 14/16] drm/i915: Add watermark tracepoints ville.syrjala
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We want to be able to use the masks to decode the register contents
regardless of the hardware generation. So just expand the masks to
cover all available bits, even if those are reserved on some
generations.

v2: Don't extend WM1_LP_SR_MASK so far, for the *future*

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c246727..cab709d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3251,11 +3251,11 @@
 
 /* define the Watermark register on Ironlake */
 #define WM0_PIPEA_ILK		0x45100
-#define  WM0_PIPE_PLANE_MASK	(0x7f<<16)
+#define  WM0_PIPE_PLANE_MASK	(0xffff<<16)
 #define  WM0_PIPE_PLANE_SHIFT	16
-#define  WM0_PIPE_SPRITE_MASK	(0x3f<<8)
+#define  WM0_PIPE_SPRITE_MASK	(0xff<<8)
 #define  WM0_PIPE_SPRITE_SHIFT	8
-#define  WM0_PIPE_CURSOR_MASK	(0x1f)
+#define  WM0_PIPE_CURSOR_MASK	(0xff)
 
 #define WM0_PIPEB_ILK		0x45104
 #define WM0_PIPEC_IVB		0x45200
@@ -3265,9 +3265,9 @@
 #define  WM1_LP_LATENCY_MASK	(0x7f<<24)
 #define  WM1_LP_FBC_MASK	(0xf<<20)
 #define  WM1_LP_FBC_SHIFT	20
-#define  WM1_LP_SR_MASK		(0x1ff<<8)
+#define  WM1_LP_SR_MASK		(0x7ff<<8)
 #define  WM1_LP_SR_SHIFT	8
-#define  WM1_LP_CURSOR_MASK	(0x3f)
+#define  WM1_LP_CURSOR_MASK	(0xff)
 #define WM2_LP_ILK		0x4510c
 #define  WM2_LP_EN		(1<<31)
 #define WM3_LP_ILK		0x45110
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 14/16] drm/i915: Add watermark tracepoints
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (12 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH v2 13/16] drm/i915: Adjust watermark register masks ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 19:40   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums ville.syrjala
  2013-10-09 16:18 ` [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level ville.syrjala
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@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@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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (13 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 14/16] drm/i915: Add watermark tracepoints ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 17:07   ` Paulo Zanoni
  2013-10-09 16:18 ` [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level ville.syrjala
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Makes the intention more clear.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 022cd5b..7b52e39 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2371,11 +2371,11 @@ static unsigned int ilk_fbc_wm_max(void)
 	return 15;
 }
 
-static void ilk_wm_max(struct drm_device *dev,
-		       int level,
-		       const struct intel_wm_config *config,
-		       enum intel_ddb_partitioning ddb_partitioning,
-		       struct hsw_wm_maximums *max)
+static void ilk_compute_wm_maximums(struct drm_device *dev,
+				    int level,
+				    const struct intel_wm_config *config,
+				    enum intel_ddb_partitioning ddb_partitioning,
+				    struct hsw_wm_maximums *max)
 {
 	max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
 	max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
@@ -2626,7 +2626,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	struct hsw_wm_maximums max;
 
 	/* LP0 watermarks always use 1/2 DDB partitioning */
-	ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
 	for (level = 0; level <= max_level; level++)
 		ilk_compute_wm_level(dev_priv, level, params,
@@ -2954,12 +2954,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 
 	intel_crtc->wm.active = pipe_wm;
 
-	ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
+	ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
 	ilk_wm_merge(dev, &max, &lp_wm_1_2);
 
 	/* 5/6 split only in single pipe config on IVB+ */
 	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {
-		ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
+		ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
 		ilk_wm_merge(dev, &max, &lp_wm_5_6);
 
 		best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level
  2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
                   ` (14 preceding siblings ...)
  2013-10-09 16:18 ` [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums ville.syrjala
@ 2013-10-09 16:18 ` ville.syrjala
  2013-10-11 17:08   ` Paulo Zanoni
  15 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-09 16:18 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Makes the behaviour of the function more clear.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7b52e39..211a946 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2383,9 +2383,9 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
 	max->fbc = ilk_fbc_wm_max();
 }
 
-static bool ilk_check_wm(int level,
-			 const struct hsw_wm_maximums *max,
-			 struct intel_wm_level *result)
+static bool ilk_validate_wm_level(int level,
+				  const struct hsw_wm_maximums *max,
+				  struct intel_wm_level *result)
 {
 	bool ret;
 
@@ -2635,7 +2635,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
 	pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
 	/* At least LP0 must be valid */
-	return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
+	return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
 }
 
 /*
@@ -2680,7 +2680,7 @@ static void ilk_wm_merge(struct drm_device *dev,
 
 		ilk_merge_wm_level(dev, level, wm);
 
-		if (!ilk_check_wm(level, max, wm))
+		if (!ilk_validate_wm_level(level, max, wm))
 			break;
 
 		/*
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute
  2013-10-09 16:17 ` [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute ville.syrjala
@ 2013-10-10 21:43   ` Paulo Zanoni
  2013-10-11  8:07     ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 21:43 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Introduce a new struct intel_pipe_wm which contains all the
> watermarks for a single pipe. Use it to unify the LP0 and LP1+
> watermark computations so that we can just iterate through the
> watermark levels neatly and call ilk_compute_wm_level() for each.
>
> Also add another tool ilk_wm_merge() that merges the LP1+ watermarks
> from all pipes. For that, embed one intel_pipe_wm inside intel_crtc that
> contains the currently valid watermarks for each pipe.
>
> This is mainly preparatory work for pre-computing the watermarks for
> each pipe and merging them at a later time. For now the merging still
> happens immediately.
>
> v2: Add some comments about level 0 DDB split and intel_wm_config
>     Add WARN_ON for level 0 being disabled
>     s/lp_wm/merged
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h |  12 +++
>  drivers/gpu/drm/i915/intel_pm.c  | 192 +++++++++++++++++++++++----------------
>  2 files changed, 128 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 71cfabd..3325b0b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -309,6 +309,12 @@ struct intel_crtc_config {
>         bool double_wide;
>  };
>
> +struct intel_pipe_wm {
> +       struct intel_wm_level wm[5];
> +       uint32_t linetime;
> +       bool fbc_wm_enabled;
> +};
> +
>  struct intel_crtc {
>         struct drm_crtc base;
>         enum pipe pipe;
> @@ -349,6 +355,12 @@ struct intel_crtc {
>         /* Access to these should be protected by dev_priv->irq_lock. */
>         bool cpu_fifo_underrun_disabled;
>         bool pch_fifo_underrun_disabled;
> +
> +       /* per-pipe watermark state */
> +       struct {
> +               /* watermarks currently being used  */
> +               struct intel_pipe_wm active;
> +       } wm;
>  };
>
>  struct intel_plane_wm_parameters {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 5e743ec..30b380c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2458,53 +2458,6 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
>         result->enable = true;
>  }
>
> -static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
> -                             int level, const struct hsw_wm_maximums *max,
> -                             const struct hsw_pipe_wm_parameters *params,
> -                             struct intel_wm_level *result)
> -{
> -       enum pipe pipe;
> -       struct intel_wm_level res[3];
> -
> -       for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
> -               ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
> -
> -       result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
> -       result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
> -       result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
> -       result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
> -       result->enable = true;
> -
> -       return ilk_check_wm(level, max, result);
> -}
> -
> -
> -static uint32_t hsw_compute_wm_pipe(struct drm_device *dev,
> -                                   const struct hsw_pipe_wm_parameters *params)
> -{
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct intel_wm_config config = {
> -               .num_pipes_active = 1,
> -               .sprites_enabled = params->spr.enabled,
> -               .sprites_scaled = params->spr.scaled,
> -       };
> -       struct hsw_wm_maximums max;
> -       struct intel_wm_level res;
> -
> -       if (!params->active)
> -               return 0;
> -
> -       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> -
> -       ilk_compute_wm_level(dev_priv, 0, params, &res);
> -
> -       ilk_check_wm(0, &max, &res);
> -
> -       return (res.pri_val << WM0_PIPE_PLANE_SHIFT) |
> -              (res.spr_val << WM0_PIPE_SPRITE_SHIFT) |
> -              res.cur_val;
> -}
> -
>  static uint32_t
>  hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
>  {
> @@ -2687,44 +2640,123 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>                 *lp_max_5_6 = *lp_max_1_2;
>  }
>
> +/* Compute new watermarks for the pipe */
> +static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> +                                 const struct hsw_pipe_wm_parameters *params,
> +                                 struct intel_pipe_wm *pipe_wm)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       int level, max_level = ilk_wm_max_level(dev);
> +       /* LP0 watermark maximums depend on this pipe alone */
> +       struct intel_wm_config config = {
> +               .num_pipes_active = 1,
> +               .sprites_enabled = params->spr.enabled,
> +               .sprites_scaled = params->spr.scaled,
> +       };
> +       struct hsw_wm_maximums max;
> +
> +       memset(pipe_wm, 0, sizeof(*pipe_wm));
> +
> +       /* LP0 watermarks always use 1/2 DDB partitioning */
> +       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> +
> +       for (level = 0; level <= max_level; level++)
> +               ilk_compute_wm_level(dev_priv, level, params,
> +                                    &pipe_wm->wm[level]);
> +
> +       pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
> +
> +       /* At least LP0 must be valid */
> +       return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
> +}
> +
> +/*
> + * Merge the watermarks from all active pipes for a specific level.
> + */
> +static void ilk_merge_wm_level(struct drm_device *dev,
> +                              int level,
> +                              struct intel_wm_level *ret_wm)
> +{
> +       const struct intel_crtc *intel_crtc;
> +
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> +               const struct intel_wm_level *wm =
> +                       &intel_crtc->wm.active.wm[level];
> +
> +               if (!wm->enable)
> +                       return;

Why exactly is this check here and what does it mean? Why not a
"break" nor a "continue"? Do we expect to ever return at this point?

It seems intel_compute_pipe_wm calls ilk_compute_wm_level which sets
"result->enable = true" for everything. Then only level 0 goes through
ilk_check_wm (which may turn result->enable to zero), but the level1+
watermarks (which are the ones used in the merge function) never get a
chance to set wm->enable to false. So the check would be useless.
Maybe I'm missing something?

With the questions above (answered || fixed || clarified || patched):

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +
> +               ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
> +               ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
> +               ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
> +               ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
> +       }
> +
> +       ret_wm->enable = true;
> +}
> +
> +/*
> + * Merge all low power watermarks for all active pipes.
> + */
> +static void ilk_wm_merge(struct drm_device *dev,
> +                        const struct hsw_wm_maximums *max,
> +                        struct intel_pipe_wm *merged)
> +{
> +       int level, max_level = ilk_wm_max_level(dev);
> +
> +       merged->fbc_wm_enabled = true;
> +
> +       /* merge each WM1+ level */
> +       for (level = 1; level <= max_level; level++) {
> +               struct intel_wm_level *wm = &merged->wm[level];
> +
> +               ilk_merge_wm_level(dev, level, wm);
> +
> +               if (!ilk_check_wm(level, max, wm))
> +                       break;
> +
> +               /*
> +                * The spec says it is preferred to disable
> +                * FBC WMs instead of disabling a WM level.
> +                */
> +               if (wm->fbc_val > max->fbc) {
> +                       merged->fbc_wm_enabled = false;
> +                       wm->fbc_val = 0;
> +               }
> +       }
> +}
> +
>  static void hsw_compute_wm_results(struct drm_device *dev,
>                                    const struct hsw_pipe_wm_parameters *params,
>                                    const struct hsw_wm_maximums *lp_maximums,
>                                    struct hsw_wm_values *results)
>  {
> -       struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct drm_crtc *crtc;
> -       struct intel_wm_level lp_results[4] = {};
> -       enum pipe pipe;
> -       int level, max_level, wm_lp;
> +       struct intel_crtc *intel_crtc;
> +       int level, wm_lp;
> +       struct intel_pipe_wm merged = {};
>
> -       for (level = 1; level <= 4; level++)
> -               if (!hsw_compute_lp_wm(dev_priv, level,
> -                                      lp_maximums, params,
> -                                      &lp_results[level - 1]))
> -                       break;
> -       max_level = level - 1;
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
> +               intel_compute_pipe_wm(&intel_crtc->base,
> +                                     &params[intel_crtc->pipe],
> +                                     &intel_crtc->wm.active);
> +
> +       ilk_wm_merge(dev, lp_maximums, &merged);
>
>         memset(results, 0, sizeof(*results));
>
> -       /* The spec says it is preferred to disable FBC WMs instead of disabling
> -        * a WM level. */
> -       results->enable_fbc_wm = true;
> -       for (level = 1; level <= max_level; level++) {
> -               if (lp_results[level - 1].fbc_val > lp_maximums->fbc) {
> -                       results->enable_fbc_wm = false;
> -                       lp_results[level - 1].fbc_val = 0;
> -               }
> -       }
> +       results->enable_fbc_wm = merged.fbc_wm_enabled;
>
> +       /* LP1+ register values */
>         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
>                 const struct intel_wm_level *r;
>
> -               level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
> -               if (level > max_level)
> +               level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
> +
> +               r = &merged.wm[level];
> +               if (!r->enable)
>                         break;
>
> -               r = &lp_results[level - 1];
>                 results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
>                                                           r->fbc_val,
>                                                           r->pri_val,
> @@ -2732,13 +2764,21 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>                 results->wm_lp_spr[wm_lp - 1] = r->spr_val;
>         }
>
> -       for_each_pipe(pipe)
> -               results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev,
> -                                                            &params[pipe]);
> +       /* LP0 register values */
> +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> +               enum pipe pipe = intel_crtc->pipe;
> +               const struct intel_wm_level *r =
> +                       &intel_crtc->wm.active.wm[0];
>
> -       for_each_pipe(pipe) {
> -               crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> -               results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
> +               if (WARN_ON(!r->enable))
> +                       continue;
> +
> +               results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
> +
> +               results->wm_pipe[pipe] =
> +                       (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
> +                       (r->spr_val << WM0_PIPE_SPRITE_SHIFT) |
> +                       r->cur_val;
>         }
>  }
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe
  2013-10-09 16:17 ` [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe ville.syrjala
@ 2013-10-10 21:57   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 21:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> No point in re-computing the watermarks for all pipes, when only one
> pipe has changed. The watermarks stored under intel_crtc.wm.active are
> still valid for the other pipes. We just need to redo the merging.
>
> We can also skip the merge/update procedure completely if the new
> watermarks for the affected pipe come out unchanged.

Nice one!

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 67 +++++++++++++++++------------------------
>  1 file changed, 28 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 30b380c..7eea69d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2584,29 +2584,19 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>         intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
>  }
>
> -static void hsw_compute_wm_parameters(struct drm_device *dev,
> -                                     struct hsw_pipe_wm_parameters *params,
> +static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
> +                                     struct hsw_pipe_wm_parameters *p,
>                                       struct hsw_wm_maximums *lp_max_1_2,
>                                       struct hsw_wm_maximums *lp_max_5_6)
>  {
> -       struct drm_crtc *crtc;
> -       struct drm_plane *plane;
> -       enum pipe pipe;
> +       struct drm_device *dev = crtc->dev;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       enum pipe pipe = intel_crtc->pipe;
>         struct intel_wm_config config = {};
> +       struct drm_plane *plane;
>
> -       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -               struct hsw_pipe_wm_parameters *p;
> -
> -               pipe = intel_crtc->pipe;
> -               p = &params[pipe];
> -
> -               p->active = intel_crtc_active(crtc);
> -               if (!p->active)
> -                       continue;
> -
> -               config.num_pipes_active++;
> -
> +       p->active = intel_crtc_active(crtc);
> +       if (p->active) {
>                 p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
>                 p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
>                 p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
> @@ -2618,17 +2608,17 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>                 p->cur.enabled = true;
>         }
>
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> +               config.num_pipes_active += intel_crtc_active(crtc);
> +
>         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
>                 struct intel_plane *intel_plane = to_intel_plane(plane);
> -               struct hsw_pipe_wm_parameters *p;
> -
> -               pipe = intel_plane->pipe;
> -               p = &params[pipe];
>
> -               p->spr = intel_plane->wm;
> +               if (intel_plane->pipe == pipe)
> +                       p->spr = intel_plane->wm;
>
> -               config.sprites_enabled |= p->spr.enabled;
> -               config.sprites_scaled |= p->spr.scaled;
> +               config.sprites_enabled |= intel_plane->wm.enabled;
> +               config.sprites_scaled |= intel_plane->wm.scaled;
>         }
>
>         ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
> @@ -2656,8 +2646,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         };
>         struct hsw_wm_maximums max;
>
> -       memset(pipe_wm, 0, sizeof(*pipe_wm));
> -
>         /* LP0 watermarks always use 1/2 DDB partitioning */
>         ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
>
> @@ -2728,7 +2716,6 @@ static void ilk_wm_merge(struct drm_device *dev,
>  }
>
>  static void hsw_compute_wm_results(struct drm_device *dev,
> -                                  const struct hsw_pipe_wm_parameters *params,
>                                    const struct hsw_wm_maximums *lp_maximums,
>                                    struct hsw_wm_values *results)
>  {
> @@ -2736,11 +2723,6 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>         int level, wm_lp;
>         struct intel_pipe_wm merged = {};
>
> -       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
> -               intel_compute_pipe_wm(&intel_crtc->base,
> -                                     &params[intel_crtc->pipe],
> -                                     &intel_crtc->wm.active);
> -
>         ilk_wm_merge(dev, lp_maximums, &merged);
>
>         memset(results, 0, sizeof(*results));
> @@ -2907,20 +2889,27 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>
>  static void haswell_update_wm(struct drm_crtc *crtc)
>  {
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> -       struct hsw_pipe_wm_parameters params[3];
> +       struct hsw_pipe_wm_parameters params = {};
>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
>         enum intel_ddb_partitioning partitioning;
> +       struct intel_pipe_wm pipe_wm = {};
> +
> +       hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
> +
> +       intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> +
> +       if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> +               return;
>
> -       hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6);
> +       intel_crtc->wm.active = pipe_wm;
>
> -       hsw_compute_wm_results(dev, params,
> -                              &lp_max_1_2, &results_1_2);
> +       hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2);
>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
> -               hsw_compute_wm_results(dev, params,
> -                                      &lp_max_5_6, &results_5_6);
> +               hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6);
>                 best_results = hsw_find_best_result(&results_1_2, &results_5_6);
>         } else {
>                 best_results = &results_1_2;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results()
  2013-10-09 16:17 ` [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results() ville.syrjala
@ 2013-10-10 22:04   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:04 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> I want to convert hsw_find_best_result() to use intel_pipe_wm, so we
> need to move the merging to happen outside hsw_compute_wm_results().
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7eea69d..c2d439f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2716,26 +2716,23 @@ static void ilk_wm_merge(struct drm_device *dev,
>  }
>
>  static void hsw_compute_wm_results(struct drm_device *dev,
> -                                  const struct hsw_wm_maximums *lp_maximums,
> +                                  const struct intel_pipe_wm *merged,
>                                    struct hsw_wm_values *results)
>  {
>         struct intel_crtc *intel_crtc;
>         int level, wm_lp;
> -       struct intel_pipe_wm merged = {};
> -
> -       ilk_wm_merge(dev, lp_maximums, &merged);
>
>         memset(results, 0, sizeof(*results));
>
> -       results->enable_fbc_wm = merged.fbc_wm_enabled;
> +       results->enable_fbc_wm = merged->fbc_wm_enabled;
>
>         /* LP1+ register values */
>         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
>                 const struct intel_wm_level *r;
>
> -               level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
> +               level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
>
> -               r = &merged.wm[level];
> +               r = &merged->wm[level];
>                 if (!r->enable)
>                         break;
>
> @@ -2897,6 +2894,7 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         struct hsw_wm_values results_1_2, results_5_6, *best_results;
>         enum intel_ddb_partitioning partitioning;
>         struct intel_pipe_wm pipe_wm = {};
> +       struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {};
>
>         hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
>
> @@ -2907,9 +2905,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>
>         intel_crtc->wm.active = pipe_wm;
>
> -       hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2);
> +       ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
> +       ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);

Shouldn't you move the 5_6 ilk_wm_merge to inside the "if" statement,
because it's only needed there?

With or without that: Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +
> +       hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2);
>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
> -               hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6);
> +               hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6);
>                 best_results = hsw_find_best_result(&results_1_2, &results_5_6);
>         } else {
>                 best_results = &results_1_2;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results
  2013-10-09 16:17 ` [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results ville.syrjala
@ 2013-10-10 22:20   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:20 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Let's try to keep using the intermediate intel_pipe_wm representation
> for as long as possible. It avoids subtle knowledge about the
> internals of the hardware registers when trying to choose the
> best watermark configuration.
>
> While at it replace the memset() w/ zero initialization.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Looks correct. These things are hard to review... So many structs!

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 42 ++++++++++++++++++++---------------------
>  1 file changed, 21 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c2d439f..b09715f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2722,8 +2722,6 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>         struct intel_crtc *intel_crtc;
>         int level, wm_lp;
>
> -       memset(results, 0, sizeof(*results));
> -
>         results->enable_fbc_wm = merged->fbc_wm_enabled;
>
>         /* LP1+ register values */
> @@ -2763,24 +2761,26 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>
>  /* Find the result with the highest level enabled. Check for enable_fbc_wm in
>   * case both are at the same level. Prefer r1 in case they're the same. */
> -static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1,
> -                                                 struct hsw_wm_values *r2)
> +static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
> +                                                 struct intel_pipe_wm *r1,
> +                                                 struct intel_pipe_wm *r2)
>  {
> -       int i, val_r1 = 0, val_r2 = 0;
> +       int level, max_level = ilk_wm_max_level(dev);
> +       int level1 = 0, level2 = 0;
>
> -       for (i = 0; i < 3; i++) {
> -               if (r1->wm_lp[i] & WM3_LP_EN)
> -                       val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK;
> -               if (r2->wm_lp[i] & WM3_LP_EN)
> -                       val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK;
> +       for (level = 1; level <= max_level; level++) {
> +               if (r1->wm[level].enable)
> +                       level1 = level;
> +               if (r2->wm[level].enable)
> +                       level2 = level;
>         }
>
> -       if (val_r1 == val_r2) {
> -               if (r2->enable_fbc_wm && !r1->enable_fbc_wm)
> +       if (level1 == level2) {
> +               if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled)
>                         return r2;
>                 else
>                         return r1;
> -       } else if (val_r1 > val_r2) {
> +       } else if (level1 > level2) {
>                 return r1;
>         } else {
>                 return r2;
> @@ -2891,10 +2891,10 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>         struct hsw_pipe_wm_parameters params = {};
> -       struct hsw_wm_values results_1_2, results_5_6, *best_results;
> +       struct hsw_wm_values results = {};
>         enum intel_ddb_partitioning partitioning;
>         struct intel_pipe_wm pipe_wm = {};
> -       struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {};
> +       struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
>
>         hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
>
> @@ -2908,18 +2908,18 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
>         ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
>
> -       hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2);
>         if (lp_max_1_2.pri != lp_max_5_6.pri) {
> -               hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6);
> -               best_results = hsw_find_best_result(&results_1_2, &results_5_6);
> +               best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
>         } else {
> -               best_results = &results_1_2;
> +               best_lp_wm = &lp_wm_1_2;
>         }
>
> -       partitioning = (best_results == &results_1_2) ?
> +       hsw_compute_wm_results(dev, best_lp_wm, &results);
> +
> +       partitioning = (best_lp_wm == &lp_wm_1_2) ?
>                        INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
>
> -       hsw_write_wm_values(dev_priv, best_results, partitioning);
> +       hsw_write_wm_values(dev_priv, &results, partitioning);
>  }
>
>  static void haswell_update_sprite_wm(struct drm_plane *plane,
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters()
  2013-10-09 16:17 ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() ville.syrjala
@ 2013-10-10 22:34   ` Paulo Zanoni
  2013-10-11  8:26     ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:34 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Move the watermark max computations into haswell_update_wm(). This
> allows keeping the 1/2 vs. 5/6 split code in one place, and avoid having
> to pass around so many things. We also save a bit of stack space by only
> requiring one copy of struct hsw_wm_maximums.
>
> Also move the intel_wm_config out from hsw_compute_wm_parameters() and
> pass it it. We'll have some need for it in haswell_update_wm() later.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++-------------------
>  1 file changed, 14 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index b09715f..0fe6c36 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2586,13 +2586,11 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>
>  static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>                                       struct hsw_pipe_wm_parameters *p,
> -                                     struct hsw_wm_maximums *lp_max_1_2,
> -                                     struct hsw_wm_maximums *lp_max_5_6)
> +                                     struct intel_wm_config *config)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         enum pipe pipe = intel_crtc->pipe;
> -       struct intel_wm_config config = {};
>         struct drm_plane *plane;
>
>         p->active = intel_crtc_active(crtc);
> @@ -2609,7 +2607,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>         }
>
>         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> -               config.num_pipes_active += intel_crtc_active(crtc);
> +               config->num_pipes_active += intel_crtc_active(crtc);
>
>         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
>                 struct intel_plane *intel_plane = to_intel_plane(plane);
> @@ -2617,17 +2615,9 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>                 if (intel_plane->pipe == pipe)
>                         p->spr = intel_plane->wm;
>
> -               config.sprites_enabled |= intel_plane->wm.enabled;
> -               config.sprites_scaled |= intel_plane->wm.scaled;
> +               config->sprites_enabled |= intel_plane->wm.enabled;
> +               config->sprites_scaled |= intel_plane->wm.scaled;
>         }
> -
> -       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
> -
> -       /* 5/6 split only in single pipe config on IVB+ */
> -       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1)
> -               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
> -       else
> -               *lp_max_5_6 = *lp_max_1_2;
>  }
>
>  /* Compute new watermarks for the pipe */
> @@ -2889,14 +2879,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>         struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
> -       struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> +       struct hsw_wm_maximums max;
>         struct hsw_pipe_wm_parameters params = {};
>         struct hsw_wm_values results = {};
>         enum intel_ddb_partitioning partitioning;
>         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 = {};
>
> -       hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
> +       hsw_compute_wm_parameters(crtc, &params, &config);
>
>         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
>
> @@ -2905,10 +2896,14 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>
>         intel_crtc->wm.active = pipe_wm;
>
> -       ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
> -       ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
> +       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
> +       ilk_wm_merge(dev, &max, &lp_wm_1_2);
> +
> +       /* 5/6 split only in single pipe config on IVB+ */
> +       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {

No need to calculate 5_6 on zero pipes, I guess.


> +               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
> +               ilk_wm_merge(dev, &max, &lp_wm_5_6);

Oh, so now you've moved ilk_wm_merge to the "if" statement, as I
requested on the review to a previous patch :)

>
> -       if (lp_max_1_2.pri != lp_max_5_6.pri) {

By removing this check, you're now also calculating 5_6 watermarks for
the case where we just have 1 pipe but the sprites are disabled.


>                 best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
>         } else {
>                 best_lp_wm = &lp_wm_1_2;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes
  2013-10-09 16:18 ` [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes ville.syrjala
@ 2013-10-10 22:38   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:38 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> When there are zero active pipes, all the watermarks should be zero
> also. No point in wasting time w/ computing the 5/6 split watermark
> config.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 0fe6c36..c17518d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2900,7 +2900,7 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         ilk_wm_merge(dev, &max, &lp_wm_1_2);
>
>         /* 5/6 split only in single pipe config on IVB+ */
> -       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {
> +       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {

I was going to say "but you've just introduced this in the last
patch", then I re-check and saw that it was already there even before
the previous patch, you've just moved the code around on the last
patch.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

>                 ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
>                 ilk_wm_merge(dev, &max, &lp_wm_5_6);
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation
  2013-10-09 16:18 ` [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation ville.syrjala
@ 2013-10-10 22:42   ` Paulo Zanoni
  2013-10-11  8:10     ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:42 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> On HSW the LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4. We make the
> conversion from LPn to to the level at one point current. Later we're
> going to do it in a few places, so move it to a separate function.

I guess this function will work on ILK/SNB/IVB even though they don't
follow this rule, right? If yes: Reviewed-by: Paulo Zanoni
<paulo.r.zanoni@intel.com>

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c17518d..d307039 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2705,6 +2705,12 @@ static void ilk_wm_merge(struct drm_device *dev,
>         }
>  }
>
> +static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
> +{
> +       /* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4 */
> +       return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable);
> +}
> +
>  static void hsw_compute_wm_results(struct drm_device *dev,
>                                    const struct intel_pipe_wm *merged,
>                                    struct hsw_wm_values *results)
> @@ -2718,7 +2724,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
>                 const struct intel_wm_level *r;
>
> -               level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
> +               level = ilk_wm_lp_to_level(wm_lp, merged);
>
>                 r = &merged->wm[level];
>                 if (!r->enable)
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config
  2013-10-09 16:18 ` [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config ville.syrjala
@ 2013-10-10 22:45   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-10 22:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The fbc_wm_enabled member in intel_wm_config is useless for the time
> being. The original idea for it was that we'd pre-compute it and so
> that the WM merging process could know whether it needs to worry
> about FBC watermarks at all.

If it compiles, then I guess it's fine, right?

>
> But we don't have a convenient way to pre-check for the possibility
> of FBC being used. intel_update_fbc() should be split up for that.

I wonder if we should keep that register bit which says "disable FBC
watermarks" disabled all the time while FBC is disabled... Last time I
checked, we were not doing this.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index d307039..e81221d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2213,7 +2213,6 @@ struct intel_wm_config {
>         unsigned int num_pipes_active;
>         bool sprites_enabled;
>         bool sprites_scaled;
> -       bool fbc_wm_enabled;
>  };
>
>  /*
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute
  2013-10-10 21:43   ` Paulo Zanoni
@ 2013-10-11  8:07     ` Ville Syrjälä
  2013-10-11 13:51       ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11  8:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Thu, Oct 10, 2013 at 06:43:55PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Introduce a new struct intel_pipe_wm which contains all the
> > watermarks for a single pipe. Use it to unify the LP0 and LP1+
> > watermark computations so that we can just iterate through the
> > watermark levels neatly and call ilk_compute_wm_level() for each.
> >
> > Also add another tool ilk_wm_merge() that merges the LP1+ watermarks
> > from all pipes. For that, embed one intel_pipe_wm inside intel_crtc that
> > contains the currently valid watermarks for each pipe.
> >
> > This is mainly preparatory work for pre-computing the watermarks for
> > each pipe and merging them at a later time. For now the merging still
> > happens immediately.
> >
> > v2: Add some comments about level 0 DDB split and intel_wm_config
> >     Add WARN_ON for level 0 being disabled
> >     s/lp_wm/merged
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_drv.h |  12 +++
> >  drivers/gpu/drm/i915/intel_pm.c  | 192 +++++++++++++++++++++++----------------
> >  2 files changed, 128 insertions(+), 76 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 71cfabd..3325b0b 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -309,6 +309,12 @@ struct intel_crtc_config {
> >         bool double_wide;
> >  };
> >
> > +struct intel_pipe_wm {
> > +       struct intel_wm_level wm[5];
> > +       uint32_t linetime;
> > +       bool fbc_wm_enabled;
> > +};
> > +
> >  struct intel_crtc {
> >         struct drm_crtc base;
> >         enum pipe pipe;
> > @@ -349,6 +355,12 @@ struct intel_crtc {
> >         /* Access to these should be protected by dev_priv->irq_lock. */
> >         bool cpu_fifo_underrun_disabled;
> >         bool pch_fifo_underrun_disabled;
> > +
> > +       /* per-pipe watermark state */
> > +       struct {
> > +               /* watermarks currently being used  */
> > +               struct intel_pipe_wm active;
> > +       } wm;
> >  };
> >
> >  struct intel_plane_wm_parameters {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 5e743ec..30b380c 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2458,53 +2458,6 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
> >         result->enable = true;
> >  }
> >
> > -static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
> > -                             int level, const struct hsw_wm_maximums *max,
> > -                             const struct hsw_pipe_wm_parameters *params,
> > -                             struct intel_wm_level *result)
> > -{
> > -       enum pipe pipe;
> > -       struct intel_wm_level res[3];
> > -
> > -       for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
> > -               ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
> > -
> > -       result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
> > -       result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
> > -       result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
> > -       result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
> > -       result->enable = true;
> > -
> > -       return ilk_check_wm(level, max, result);
> > -}
> > -
> > -
> > -static uint32_t hsw_compute_wm_pipe(struct drm_device *dev,
> > -                                   const struct hsw_pipe_wm_parameters *params)
> > -{
> > -       struct drm_i915_private *dev_priv = dev->dev_private;
> > -       struct intel_wm_config config = {
> > -               .num_pipes_active = 1,
> > -               .sprites_enabled = params->spr.enabled,
> > -               .sprites_scaled = params->spr.scaled,
> > -       };
> > -       struct hsw_wm_maximums max;
> > -       struct intel_wm_level res;
> > -
> > -       if (!params->active)
> > -               return 0;
> > -
> > -       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> > -
> > -       ilk_compute_wm_level(dev_priv, 0, params, &res);
> > -
> > -       ilk_check_wm(0, &max, &res);
> > -
> > -       return (res.pri_val << WM0_PIPE_PLANE_SHIFT) |
> > -              (res.spr_val << WM0_PIPE_SPRITE_SHIFT) |
> > -              res.cur_val;
> > -}
> > -
> >  static uint32_t
> >  hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
> >  {
> > @@ -2687,44 +2640,123 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
> >                 *lp_max_5_6 = *lp_max_1_2;
> >  }
> >
> > +/* Compute new watermarks for the pipe */
> > +static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
> > +                                 const struct hsw_pipe_wm_parameters *params,
> > +                                 struct intel_pipe_wm *pipe_wm)
> > +{
> > +       struct drm_device *dev = crtc->dev;
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       int level, max_level = ilk_wm_max_level(dev);
> > +       /* LP0 watermark maximums depend on this pipe alone */
> > +       struct intel_wm_config config = {
> > +               .num_pipes_active = 1,
> > +               .sprites_enabled = params->spr.enabled,
> > +               .sprites_scaled = params->spr.scaled,
> > +       };
> > +       struct hsw_wm_maximums max;
> > +
> > +       memset(pipe_wm, 0, sizeof(*pipe_wm));
> > +
> > +       /* LP0 watermarks always use 1/2 DDB partitioning */
> > +       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> > +
> > +       for (level = 0; level <= max_level; level++)
> > +               ilk_compute_wm_level(dev_priv, level, params,
> > +                                    &pipe_wm->wm[level]);
> > +
> > +       pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
> > +
> > +       /* At least LP0 must be valid */
> > +       return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
> > +}
> > +
> > +/*
> > + * Merge the watermarks from all active pipes for a specific level.
> > + */
> > +static void ilk_merge_wm_level(struct drm_device *dev,
> > +                              int level,
> > +                              struct intel_wm_level *ret_wm)
> > +{
> > +       const struct intel_crtc *intel_crtc;
> > +
> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> > +               const struct intel_wm_level *wm =
> > +                       &intel_crtc->wm.active.wm[level];
> > +
> > +               if (!wm->enable)
> > +                       return;
> 
> Why exactly is this check here and what does it mean? Why not a
> "break" nor a "continue"? Do we expect to ever return at this point?

It means this watermark level wasn't enabled for this pipe, hence this
level (and bigger levels) must not be enabled in the merged watermarks
either.

> 
> It seems intel_compute_pipe_wm calls ilk_compute_wm_level which sets
> "result->enable = true" for everything. Then only level 0 goes through
> ilk_check_wm (which may turn result->enable to zero), but the level1+
> watermarks (which are the ones used in the merge function) never get a
> chance to set wm->enable to false. So the check would be useless.
> Maybe I'm missing something?

Yeah I guess with HSW it would never happen since it doesn't support
sprite scaling, and sprites in general don't restrict watermark levels.

Once we get to to use the same code for older generations, sprites
may cause some watermark levels to be disabled, so this could happen
there. But as multi-pipe LP1+ watermarks are a HSW only feature, we
should never get here on those older generations.

So I guess we could just drop that check or make it a WARN_ON to make
sure we catch problems. Or we could keep it as is, and maybe add an extra
knob to debugfs (or a module param) that would allow the user to
artifically limit watermarks levels. That could be a useful testing
aid in case we run into underrus. I think I actually have a
patch somewhere that does that.

> 
> With the questions above (answered || fixed || clarified || patched):
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> > +
> > +               ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
> > +               ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
> > +               ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
> > +               ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
> > +       }
> > +
> > +       ret_wm->enable = true;
> > +}
> > +
> > +/*
> > + * Merge all low power watermarks for all active pipes.
> > + */
> > +static void ilk_wm_merge(struct drm_device *dev,
> > +                        const struct hsw_wm_maximums *max,
> > +                        struct intel_pipe_wm *merged)
> > +{
> > +       int level, max_level = ilk_wm_max_level(dev);
> > +
> > +       merged->fbc_wm_enabled = true;
> > +
> > +       /* merge each WM1+ level */
> > +       for (level = 1; level <= max_level; level++) {
> > +               struct intel_wm_level *wm = &merged->wm[level];
> > +
> > +               ilk_merge_wm_level(dev, level, wm);
> > +
> > +               if (!ilk_check_wm(level, max, wm))
> > +                       break;
> > +
> > +               /*
> > +                * The spec says it is preferred to disable
> > +                * FBC WMs instead of disabling a WM level.
> > +                */
> > +               if (wm->fbc_val > max->fbc) {
> > +                       merged->fbc_wm_enabled = false;
> > +                       wm->fbc_val = 0;
> > +               }
> > +       }
> > +}
> > +
> >  static void hsw_compute_wm_results(struct drm_device *dev,
> >                                    const struct hsw_pipe_wm_parameters *params,
> >                                    const struct hsw_wm_maximums *lp_maximums,
> >                                    struct hsw_wm_values *results)
> >  {
> > -       struct drm_i915_private *dev_priv = dev->dev_private;
> > -       struct drm_crtc *crtc;
> > -       struct intel_wm_level lp_results[4] = {};
> > -       enum pipe pipe;
> > -       int level, max_level, wm_lp;
> > +       struct intel_crtc *intel_crtc;
> > +       int level, wm_lp;
> > +       struct intel_pipe_wm merged = {};
> >
> > -       for (level = 1; level <= 4; level++)
> > -               if (!hsw_compute_lp_wm(dev_priv, level,
> > -                                      lp_maximums, params,
> > -                                      &lp_results[level - 1]))
> > -                       break;
> > -       max_level = level - 1;
> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
> > +               intel_compute_pipe_wm(&intel_crtc->base,
> > +                                     &params[intel_crtc->pipe],
> > +                                     &intel_crtc->wm.active);
> > +
> > +       ilk_wm_merge(dev, lp_maximums, &merged);
> >
> >         memset(results, 0, sizeof(*results));
> >
> > -       /* The spec says it is preferred to disable FBC WMs instead of disabling
> > -        * a WM level. */
> > -       results->enable_fbc_wm = true;
> > -       for (level = 1; level <= max_level; level++) {
> > -               if (lp_results[level - 1].fbc_val > lp_maximums->fbc) {
> > -                       results->enable_fbc_wm = false;
> > -                       lp_results[level - 1].fbc_val = 0;
> > -               }
> > -       }
> > +       results->enable_fbc_wm = merged.fbc_wm_enabled;
> >
> > +       /* LP1+ register values */
> >         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> >                 const struct intel_wm_level *r;
> >
> > -               level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
> > -               if (level > max_level)
> > +               level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
> > +
> > +               r = &merged.wm[level];
> > +               if (!r->enable)
> >                         break;
> >
> > -               r = &lp_results[level - 1];
> >                 results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
> >                                                           r->fbc_val,
> >                                                           r->pri_val,
> > @@ -2732,13 +2764,21 @@ static void hsw_compute_wm_results(struct drm_device *dev,
> >                 results->wm_lp_spr[wm_lp - 1] = r->spr_val;
> >         }
> >
> > -       for_each_pipe(pipe)
> > -               results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev,
> > -                                                            &params[pipe]);
> > +       /* LP0 register values */
> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
> > +               enum pipe pipe = intel_crtc->pipe;
> > +               const struct intel_wm_level *r =
> > +                       &intel_crtc->wm.active.wm[0];
> >
> > -       for_each_pipe(pipe) {
> > -               crtc = dev_priv->pipe_to_crtc_mapping[pipe];
> > -               results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
> > +               if (WARN_ON(!r->enable))
> > +                       continue;
> > +
> > +               results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
> > +
> > +               results->wm_pipe[pipe] =
> > +                       (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
> > +                       (r->spr_val << WM0_PIPE_SPRITE_SHIFT) |
> > +                       r->cur_val;
> >         }
> >  }
> >
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation
  2013-10-10 22:42   ` Paulo Zanoni
@ 2013-10-11  8:10     ` Ville Syrjälä
  0 siblings, 0 replies; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11  8:10 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Thu, Oct 10, 2013 at 07:42:22PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > On HSW the LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4. We make the
> > conversion from LPn to to the level at one point current. Later we're
> > going to do it in a few places, so move it to a separate function.
> 
> I guess this function will work on ILK/SNB/IVB even though they don't
> follow this rule, right? If yes: Reviewed-by: Paulo Zanoni
> <paulo.r.zanoni@intel.com>

Yes, level 4 is never enabled on those, so we never do the +1.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 8 +++++++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index c17518d..d307039 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2705,6 +2705,12 @@ static void ilk_wm_merge(struct drm_device *dev,
> >         }
> >  }
> >
> > +static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
> > +{
> > +       /* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4 */
> > +       return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable);
> > +}
> > +
> >  static void hsw_compute_wm_results(struct drm_device *dev,
> >                                    const struct intel_pipe_wm *merged,
> >                                    struct hsw_wm_values *results)
> > @@ -2718,7 +2724,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
> >         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> >                 const struct intel_wm_level *r;
> >
> > -               level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable);
> > +               level = ilk_wm_lp_to_level(wm_lp, merged);
> >
> >                 r = &merged->wm[level];
> >                 if (!r->enable)
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters()
  2013-10-10 22:34   ` Paulo Zanoni
@ 2013-10-11  8:26     ` Ville Syrjälä
  2013-10-11 12:26       ` [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled ville.syrjala
  2013-10-11 13:53       ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() Paulo Zanoni
  0 siblings, 2 replies; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11  8:26 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Thu, Oct 10, 2013 at 07:34:38PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Move the watermark max computations into haswell_update_wm(). This
> > allows keeping the 1/2 vs. 5/6 split code in one place, and avoid having
> > to pass around so many things. We also save a bit of stack space by only
> > requiring one copy of struct hsw_wm_maximums.
> >
> > Also move the intel_wm_config out from hsw_compute_wm_parameters() and
> > pass it it. We'll have some need for it in haswell_update_wm() later.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++-------------------
> >  1 file changed, 14 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index b09715f..0fe6c36 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2586,13 +2586,11 @@ static void intel_setup_wm_latency(struct drm_device *dev)
> >
> >  static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
> >                                       struct hsw_pipe_wm_parameters *p,
> > -                                     struct hsw_wm_maximums *lp_max_1_2,
> > -                                     struct hsw_wm_maximums *lp_max_5_6)
> > +                                     struct intel_wm_config *config)
> >  {
> >         struct drm_device *dev = crtc->dev;
> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >         enum pipe pipe = intel_crtc->pipe;
> > -       struct intel_wm_config config = {};
> >         struct drm_plane *plane;
> >
> >         p->active = intel_crtc_active(crtc);
> > @@ -2609,7 +2607,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
> >         }
> >
> >         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> > -               config.num_pipes_active += intel_crtc_active(crtc);
> > +               config->num_pipes_active += intel_crtc_active(crtc);
> >
> >         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> >                 struct intel_plane *intel_plane = to_intel_plane(plane);
> > @@ -2617,17 +2615,9 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
> >                 if (intel_plane->pipe == pipe)
> >                         p->spr = intel_plane->wm;
> >
> > -               config.sprites_enabled |= intel_plane->wm.enabled;
> > -               config.sprites_scaled |= intel_plane->wm.scaled;
> > +               config->sprites_enabled |= intel_plane->wm.enabled;
> > +               config->sprites_scaled |= intel_plane->wm.scaled;
> >         }
> > -
> > -       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
> > -
> > -       /* 5/6 split only in single pipe config on IVB+ */
> > -       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1)
> > -               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
> > -       else
> > -               *lp_max_5_6 = *lp_max_1_2;
> >  }
> >
> >  /* Compute new watermarks for the pipe */
> > @@ -2889,14 +2879,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >         struct drm_device *dev = crtc->dev;
> >         struct drm_i915_private *dev_priv = dev->dev_private;
> > -       struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
> > +       struct hsw_wm_maximums max;
> >         struct hsw_pipe_wm_parameters params = {};
> >         struct hsw_wm_values results = {};
> >         enum intel_ddb_partitioning partitioning;
> >         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 = {};
> >
> > -       hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
> > +       hsw_compute_wm_parameters(crtc, &params, &config);
> >
> >         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
> >
> > @@ -2905,10 +2896,14 @@ static void haswell_update_wm(struct drm_crtc *crtc)
> >
> >         intel_crtc->wm.active = pipe_wm;
> >
> > -       ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
> > -       ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
> > +       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
> > +       ilk_wm_merge(dev, &max, &lp_wm_1_2);
> > +
> > +       /* 5/6 split only in single pipe config on IVB+ */
> > +       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {
> 
> No need to calculate 5_6 on zero pipes, I guess.
> 
> 
> > +               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
> > +               ilk_wm_merge(dev, &max, &lp_wm_5_6);
> 
> Oh, so now you've moved ilk_wm_merge to the "if" statement, as I
> requested on the review to a previous patch :)
> 
> >
> > -       if (lp_max_1_2.pri != lp_max_5_6.pri) {
> 
> By removing this check, you're now also calculating 5_6 watermarks for
> the case where we just have 1 pipe but the sprites are disabled.

Hmm, right. I guess we should just add a more explicit
config.sprites_enabled check here to avoid that overhead.

> 
> 
> >                 best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
> >         } else {
> >                 best_lp_wm = &lp_wm_1_2;
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled
  2013-10-11  8:26     ` Ville Syrjälä
@ 2013-10-11 12:26       ` ville.syrjala
  2013-10-11 17:21         ` Paulo Zanoni
  2013-10-11 13:53       ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() Paulo Zanoni
  1 sibling, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-11 12:26 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Using the 5/6 DDB split make sense only when sprites are enabled.
So check that before we waste any cycles computing the merged
watermarks with the 5/6 DDB split.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 211a946..214a8de 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2958,7 +2958,8 @@ static void haswell_update_wm(struct drm_crtc *crtc)
 	ilk_wm_merge(dev, &max, &lp_wm_1_2);
 
 	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {
+	if (INTEL_INFO(dev)->gen >= 7 &&
+	    config.num_pipes_active == 1 && config.sprites_enabled) {
 		ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
 		ilk_wm_merge(dev, &max, &lp_wm_5_6);
 
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute
  2013-10-11  8:07     ` Ville Syrjälä
@ 2013-10-11 13:51       ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 13:51 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Thu, Oct 10, 2013 at 06:43:55PM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Introduce a new struct intel_pipe_wm which contains all the
>> > watermarks for a single pipe. Use it to unify the LP0 and LP1+
>> > watermark computations so that we can just iterate through the
>> > watermark levels neatly and call ilk_compute_wm_level() for each.
>> >
>> > Also add another tool ilk_wm_merge() that merges the LP1+ watermarks
>> > from all pipes. For that, embed one intel_pipe_wm inside intel_crtc that
>> > contains the currently valid watermarks for each pipe.
>> >
>> > This is mainly preparatory work for pre-computing the watermarks for
>> > each pipe and merging them at a later time. For now the merging still
>> > happens immediately.
>> >
>> > v2: Add some comments about level 0 DDB split and intel_wm_config
>> >     Add WARN_ON for level 0 being disabled
>> >     s/lp_wm/merged
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_drv.h |  12 +++
>> >  drivers/gpu/drm/i915/intel_pm.c  | 192 +++++++++++++++++++++++----------------
>> >  2 files changed, 128 insertions(+), 76 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> > index 71cfabd..3325b0b 100644
>> > --- a/drivers/gpu/drm/i915/intel_drv.h
>> > +++ b/drivers/gpu/drm/i915/intel_drv.h
>> > @@ -309,6 +309,12 @@ struct intel_crtc_config {
>> >         bool double_wide;
>> >  };
>> >
>> > +struct intel_pipe_wm {
>> > +       struct intel_wm_level wm[5];
>> > +       uint32_t linetime;
>> > +       bool fbc_wm_enabled;
>> > +};
>> > +
>> >  struct intel_crtc {
>> >         struct drm_crtc base;
>> >         enum pipe pipe;
>> > @@ -349,6 +355,12 @@ struct intel_crtc {
>> >         /* Access to these should be protected by dev_priv->irq_lock. */
>> >         bool cpu_fifo_underrun_disabled;
>> >         bool pch_fifo_underrun_disabled;
>> > +
>> > +       /* per-pipe watermark state */
>> > +       struct {
>> > +               /* watermarks currently being used  */
>> > +               struct intel_pipe_wm active;
>> > +       } wm;
>> >  };
>> >
>> >  struct intel_plane_wm_parameters {
>> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> > index 5e743ec..30b380c 100644
>> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> > @@ -2458,53 +2458,6 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
>> >         result->enable = true;
>> >  }
>> >
>> > -static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
>> > -                             int level, const struct hsw_wm_maximums *max,
>> > -                             const struct hsw_pipe_wm_parameters *params,
>> > -                             struct intel_wm_level *result)
>> > -{
>> > -       enum pipe pipe;
>> > -       struct intel_wm_level res[3];
>> > -
>> > -       for (pipe = PIPE_A; pipe <= PIPE_C; pipe++)
>> > -               ilk_compute_wm_level(dev_priv, level, &params[pipe], &res[pipe]);
>> > -
>> > -       result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val);
>> > -       result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val);
>> > -       result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val);
>> > -       result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val);
>> > -       result->enable = true;
>> > -
>> > -       return ilk_check_wm(level, max, result);
>> > -}
>> > -
>> > -
>> > -static uint32_t hsw_compute_wm_pipe(struct drm_device *dev,
>> > -                                   const struct hsw_pipe_wm_parameters *params)
>> > -{
>> > -       struct drm_i915_private *dev_priv = dev->dev_private;
>> > -       struct intel_wm_config config = {
>> > -               .num_pipes_active = 1,
>> > -               .sprites_enabled = params->spr.enabled,
>> > -               .sprites_scaled = params->spr.scaled,
>> > -       };
>> > -       struct hsw_wm_maximums max;
>> > -       struct intel_wm_level res;
>> > -
>> > -       if (!params->active)
>> > -               return 0;
>> > -
>> > -       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
>> > -
>> > -       ilk_compute_wm_level(dev_priv, 0, params, &res);
>> > -
>> > -       ilk_check_wm(0, &max, &res);
>> > -
>> > -       return (res.pri_val << WM0_PIPE_PLANE_SHIFT) |
>> > -              (res.spr_val << WM0_PIPE_SPRITE_SHIFT) |
>> > -              res.cur_val;
>> > -}
>> > -
>> >  static uint32_t
>> >  hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
>> >  {
>> > @@ -2687,44 +2640,123 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
>> >                 *lp_max_5_6 = *lp_max_1_2;
>> >  }
>> >
>> > +/* Compute new watermarks for the pipe */
>> > +static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>> > +                                 const struct hsw_pipe_wm_parameters *params,
>> > +                                 struct intel_pipe_wm *pipe_wm)
>> > +{
>> > +       struct drm_device *dev = crtc->dev;
>> > +       struct drm_i915_private *dev_priv = dev->dev_private;
>> > +       int level, max_level = ilk_wm_max_level(dev);
>> > +       /* LP0 watermark maximums depend on this pipe alone */
>> > +       struct intel_wm_config config = {
>> > +               .num_pipes_active = 1,
>> > +               .sprites_enabled = params->spr.enabled,
>> > +               .sprites_scaled = params->spr.scaled,
>> > +       };
>> > +       struct hsw_wm_maximums max;
>> > +
>> > +       memset(pipe_wm, 0, sizeof(*pipe_wm));
>> > +
>> > +       /* LP0 watermarks always use 1/2 DDB partitioning */
>> > +       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
>> > +
>> > +       for (level = 0; level <= max_level; level++)
>> > +               ilk_compute_wm_level(dev_priv, level, params,
>> > +                                    &pipe_wm->wm[level]);
>> > +
>> > +       pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
>> > +
>> > +       /* At least LP0 must be valid */
>> > +       return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
>> > +}
>> > +
>> > +/*
>> > + * Merge the watermarks from all active pipes for a specific level.
>> > + */
>> > +static void ilk_merge_wm_level(struct drm_device *dev,
>> > +                              int level,
>> > +                              struct intel_wm_level *ret_wm)
>> > +{
>> > +       const struct intel_crtc *intel_crtc;
>> > +
>> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
>> > +               const struct intel_wm_level *wm =
>> > +                       &intel_crtc->wm.active.wm[level];
>> > +
>> > +               if (!wm->enable)
>> > +                       return;
>>
>> Why exactly is this check here and what does it mean? Why not a
>> "break" nor a "continue"? Do we expect to ever return at this point?
>
> It means this watermark level wasn't enabled for this pipe, hence this
> level (and bigger levels) must not be enabled in the merged watermarks
> either.
>
>>
>> It seems intel_compute_pipe_wm calls ilk_compute_wm_level which sets
>> "result->enable = true" for everything. Then only level 0 goes through
>> ilk_check_wm (which may turn result->enable to zero), but the level1+
>> watermarks (which are the ones used in the merge function) never get a
>> chance to set wm->enable to false. So the check would be useless.
>> Maybe I'm missing something?
>
> Yeah I guess with HSW it would never happen since it doesn't support
> sprite scaling, and sprites in general don't restrict watermark levels.
>
> Once we get to to use the same code for older generations, sprites
> may cause some watermark levels to be disabled, so this could happen
> there. But as multi-pipe LP1+ watermarks are a HSW only feature, we
> should never get here on those older generations.
>
> So I guess we could just drop that check or make it a WARN_ON to make
> sure we catch problems. Or we could keep it as is, and maybe add an extra
> knob to debugfs (or a module param) that would allow the user to
> artifically limit watermarks levels. That could be a useful testing
> aid in case we run into underrus. I think I actually have a
> patch somewhere that does that.
>

Thanks for the clarification. Since it seems correct, it makes sense
to merge this patch and then do any additional work as future patches.

>>
>> With the questions above (answered || fixed || clarified || patched):
>>
>> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> > +
>> > +               ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val);
>> > +               ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val);
>> > +               ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val);
>> > +               ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val);
>> > +       }
>> > +
>> > +       ret_wm->enable = true;
>> > +}
>> > +
>> > +/*
>> > + * Merge all low power watermarks for all active pipes.
>> > + */
>> > +static void ilk_wm_merge(struct drm_device *dev,
>> > +                        const struct hsw_wm_maximums *max,
>> > +                        struct intel_pipe_wm *merged)
>> > +{
>> > +       int level, max_level = ilk_wm_max_level(dev);
>> > +
>> > +       merged->fbc_wm_enabled = true;
>> > +
>> > +       /* merge each WM1+ level */
>> > +       for (level = 1; level <= max_level; level++) {
>> > +               struct intel_wm_level *wm = &merged->wm[level];
>> > +
>> > +               ilk_merge_wm_level(dev, level, wm);
>> > +
>> > +               if (!ilk_check_wm(level, max, wm))
>> > +                       break;
>> > +
>> > +               /*
>> > +                * The spec says it is preferred to disable
>> > +                * FBC WMs instead of disabling a WM level.
>> > +                */
>> > +               if (wm->fbc_val > max->fbc) {
>> > +                       merged->fbc_wm_enabled = false;
>> > +                       wm->fbc_val = 0;
>> > +               }
>> > +       }
>> > +}
>> > +
>> >  static void hsw_compute_wm_results(struct drm_device *dev,
>> >                                    const struct hsw_pipe_wm_parameters *params,
>> >                                    const struct hsw_wm_maximums *lp_maximums,
>> >                                    struct hsw_wm_values *results)
>> >  {
>> > -       struct drm_i915_private *dev_priv = dev->dev_private;
>> > -       struct drm_crtc *crtc;
>> > -       struct intel_wm_level lp_results[4] = {};
>> > -       enum pipe pipe;
>> > -       int level, max_level, wm_lp;
>> > +       struct intel_crtc *intel_crtc;
>> > +       int level, wm_lp;
>> > +       struct intel_pipe_wm merged = {};
>> >
>> > -       for (level = 1; level <= 4; level++)
>> > -               if (!hsw_compute_lp_wm(dev_priv, level,
>> > -                                      lp_maximums, params,
>> > -                                      &lp_results[level - 1]))
>> > -                       break;
>> > -       max_level = level - 1;
>> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
>> > +               intel_compute_pipe_wm(&intel_crtc->base,
>> > +                                     &params[intel_crtc->pipe],
>> > +                                     &intel_crtc->wm.active);
>> > +
>> > +       ilk_wm_merge(dev, lp_maximums, &merged);
>> >
>> >         memset(results, 0, sizeof(*results));
>> >
>> > -       /* The spec says it is preferred to disable FBC WMs instead of disabling
>> > -        * a WM level. */
>> > -       results->enable_fbc_wm = true;
>> > -       for (level = 1; level <= max_level; level++) {
>> > -               if (lp_results[level - 1].fbc_val > lp_maximums->fbc) {
>> > -                       results->enable_fbc_wm = false;
>> > -                       lp_results[level - 1].fbc_val = 0;
>> > -               }
>> > -       }
>> > +       results->enable_fbc_wm = merged.fbc_wm_enabled;
>> >
>> > +       /* LP1+ register values */
>> >         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
>> >                 const struct intel_wm_level *r;
>> >
>> > -               level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp;
>> > -               if (level > max_level)
>> > +               level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable);
>> > +
>> > +               r = &merged.wm[level];
>> > +               if (!r->enable)
>> >                         break;
>> >
>> > -               r = &lp_results[level - 1];
>> >                 results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2,
>> >                                                           r->fbc_val,
>> >                                                           r->pri_val,
>> > @@ -2732,13 +2764,21 @@ static void hsw_compute_wm_results(struct drm_device *dev,
>> >                 results->wm_lp_spr[wm_lp - 1] = r->spr_val;
>> >         }
>> >
>> > -       for_each_pipe(pipe)
>> > -               results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev,
>> > -                                                            &params[pipe]);
>> > +       /* LP0 register values */
>> > +       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
>> > +               enum pipe pipe = intel_crtc->pipe;
>> > +               const struct intel_wm_level *r =
>> > +                       &intel_crtc->wm.active.wm[0];
>> >
>> > -       for_each_pipe(pipe) {
>> > -               crtc = dev_priv->pipe_to_crtc_mapping[pipe];
>> > -               results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc);
>> > +               if (WARN_ON(!r->enable))
>> > +                       continue;
>> > +
>> > +               results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
>> > +
>> > +               results->wm_pipe[pipe] =
>> > +                       (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
>> > +                       (r->spr_val << WM0_PIPE_SPRITE_SHIFT) |
>> > +                       r->cur_val;
>> >         }
>> >  }
>> >
>> > --
>> > 1.8.1.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters()
  2013-10-11  8:26     ` Ville Syrjälä
  2013-10-11 12:26       ` [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled ville.syrjala
@ 2013-10-11 13:53       ` Paulo Zanoni
  1 sibling, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 13:53 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Thu, Oct 10, 2013 at 07:34:38PM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Move the watermark max computations into haswell_update_wm(). This
>> > allows keeping the 1/2 vs. 5/6 split code in one place, and avoid having
>> > to pass around so many things. We also save a bit of stack space by only
>> > requiring one copy of struct hsw_wm_maximums.
>> >
>> > Also move the intel_wm_config out from hsw_compute_wm_parameters() and
>> > pass it it. We'll have some need for it in haswell_update_wm() later.
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++-------------------
>> >  1 file changed, 14 insertions(+), 19 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> > index b09715f..0fe6c36 100644
>> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> > @@ -2586,13 +2586,11 @@ static void intel_setup_wm_latency(struct drm_device *dev)
>> >
>> >  static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>> >                                       struct hsw_pipe_wm_parameters *p,
>> > -                                     struct hsw_wm_maximums *lp_max_1_2,
>> > -                                     struct hsw_wm_maximums *lp_max_5_6)
>> > +                                     struct intel_wm_config *config)
>> >  {
>> >         struct drm_device *dev = crtc->dev;
>> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> >         enum pipe pipe = intel_crtc->pipe;
>> > -       struct intel_wm_config config = {};
>> >         struct drm_plane *plane;
>> >
>> >         p->active = intel_crtc_active(crtc);
>> > @@ -2609,7 +2607,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>> >         }
>> >
>> >         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
>> > -               config.num_pipes_active += intel_crtc_active(crtc);
>> > +               config->num_pipes_active += intel_crtc_active(crtc);
>> >
>> >         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
>> >                 struct intel_plane *intel_plane = to_intel_plane(plane);
>> > @@ -2617,17 +2615,9 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
>> >                 if (intel_plane->pipe == pipe)
>> >                         p->spr = intel_plane->wm;
>> >
>> > -               config.sprites_enabled |= intel_plane->wm.enabled;
>> > -               config.sprites_scaled |= intel_plane->wm.scaled;
>> > +               config->sprites_enabled |= intel_plane->wm.enabled;
>> > +               config->sprites_scaled |= intel_plane->wm.scaled;
>> >         }
>> > -
>> > -       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2);
>> > -
>> > -       /* 5/6 split only in single pipe config on IVB+ */
>> > -       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1)
>> > -               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6);
>> > -       else
>> > -               *lp_max_5_6 = *lp_max_1_2;
>> >  }
>> >
>> >  /* Compute new watermarks for the pipe */
>> > @@ -2889,14 +2879,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>> >         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> >         struct drm_device *dev = crtc->dev;
>> >         struct drm_i915_private *dev_priv = dev->dev_private;
>> > -       struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
>> > +       struct hsw_wm_maximums max;
>> >         struct hsw_pipe_wm_parameters params = {};
>> >         struct hsw_wm_values results = {};
>> >         enum intel_ddb_partitioning partitioning;
>> >         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 = {};
>> >
>> > -       hsw_compute_wm_parameters(crtc, &params, &lp_max_1_2, &lp_max_5_6);
>> > +       hsw_compute_wm_parameters(crtc, &params, &config);
>> >
>> >         intel_compute_pipe_wm(crtc, &params, &pipe_wm);
>> >
>> > @@ -2905,10 +2896,14 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>> >
>> >         intel_crtc->wm.active = pipe_wm;
>> >
>> > -       ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2);
>> > -       ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6);
>> > +       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
>> > +       ilk_wm_merge(dev, &max, &lp_wm_1_2);
>> > +
>> > +       /* 5/6 split only in single pipe config on IVB+ */
>> > +       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) {
>>
>> No need to calculate 5_6 on zero pipes, I guess.
>>
>>
>> > +               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
>> > +               ilk_wm_merge(dev, &max, &lp_wm_5_6);
>>
>> Oh, so now you've moved ilk_wm_merge to the "if" statement, as I
>> requested on the review to a previous patch :)
>>
>> >
>> > -       if (lp_max_1_2.pri != lp_max_5_6.pri) {
>>
>> By removing this check, you're now also calculating 5_6 watermarks for
>> the case where we just have 1 pipe but the sprites are disabled.
>
> Hmm, right. I guess we should just add a more explicit
> config.sprites_enabled check here to avoid that overhead.

Since you've addressed this issue on patch 17/16, and it's just an
optimization, not a real bug:

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

>
>>
>>
>> >                 best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
>> >         } else {
>> >                 best_lp_wm = &lp_wm_1_2;
>> > --
>> > 1.8.1.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm
  2013-10-09 16:18 ` [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm ville.syrjala
@ 2013-10-11 14:21   ` Paulo Zanoni
  2013-10-15  8:24     ` Daniel Vetter
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 14:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> To make it easier to check what watermark updates are actually
> necessary, keep copies of the relevant bits that match the current
> hardware state.
>
> Also add DDB partitioning into hsw_wm_values as that's another piece
> of state we want to track.
>
> We don't read out the hardware state on init yet, so we can't really
> start using this yet, but it will be used later.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h | 12 +++++++++++
>  drivers/gpu/drm/i915/intel_pm.c | 46 ++++++++++++++---------------------------
>  2 files changed, 27 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 9cac93c..478d17c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1140,6 +1140,15 @@ struct intel_wm_level {
>         uint32_t fbc_val;
>  };
>
> +struct hsw_wm_values {
> +       uint32_t wm_pipe[3];
> +       uint32_t wm_lp[3];
> +       uint32_t wm_lp_spr[3];
> +       uint32_t wm_linetime[3];
> +       bool enable_fbc_wm;
> +       enum intel_ddb_partitioning partitioning;
> +};
> +
>  /*
>   * This struct tracks the state needed for the Package C8+ feature.
>   *
> @@ -1399,6 +1408,9 @@ typedef struct drm_i915_private {
>                 uint16_t spr_latency[5];
>                 /* cursor */
>                 uint16_t cur_latency[5];
> +
> +               /* current hardware state */
> +               struct hsw_wm_values hw;
>         } wm;
>
>         struct i915_package_c8 pc8;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e81221d..bed96fb 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2200,14 +2200,6 @@ struct hsw_wm_maximums {
>         uint16_t fbc;
>  };
>
> -struct hsw_wm_values {
> -       uint32_t wm_pipe[3];
> -       uint32_t wm_lp[3];
> -       uint32_t wm_lp_spr[3];
> -       uint32_t wm_linetime[3];
> -       bool enable_fbc_wm;
> -};
> -
>  /* used in computing the new watermarks state */
>  struct intel_wm_config {
>         unsigned int num_pipes_active;
> @@ -2712,12 +2704,14 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
>
>  static void hsw_compute_wm_results(struct drm_device *dev,
>                                    const struct intel_pipe_wm *merged,
> +                                  enum intel_ddb_partitioning partitioning,
>                                    struct hsw_wm_values *results)
>  {
>         struct intel_crtc *intel_crtc;
>         int level, wm_lp;
>
>         results->enable_fbc_wm = merged->fbc_wm_enabled;
> +       results->partitioning = partitioning;
>
>         /* LP1+ register values */
>         for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> @@ -2787,13 +2781,10 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
>   * causes WMs to be re-evaluated, expending some power.
>   */
>  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> -                               struct hsw_wm_values *results,
> -                               enum intel_ddb_partitioning partitioning)
> +                               struct hsw_wm_values *results)
>  {
>         struct hsw_wm_values previous;
>         uint32_t val;
> -       enum intel_ddb_partitioning prev_partitioning;
> -       bool prev_enable_fbc_wm;
>
>         previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
>         previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> @@ -2808,21 +2799,12 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>         previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
>         previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
>
> -       prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> +       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
>                                 INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
>
> -       prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> -
> -       if (memcmp(results->wm_pipe, previous.wm_pipe,
> -                  sizeof(results->wm_pipe)) == 0 &&
> -           memcmp(results->wm_lp, previous.wm_lp,
> -                  sizeof(results->wm_lp)) == 0 &&
> -           memcmp(results->wm_lp_spr, previous.wm_lp_spr,
> -                  sizeof(results->wm_lp_spr)) == 0 &&
> -           memcmp(results->wm_linetime, previous.wm_linetime,
> -                  sizeof(results->wm_linetime)) == 0 &&
> -           partitioning == prev_partitioning &&
> -           results->enable_fbc_wm == prev_enable_fbc_wm)
> +       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +
> +       if (memcmp(results, &previous, sizeof(*results)) == 0)

This may cause problems since we're also comparing the structure
paddings. It seems "results" is already zero-initialized, so if you
also zero-initialize "previous" we'll probably be fine with the
memcmp(). But my fear is that future code changes will break this, so
if you stick with the new memcmp please add a comment remembering us
that we rely on zero-initializing stuff. Or maybe keep the
old-big-ugly code.


>                 return;
>
>         if (previous.wm_lp[2] != 0)
> @@ -2846,16 +2828,16 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>         if (previous.wm_linetime[2] != results->wm_linetime[2])
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
>
> -       if (prev_partitioning != partitioning) {
> +       if (previous.partitioning != results->partitioning) {
>                 val = I915_READ(WM_MISC);
> -               if (partitioning == INTEL_DDB_PART_1_2)
> +               if (results->partitioning == INTEL_DDB_PART_1_2)
>                         val &= ~WM_MISC_DATA_PARTITION_5_6;
>                 else
>                         val |= WM_MISC_DATA_PARTITION_5_6;
>                 I915_WRITE(WM_MISC, val);
>         }
>
> -       if (prev_enable_fbc_wm != results->enable_fbc_wm) {
> +       if (previous.enable_fbc_wm != results->enable_fbc_wm) {
>                 val = I915_READ(DISP_ARB_CTL);
>                 if (results->enable_fbc_wm)
>                         val &= ~DISP_FBC_WM_DIS;
> @@ -2877,6 +2859,8 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
>         if (results->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> +
> +       dev_priv->wm.hw = *results;
>  }
>
>  static void haswell_update_wm(struct drm_crtc *crtc)
> @@ -2914,12 +2898,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>                 best_lp_wm = &lp_wm_1_2;
>         }
>
> -       hsw_compute_wm_results(dev, best_lp_wm, &results);
> -
>         partitioning = (best_lp_wm == &lp_wm_1_2) ?
>                        INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
>
> -       hsw_write_wm_values(dev_priv, &results, partitioning);
> +       hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results);
> +
> +       hsw_write_wm_values(dev_priv, &results);
>  }
>
>  static void haswell_update_sprite_wm(struct drm_plane *plane,
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-09 16:18 ` [PATCH 10/16] drm/i915: Improve watermark dirtyness checks ville.syrjala
@ 2013-10-11 15:02   ` Paulo Zanoni
  2013-10-11 15:48     ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 15:02 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Currently hsw_write_vm_values() may write to certain watermark
> registers needlessly. For instance it will disable LP1+ watermarks
> around WM_PIPE changes even though that's not needed. Also if only,
> say, LP3 changes, the current code will again disable all LP1+
> watermarks even though only LP3 needs to be reconfigured.
>
> Add an easy to read function that will compute the dirtyness of the
> watermarks, and use that information to further optimize the watermark
> programming.

Clever solution to the problem!

Some comments below.


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 95 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 77 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index bed96fb..5bd8c73 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2776,6 +2776,63 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
>         }
>  }
>
> +/* dirty bits used to track which watermarks need changes */
> +#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
> +#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
> +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
> +#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
> +#define WM_DIRTY_FBC (1 << 24)
> +#define WM_DIRTY_DDB (1 << 25)
> +
> +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> +                                        const struct hsw_wm_values *old,
> +                                        const struct hsw_wm_values *new)
> +{
> +       unsigned int dirty = 0;
> +       enum pipe pipe;
> +       int wm_lp;
> +
> +       for_each_pipe(pipe) {
> +               if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
> +                       dirty |= WM_DIRTY_LINETIME(pipe);
> +                       /* Must disable LP1+ watermarks too */
> +                       dirty |= WM_DIRTY_LP_ALL;
> +               }
> +
> +               if (old->wm_pipe[pipe] != new->wm_pipe[pipe])
> +                       dirty |= WM_DIRTY_PIPE(pipe);

I think this one also needs WM_DIRTY_LP_ALL. I don't think changing
level zero without stopping the LP levels is safe.


> +       }
> +
> +       if (old->enable_fbc_wm != new->enable_fbc_wm) {
> +               dirty |= WM_DIRTY_FBC;
> +               /* Must disable LP1+ watermarks too */
> +               dirty |= WM_DIRTY_LP_ALL;
> +       }
> +
> +       if (old->partitioning != new->partitioning) {
> +               dirty |= WM_DIRTY_DDB;
> +               /* Must disable LP1+ watermarks too */
> +               dirty |= WM_DIRTY_LP_ALL;
> +       }
> +
> +       /* LP1+ watermarks already deemed dirty, no need to continue */
> +       if (dirty & WM_DIRTY_LP_ALL)
> +               return dirty;
> +
> +       /* Find the lowest numbered LP1+ watermark in need of an update... */
> +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> +               if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
> +                   old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
> +                       break;
> +       }
> +
> +       /* ...and mark it and all higher numbered LP1+ watermarks as dirty */
> +       for (; wm_lp <= 3; wm_lp++)
> +               dirty |= WM_DIRTY_LP(wm_lp);
> +
> +       return dirty;
> +}
> +
>  /*
>   * The spec says we shouldn't write when we don't need, because every write
>   * causes WMs to be re-evaluated, expending some power.
> @@ -2784,6 +2841,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                                 struct hsw_wm_values *results)
>  {
>         struct hsw_wm_values previous;
> +       unsigned int dirty;
>         uint32_t val;
>
>         previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> @@ -2804,31 +2862,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>
>         previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>
> -       if (memcmp(results, &previous, sizeof(*results)) == 0)

Oh, you've just removed the memcmp I complained about... Still, I
believe it had a bug.


> +       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> +       if (!dirty)
>                 return;
>
> -       if (previous.wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, 0);
> -       if (previous.wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, 0);
> -       if (previous.wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, 0);
>
> -       if (previous.wm_pipe[0] != results->wm_pipe[0])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_A))
>                 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
> -       if (previous.wm_pipe[1] != results->wm_pipe[1])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_B))
>                 I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
> -       if (previous.wm_pipe[2] != results->wm_pipe[2])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_C))
>                 I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
>
> -       if (previous.wm_linetime[0] != results->wm_linetime[0])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_A))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
> -       if (previous.wm_linetime[1] != results->wm_linetime[1])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_B))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
> -       if (previous.wm_linetime[2] != results->wm_linetime[2])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_C))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
>
> -       if (previous.partitioning != results->partitioning) {
> +       if (dirty & WM_DIRTY_DDB) {
>                 val = I915_READ(WM_MISC);
>                 if (results->partitioning == INTEL_DDB_PART_1_2)
>                         val &= ~WM_MISC_DATA_PARTITION_5_6;
> @@ -2837,7 +2896,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(WM_MISC, val);
>         }
>
> -       if (previous.enable_fbc_wm != results->enable_fbc_wm) {
> +       if (dirty & WM_DIRTY_FBC) {
>                 val = I915_READ(DISP_ARB_CTL);
>                 if (results->enable_fbc_wm)
>                         val &= ~DISP_FBC_WM_DIS;
> @@ -2846,18 +2905,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(DISP_ARB_CTL, val);
>         }
>
> -       if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);

As far as I understood, if previous.wm_lp_spr[X] !=
results->wm_lp_spr[X], then for sure "dirty & WM_DIRTY_LP(X)", right?
So the "dirty" check would be redundant here. And we can't remove the
second part because we can have "dirty & WM_DIRTY_LP(X) while the
sprite values don't change.


> -       if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> -       if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>
> -       if (results->wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
> -       if (results->wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> -       if (results->wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
>
>         dev_priv->wm.hw = *results;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-11 15:02   ` Paulo Zanoni
@ 2013-10-11 15:48     ` Ville Syrjälä
  2013-10-11 16:12       ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11 15:48 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 12:02:53PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Currently hsw_write_vm_values() may write to certain watermark
> > registers needlessly. For instance it will disable LP1+ watermarks
> > around WM_PIPE changes even though that's not needed. Also if only,
> > say, LP3 changes, the current code will again disable all LP1+
> > watermarks even though only LP3 needs to be reconfigured.
> >
> > Add an easy to read function that will compute the dirtyness of the
> > watermarks, and use that information to further optimize the watermark
> > programming.
> 
> Clever solution to the problem!
> 
> Some comments below.
> 
> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 95 +++++++++++++++++++++++++++++++++--------
> >  1 file changed, 77 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index bed96fb..5bd8c73 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2776,6 +2776,63 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
> >         }
> >  }
> >
> > +/* dirty bits used to track which watermarks need changes */
> > +#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
> > +#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
> > +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
> > +#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
> > +#define WM_DIRTY_FBC (1 << 24)
> > +#define WM_DIRTY_DDB (1 << 25)
> > +
> > +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> > +                                        const struct hsw_wm_values *old,
> > +                                        const struct hsw_wm_values *new)
> > +{
> > +       unsigned int dirty = 0;
> > +       enum pipe pipe;
> > +       int wm_lp;
> > +
> > +       for_each_pipe(pipe) {
> > +               if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
> > +                       dirty |= WM_DIRTY_LINETIME(pipe);
> > +                       /* Must disable LP1+ watermarks too */
> > +                       dirty |= WM_DIRTY_LP_ALL;
> > +               }
> > +
> > +               if (old->wm_pipe[pipe] != new->wm_pipe[pipe])
> > +                       dirty |= WM_DIRTY_PIPE(pipe);
> 
> I think this one also needs WM_DIRTY_LP_ALL. I don't think changing
> level zero without stopping the LP levels is safe.

Dunno. Spec doesn't tell me to do it. Although I haven't even bothered
to check how hard it would be to cook up a configuration where just
WM_PIPE changes but WM_LPx stays the same.

Actually the spec doesn't even say that we should disable a particular
LP1+ watermark if we want to change it. It just says that you have to
disable and enable them in order.

> 
> 
> > +       }
> > +
> > +       if (old->enable_fbc_wm != new->enable_fbc_wm) {
> > +               dirty |= WM_DIRTY_FBC;
> > +               /* Must disable LP1+ watermarks too */
> > +               dirty |= WM_DIRTY_LP_ALL;
> > +       }
> > +
> > +       if (old->partitioning != new->partitioning) {
> > +               dirty |= WM_DIRTY_DDB;
> > +               /* Must disable LP1+ watermarks too */
> > +               dirty |= WM_DIRTY_LP_ALL;
> > +       }
> > +
> > +       /* LP1+ watermarks already deemed dirty, no need to continue */
> > +       if (dirty & WM_DIRTY_LP_ALL)
> > +               return dirty;
> > +
> > +       /* Find the lowest numbered LP1+ watermark in need of an update... */
> > +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> > +               if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
> > +                   old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
> > +                       break;
> > +       }
> > +
> > +       /* ...and mark it and all higher numbered LP1+ watermarks as dirty */
> > +       for (; wm_lp <= 3; wm_lp++)
> > +               dirty |= WM_DIRTY_LP(wm_lp);
> > +
> > +       return dirty;
> > +}
> > +
> >  /*
> >   * The spec says we shouldn't write when we don't need, because every write
> >   * causes WMs to be re-evaluated, expending some power.
> > @@ -2784,6 +2841,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >                                 struct hsw_wm_values *results)
> >  {
> >         struct hsw_wm_values previous;
> > +       unsigned int dirty;
> >         uint32_t val;
> >
> >         previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> > @@ -2804,31 +2862,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >
> >         previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> >
> > -       if (memcmp(results, &previous, sizeof(*results)) == 0)
> 
> Oh, you've just removed the memcmp I complained about... Still, I
> believe it had a bug.
> 
> 
> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> > +       if (!dirty)
> >                 return;
> >
> > -       if (previous.wm_lp[2] != 0)
> > +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> >                 I915_WRITE(WM3_LP_ILK, 0);
> > -       if (previous.wm_lp[1] != 0)
> > +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> >                 I915_WRITE(WM2_LP_ILK, 0);
> > -       if (previous.wm_lp[0] != 0)
> > +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> >                 I915_WRITE(WM1_LP_ILK, 0);
> >
> > -       if (previous.wm_pipe[0] != results->wm_pipe[0])
> > +       if (dirty & WM_DIRTY_PIPE(PIPE_A))
> >                 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
> > -       if (previous.wm_pipe[1] != results->wm_pipe[1])
> > +       if (dirty & WM_DIRTY_PIPE(PIPE_B))
> >                 I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
> > -       if (previous.wm_pipe[2] != results->wm_pipe[2])
> > +       if (dirty & WM_DIRTY_PIPE(PIPE_C))
> >                 I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
> >
> > -       if (previous.wm_linetime[0] != results->wm_linetime[0])
> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_A))
> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
> > -       if (previous.wm_linetime[1] != results->wm_linetime[1])
> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_B))
> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
> > -       if (previous.wm_linetime[2] != results->wm_linetime[2])
> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_C))
> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
> >
> > -       if (previous.partitioning != results->partitioning) {
> > +       if (dirty & WM_DIRTY_DDB) {
> >                 val = I915_READ(WM_MISC);
> >                 if (results->partitioning == INTEL_DDB_PART_1_2)
> >                         val &= ~WM_MISC_DATA_PARTITION_5_6;
> > @@ -2837,7 +2896,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >                 I915_WRITE(WM_MISC, val);
> >         }
> >
> > -       if (previous.enable_fbc_wm != results->enable_fbc_wm) {
> > +       if (dirty & WM_DIRTY_FBC) {
> >                 val = I915_READ(DISP_ARB_CTL);
> >                 if (results->enable_fbc_wm)
> >                         val &= ~DISP_FBC_WM_DIS;
> > @@ -2846,18 +2905,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >                 I915_WRITE(DISP_ARB_CTL, val);
> >         }
> >
> > -       if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> > +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> 
> As far as I understood, if previous.wm_lp_spr[X] !=
> results->wm_lp_spr[X], then for sure "dirty & WM_DIRTY_LP(X)", right?
> So the "dirty" check would be redundant here. And we can't remove the
> second part because we can have "dirty & WM_DIRTY_LP(X) while the
> sprite values don't change.

Right, because there's no separate enable bit for the sprite LP1+
watermarks, the dirty check is not really needed here. You want me to
remove it?

> 
> > -       if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> > +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> > -       if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> > +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
> >
> > -       if (results->wm_lp[0] != 0)
> > +       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> >                 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
> > -       if (results->wm_lp[1] != 0)
> > +       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
> >                 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> > -       if (results->wm_lp[2] != 0)
> > +       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
> >                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
> >
> >         dev_priv->wm.hw = *results;
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-11 15:48     ` Ville Syrjälä
@ 2013-10-11 16:12       ` Paulo Zanoni
  2013-10-11 16:39         ` [PATCH v2 " ville.syrjala
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 16:12 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Fri, Oct 11, 2013 at 12:02:53PM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Currently hsw_write_vm_values() may write to certain watermark
>> > registers needlessly. For instance it will disable LP1+ watermarks
>> > around WM_PIPE changes even though that's not needed. Also if only,
>> > say, LP3 changes, the current code will again disable all LP1+
>> > watermarks even though only LP3 needs to be reconfigured.
>> >
>> > Add an easy to read function that will compute the dirtyness of the
>> > watermarks, and use that information to further optimize the watermark
>> > programming.
>>
>> Clever solution to the problem!
>>
>> Some comments below.
>>
>>
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_pm.c | 95 +++++++++++++++++++++++++++++++++--------
>> >  1 file changed, 77 insertions(+), 18 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> > index bed96fb..5bd8c73 100644
>> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> > @@ -2776,6 +2776,63 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
>> >         }
>> >  }
>> >
>> > +/* dirty bits used to track which watermarks need changes */
>> > +#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
>> > +#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
>> > +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
>> > +#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
>> > +#define WM_DIRTY_FBC (1 << 24)
>> > +#define WM_DIRTY_DDB (1 << 25)
>> > +
>> > +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>> > +                                        const struct hsw_wm_values *old,
>> > +                                        const struct hsw_wm_values *new)
>> > +{
>> > +       unsigned int dirty = 0;
>> > +       enum pipe pipe;
>> > +       int wm_lp;
>> > +
>> > +       for_each_pipe(pipe) {
>> > +               if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
>> > +                       dirty |= WM_DIRTY_LINETIME(pipe);
>> > +                       /* Must disable LP1+ watermarks too */
>> > +                       dirty |= WM_DIRTY_LP_ALL;
>> > +               }
>> > +
>> > +               if (old->wm_pipe[pipe] != new->wm_pipe[pipe])
>> > +                       dirty |= WM_DIRTY_PIPE(pipe);
>>
>> I think this one also needs WM_DIRTY_LP_ALL. I don't think changing
>> level zero without stopping the LP levels is safe.
>
> Dunno. Spec doesn't tell me to do it. Although I haven't even bothered
> to check how hard it would be to cook up a configuration where just
> WM_PIPE changes but WM_LPx stays the same.
>
> Actually the spec doesn't even say that we should disable a particular
> LP1+ watermark if we want to change it. It just says that you have to
> disable and enable them in order.
>
>>
>>
>> > +       }
>> > +
>> > +       if (old->enable_fbc_wm != new->enable_fbc_wm) {
>> > +               dirty |= WM_DIRTY_FBC;
>> > +               /* Must disable LP1+ watermarks too */
>> > +               dirty |= WM_DIRTY_LP_ALL;
>> > +       }
>> > +
>> > +       if (old->partitioning != new->partitioning) {
>> > +               dirty |= WM_DIRTY_DDB;
>> > +               /* Must disable LP1+ watermarks too */
>> > +               dirty |= WM_DIRTY_LP_ALL;
>> > +       }
>> > +
>> > +       /* LP1+ watermarks already deemed dirty, no need to continue */
>> > +       if (dirty & WM_DIRTY_LP_ALL)
>> > +               return dirty;
>> > +
>> > +       /* Find the lowest numbered LP1+ watermark in need of an update... */
>> > +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
>> > +               if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
>> > +                   old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
>> > +                       break;
>> > +       }
>> > +
>> > +       /* ...and mark it and all higher numbered LP1+ watermarks as dirty */
>> > +       for (; wm_lp <= 3; wm_lp++)
>> > +               dirty |= WM_DIRTY_LP(wm_lp);
>> > +
>> > +       return dirty;
>> > +}
>> > +
>> >  /*
>> >   * The spec says we shouldn't write when we don't need, because every write
>> >   * causes WMs to be re-evaluated, expending some power.
>> > @@ -2784,6 +2841,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >                                 struct hsw_wm_values *results)
>> >  {
>> >         struct hsw_wm_values previous;
>> > +       unsigned int dirty;
>> >         uint32_t val;
>> >
>> >         previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
>> > @@ -2804,31 +2862,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >
>> >         previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> >
>> > -       if (memcmp(results, &previous, sizeof(*results)) == 0)
>>
>> Oh, you've just removed the memcmp I complained about... Still, I
>> believe it had a bug.
>>
>>
>> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
>> > +       if (!dirty)
>> >                 return;
>> >
>> > -       if (previous.wm_lp[2] != 0)
>> > +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
>> >                 I915_WRITE(WM3_LP_ILK, 0);
>> > -       if (previous.wm_lp[1] != 0)
>> > +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
>> >                 I915_WRITE(WM2_LP_ILK, 0);
>> > -       if (previous.wm_lp[0] != 0)
>> > +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
>> >                 I915_WRITE(WM1_LP_ILK, 0);
>> >
>> > -       if (previous.wm_pipe[0] != results->wm_pipe[0])
>> > +       if (dirty & WM_DIRTY_PIPE(PIPE_A))
>> >                 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
>> > -       if (previous.wm_pipe[1] != results->wm_pipe[1])
>> > +       if (dirty & WM_DIRTY_PIPE(PIPE_B))
>> >                 I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
>> > -       if (previous.wm_pipe[2] != results->wm_pipe[2])
>> > +       if (dirty & WM_DIRTY_PIPE(PIPE_C))
>> >                 I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
>> >
>> > -       if (previous.wm_linetime[0] != results->wm_linetime[0])
>> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_A))
>> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
>> > -       if (previous.wm_linetime[1] != results->wm_linetime[1])
>> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_B))
>> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
>> > -       if (previous.wm_linetime[2] != results->wm_linetime[2])
>> > +       if (dirty & WM_DIRTY_LINETIME(PIPE_C))
>> >                 I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
>> >
>> > -       if (previous.partitioning != results->partitioning) {
>> > +       if (dirty & WM_DIRTY_DDB) {
>> >                 val = I915_READ(WM_MISC);
>> >                 if (results->partitioning == INTEL_DDB_PART_1_2)
>> >                         val &= ~WM_MISC_DATA_PARTITION_5_6;
>> > @@ -2837,7 +2896,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >                 I915_WRITE(WM_MISC, val);
>> >         }
>> >
>> > -       if (previous.enable_fbc_wm != results->enable_fbc_wm) {
>> > +       if (dirty & WM_DIRTY_FBC) {
>> >                 val = I915_READ(DISP_ARB_CTL);
>> >                 if (results->enable_fbc_wm)
>> >                         val &= ~DISP_FBC_WM_DIS;
>> > @@ -2846,18 +2905,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >                 I915_WRITE(DISP_ARB_CTL, val);
>> >         }
>> >
>> > -       if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>> > +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
>>
>> As far as I understood, if previous.wm_lp_spr[X] !=
>> results->wm_lp_spr[X], then for sure "dirty & WM_DIRTY_LP(X)", right?
>> So the "dirty" check would be redundant here. And we can't remove the
>> second part because we can have "dirty & WM_DIRTY_LP(X) while the
>> sprite values don't change.
>
> Right, because there's no separate enable bit for the sprite LP1+
> watermarks, the dirty check is not really needed here. You want me to
> remove it?

It's up to you, since it's not really a bug. Sometimes I ask just to
make sure I understand everything :)

I was more worried about the other question above, I'd play the safer
side and mark levels 1+ dirty when level 0 also changes.

Thanks,
Paulo

>
>>
>> > -       if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>> > +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
>> > -       if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>> > +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>> >
>> > -       if (results->wm_lp[0] != 0)
>> > +       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
>> >                 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
>> > -       if (results->wm_lp[1] != 0)
>> > +       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
>> >                 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
>> > -       if (results->wm_lp[2] != 0)
>> > +       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
>> >                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
>> >
>> >         dev_priv->wm.hw = *results;
>> > --
>> > 1.8.1.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v2 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-11 16:12       ` Paulo Zanoni
@ 2013-10-11 16:39         ` ville.syrjala
  2013-10-11 17:57           ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-11 16:39 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently hsw_write_vm_values() may write to certain watermark
registers needlessly. For instance if only, say, LP3 changes,
the current code will again disable all LP1+ watermarks even
though only LP3 needs to be reconfigured.

Add an easy to read function that will compute the dirtyness of the
watermarks, and use that information to further optimize the watermark
programming.

v2: Disable LP1+ watermarks around changing LP0 watermarks for Paulo

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 98 +++++++++++++++++++++++++++++++++--------
 1 file changed, 80 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index bed96fb..c3e5c0b 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2776,6 +2776,66 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
 	}
 }
 
+/* dirty bits used to track which watermarks need changes */
+#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
+#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
+#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
+#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
+#define WM_DIRTY_FBC (1 << 24)
+#define WM_DIRTY_DDB (1 << 25)
+
+static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
+					 const struct hsw_wm_values *old,
+					 const struct hsw_wm_values *new)
+{
+	unsigned int dirty = 0;
+	enum pipe pipe;
+	int wm_lp;
+
+	for_each_pipe(pipe) {
+		if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
+			dirty |= WM_DIRTY_LINETIME(pipe);
+			/* Must disable LP1+ watermarks too */
+			dirty |= WM_DIRTY_LP_ALL;
+		}
+
+		if (old->wm_pipe[pipe] != new->wm_pipe[pipe]) {
+			dirty |= WM_DIRTY_PIPE(pipe);
+			/* Must disable LP1+ watermarks too */
+			dirty |= WM_DIRTY_LP_ALL;
+		}
+	}
+
+	if (old->enable_fbc_wm != new->enable_fbc_wm) {
+		dirty |= WM_DIRTY_FBC;
+		/* Must disable LP1+ watermarks too */
+		dirty |= WM_DIRTY_LP_ALL;
+	}
+
+	if (old->partitioning != new->partitioning) {
+		dirty |= WM_DIRTY_DDB;
+		/* Must disable LP1+ watermarks too */
+		dirty |= WM_DIRTY_LP_ALL;
+	}
+
+	/* LP1+ watermarks already deemed dirty, no need to continue */
+	if (dirty & WM_DIRTY_LP_ALL)
+		return dirty;
+
+	/* Find the lowest numbered LP1+ watermark in need of an update... */
+	for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
+		if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
+		    old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
+			break;
+	}
+
+	/* ...and mark it and all higher numbered LP1+ watermarks as dirty */
+	for (; wm_lp <= 3; wm_lp++)
+		dirty |= WM_DIRTY_LP(wm_lp);
+
+	return dirty;
+}
+
 /*
  * The spec says we shouldn't write when we don't need, because every write
  * causes WMs to be re-evaluated, expending some power.
@@ -2784,6 +2844,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results)
 {
 	struct hsw_wm_values previous;
+	unsigned int dirty;
 	uint32_t val;
 
 	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
@@ -2804,31 +2865,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 
 	previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
 
-	if (memcmp(results, &previous, sizeof(*results)) == 0)
+	dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
+	if (!dirty)
 		return;
 
-	if (previous.wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, 0);
-	if (previous.wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, 0);
-	if (previous.wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, 0);
 
-	if (previous.wm_pipe[0] != results->wm_pipe[0])
+	if (dirty & WM_DIRTY_PIPE(PIPE_A))
 		I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
-	if (previous.wm_pipe[1] != results->wm_pipe[1])
+	if (dirty & WM_DIRTY_PIPE(PIPE_B))
 		I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
-	if (previous.wm_pipe[2] != results->wm_pipe[2])
+	if (dirty & WM_DIRTY_PIPE(PIPE_C))
 		I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
 
-	if (previous.wm_linetime[0] != results->wm_linetime[0])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_A))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
-	if (previous.wm_linetime[1] != results->wm_linetime[1])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_B))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
-	if (previous.wm_linetime[2] != results->wm_linetime[2])
+	if (dirty & WM_DIRTY_LINETIME(PIPE_C))
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
-	if (previous.partitioning != results->partitioning) {
+	if (dirty & WM_DIRTY_DDB) {
 		val = I915_READ(WM_MISC);
 		if (results->partitioning == INTEL_DDB_PART_1_2)
 			val &= ~WM_MISC_DATA_PARTITION_5_6;
@@ -2837,7 +2899,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(WM_MISC, val);
 	}
 
-	if (previous.enable_fbc_wm != results->enable_fbc_wm) {
+	if (dirty & WM_DIRTY_FBC) {
 		val = I915_READ(DISP_ARB_CTL);
 		if (results->enable_fbc_wm)
 			val &= ~DISP_FBC_WM_DIS;
@@ -2846,18 +2908,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(DISP_ARB_CTL, val);
 	}
 
-	if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
+	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
 		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-	if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
+	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
 		I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-	if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
+	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
 		I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
-	if (results->wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
-	if (results->wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
-	if (results->wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 
 	dev_priv->wm.hw = *results;
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-09 16:18 ` [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state() ville.syrjala
@ 2013-10-11 16:45   ` Paulo Zanoni
  2013-10-11 17:15     ` Ville Syrjälä
  2013-10-14 11:55     ` [PATCH v2 " ville.syrjala
  0 siblings, 2 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 16:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Fill out the HSW watermark s/w tracking structures with the current
> hardware state in intel_modeset_setup_hw_state(). This allows us to skip
> the HW state readback during watermark programming and just use the values
> we keep around in dev_priv->wm. Reduces the overhead of the watermark
> programming quite a bit.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |   3 +
>  drivers/gpu/drm/i915/intel_drv.h     |   1 +
>  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
>  3 files changed, 82 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 27f98bc..194f933 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>                 pll->on = false;
>         }
>
> +       if (IS_HASWELL(dev))
> +               ilk_init_wm(dev);

If is_HSW, then ILK_something is quite confusing :) Not everybody is
aware of your greater plans for total watermarks domination.


> +
>         if (force_restore) {
>                 i915_redisable_vga(dev);
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 3325b0b..bdb1708 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> +void ilk_init_wm(struct drm_device *dev);
>
>
>  /* intel_sdvo.c */
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 5bd8c73..cebd9b4 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                                 struct hsw_wm_values *results)
>  {
> -       struct hsw_wm_values previous;
> +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
>         unsigned int dirty;
>         uint32_t val;
>
> -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> -
> -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> -
> -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> -
> -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
>         if (!dirty)
>                 return;
>
> -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, 0);
> -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, 0);
> -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, 0);
>
>         if (dirty & WM_DIRTY_PIPE(PIPE_A))
> @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(DISP_ARB_CTL, val);
>         }
>
> -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
>                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
>                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
>                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>
>         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
>         I915_WRITE(WM3S_LP_IVB, sprite_wm);
>  }
>
> +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
> +       enum pipe pipe = intel_crtc->pipe;
> +       static const unsigned int wm0_pipe_reg[] = {
> +               [PIPE_A] = WM0_PIPEA_ILK,
> +               [PIPE_B] = WM0_PIPEB_ILK,
> +               [PIPE_C] = WM0_PIPEC_IVB,
> +       };
> +
> +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> +
> +       /* Assume sprites are disabled */

Why? Please write in the comment.


> +
> +       if (intel_crtc_active(crtc)) {
> +               u32 tmp = hw->wm_pipe[pipe];
> +
> +               /*
> +                * For active pipes LP0 watermark is marked as
> +                * enabled, and LP1+ watermaks as disabled since
> +                * we can't really reverse compute them in case
> +                * multiple pipes are active.
> +                */
> +               active->wm[0].enable = true;
> +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
> +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
> +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
> +               active->linetime = hw->wm_linetime[pipe];
> +       } else {
> +               int level, max_level = ilk_wm_max_level(dev);
> +
> +               /*
> +                * For inactive pipes, all watermark levels
> +                * should be marked as enabled but zeroed,
> +                * which is what we'd comoute them to.
> +                */
> +               for (level = 0; level <= max_level; level++)
> +                       active->wm[level].enable = true;

Why exactly do we compute them like this?

One thing that I noticed is that, both on current -nightly (without
your series) and with your series, when we disable all the screens we
zero all the watermarks, but leave the "enable" bits of the LP
watermarks enabled. IMHO we should treat this as a bug and fix it. I
wonder if the comment above is related with this problem.


> +       }
> +}
> +
> +void ilk_init_wm(struct drm_device *dev)

IMHO, maintaining the _get_hw_state nomenclature would be an improvement.


> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> +       struct drm_crtc *crtc;
> +
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> +               ilk_init_pipe_wm(crtc);
> +
> +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> +
> +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> +
> +       hw->partitioning =
> +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);

This is a little bit dangerous... We never know if we're not going to
add a 4_6 partition type in the middle of the enum for Gen 17. And if
we add it, I'm 100% sure we'll forget to patch this line. I usually
try to avoid these things.


> +
> +       hw->enable_fbc_wm =
> +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +}
> +
>  /**
>   * intel_update_watermarks - update FIFO watermark values based on current modes

Also, this patch makes me wonder about those places where we change
the HW state directly (init_clock_gating, for example) without
touching the struct you just added. That specific init_clock_gating is
run before we call ilk_init_wm, so it shouldn't be a problem on
boot/resume, but it still leaves me worried...

Also, perhaps we could have one of those functions that try to check
if the tracked state is really the HW state...

>   *
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code
  2013-10-09 16:18 ` [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code ville.syrjala
@ 2013-10-11 16:48   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 16:48 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> This debug print just adds overhead to the watermark merging process,
> and doesn't really give enough information to be useful. Just kill
> and let's add something much better a bit later.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index cebd9b4..0450260 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2421,8 +2421,6 @@ static bool ilk_check_wm(int level,
>                 result->enable = true;
>         }
>
> -       DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis");
> -
>         return ret;
>  }
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 13/16] drm/i915: Adjust watermark register masks
  2013-10-09 16:18 ` [PATCH v2 13/16] drm/i915: Adjust watermark register masks ville.syrjala
@ 2013-10-11 17:02   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 17:02 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We want to be able to use the masks to decode the register contents
> regardless of the hardware generation. So just expand the masks to
> cover all available bits, even if those are reserved on some
> generations.
>
> v2: Don't extend WM1_LP_SR_MASK so far, for the *future*
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I checked BSpec and it seems these values were all already wrong for
Haswell! Most masks were lacking 1 bit. I think we were not using
these maks on HSW, so we're probably fine.

Maybe adding a comment saying "the masks change from Gen to Gen, but
we keep the big backwards-compatible values" could be a good thing.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index c246727..cab709d 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3251,11 +3251,11 @@
>
>  /* define the Watermark register on Ironlake */
>  #define WM0_PIPEA_ILK          0x45100
> -#define  WM0_PIPE_PLANE_MASK   (0x7f<<16)
> +#define  WM0_PIPE_PLANE_MASK   (0xffff<<16)
>  #define  WM0_PIPE_PLANE_SHIFT  16
> -#define  WM0_PIPE_SPRITE_MASK  (0x3f<<8)
> +#define  WM0_PIPE_SPRITE_MASK  (0xff<<8)
>  #define  WM0_PIPE_SPRITE_SHIFT 8
> -#define  WM0_PIPE_CURSOR_MASK  (0x1f)
> +#define  WM0_PIPE_CURSOR_MASK  (0xff)
>
>  #define WM0_PIPEB_ILK          0x45104
>  #define WM0_PIPEC_IVB          0x45200
> @@ -3265,9 +3265,9 @@
>  #define  WM1_LP_LATENCY_MASK   (0x7f<<24)
>  #define  WM1_LP_FBC_MASK       (0xf<<20)
>  #define  WM1_LP_FBC_SHIFT      20
> -#define  WM1_LP_SR_MASK                (0x1ff<<8)
> +#define  WM1_LP_SR_MASK                (0x7ff<<8)
>  #define  WM1_LP_SR_SHIFT       8
> -#define  WM1_LP_CURSOR_MASK    (0x3f)
> +#define  WM1_LP_CURSOR_MASK    (0xff)
>  #define WM2_LP_ILK             0x4510c
>  #define  WM2_LP_EN             (1<<31)
>  #define WM3_LP_ILK             0x45110
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums
  2013-10-09 16:18 ` [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums ville.syrjala
@ 2013-10-11 17:07   ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 17:07 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Makes the intention more clear.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Thanks!

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 022cd5b..7b52e39 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2371,11 +2371,11 @@ static unsigned int ilk_fbc_wm_max(void)
>         return 15;
>  }
>
> -static void ilk_wm_max(struct drm_device *dev,
> -                      int level,
> -                      const struct intel_wm_config *config,
> -                      enum intel_ddb_partitioning ddb_partitioning,
> -                      struct hsw_wm_maximums *max)
> +static void ilk_compute_wm_maximums(struct drm_device *dev,
> +                                   int level,
> +                                   const struct intel_wm_config *config,
> +                                   enum intel_ddb_partitioning ddb_partitioning,
> +                                   struct hsw_wm_maximums *max)
>  {
>         max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
>         max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
> @@ -2626,7 +2626,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         struct hsw_wm_maximums max;
>
>         /* LP0 watermarks always use 1/2 DDB partitioning */
> -       ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
> +       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
>
>         for (level = 0; level <= max_level; level++)
>                 ilk_compute_wm_level(dev_priv, level, params,
> @@ -2954,12 +2954,12 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>
>         intel_crtc->wm.active = pipe_wm;
>
> -       ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
> +       ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
>         ilk_wm_merge(dev, &max, &lp_wm_1_2);
>
>         /* 5/6 split only in single pipe config on IVB+ */
>         if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {
> -               ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
> +               ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
>                 ilk_wm_merge(dev, &max, &lp_wm_5_6);
>
>                 best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level
  2013-10-09 16:18 ` [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level ville.syrjala
@ 2013-10-11 17:08   ` Paulo Zanoni
  2013-10-15  9:16     ` Daniel Vetter
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 17:08 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Makes the behaviour of the function more clear.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Thanks :)

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7b52e39..211a946 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2383,9 +2383,9 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
>         max->fbc = ilk_fbc_wm_max();
>  }
>
> -static bool ilk_check_wm(int level,
> -                        const struct hsw_wm_maximums *max,
> -                        struct intel_wm_level *result)
> +static bool ilk_validate_wm_level(int level,
> +                                 const struct hsw_wm_maximums *max,
> +                                 struct intel_wm_level *result)
>  {
>         bool ret;
>
> @@ -2635,7 +2635,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
>         pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
>
>         /* At least LP0 must be valid */
> -       return ilk_check_wm(0, &max, &pipe_wm->wm[0]);
> +       return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
>  }
>
>  /*
> @@ -2680,7 +2680,7 @@ static void ilk_wm_merge(struct drm_device *dev,
>
>                 ilk_merge_wm_level(dev, level, wm);
>
> -               if (!ilk_check_wm(level, max, wm))
> +               if (!ilk_validate_wm_level(level, max, wm))
>                         break;
>
>                 /*
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 16:45   ` Paulo Zanoni
@ 2013-10-11 17:15     ` Ville Syrjälä
  2013-10-11 18:15       ` Paulo Zanoni
  2013-10-14 11:55     ` [PATCH v2 " ville.syrjala
  1 sibling, 1 reply; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11 17:15 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 01:45:27PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Fill out the HSW watermark s/w tracking structures with the current
> > hardware state in intel_modeset_setup_hw_state(). This allows us to skip
> > the HW state readback during watermark programming and just use the values
> > we keep around in dev_priv->wm. Reduces the overhead of the watermark
> > programming quite a bit.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c |   3 +
> >  drivers/gpu/drm/i915/intel_drv.h     |   1 +
> >  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
> >  3 files changed, 82 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 27f98bc..194f933 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
> >                 pll->on = false;
> >         }
> >
> > +       if (IS_HASWELL(dev))
> > +               ilk_init_wm(dev);
> 
> If is_HSW, then ILK_something is quite confusing :) Not everybody is
> aware of your greater plans for total watermarks domination.
> 
> 
> > +
> >         if (force_restore) {
> >                 i915_redisable_vga(dev);
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 3325b0b..bdb1708 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
> >  void gen6_rps_boost(struct drm_i915_private *dev_priv);
> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> > +void ilk_init_wm(struct drm_device *dev);
> >
> >
> >  /* intel_sdvo.c */
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 5bd8c73..cebd9b4 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> >  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >                                 struct hsw_wm_values *results)
> >  {
> > -       struct hsw_wm_values previous;
> > +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
> >         unsigned int dirty;
> >         uint32_t val;
> >
> > -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> > -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> > -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> > -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> > -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> > -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> > -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> > -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> > -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> > -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> > -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> > -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> > -
> > -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> > -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> > -
> > -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> > -
> > -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
> >         if (!dirty)
> >                 return;
> >
> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
> >                 I915_WRITE(WM3_LP_ILK, 0);
> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
> >                 I915_WRITE(WM2_LP_ILK, 0);
> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
> >                 I915_WRITE(WM1_LP_ILK, 0);
> >
> >         if (dirty & WM_DIRTY_PIPE(PIPE_A))
> > @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >                 I915_WRITE(DISP_ARB_CTL, val);
> >         }
> >
> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
> >
> >         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> > @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
> >         I915_WRITE(WM3S_LP_IVB, sprite_wm);
> >  }
> >
> > +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
> > +{
> > +       struct drm_device *dev = crtc->dev;
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> > +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
> > +       enum pipe pipe = intel_crtc->pipe;
> > +       static const unsigned int wm0_pipe_reg[] = {
> > +               [PIPE_A] = WM0_PIPEA_ILK,
> > +               [PIPE_B] = WM0_PIPEB_ILK,
> > +               [PIPE_C] = WM0_PIPEC_IVB,
> > +       };
> > +
> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> > +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> > +
> > +       /* Assume sprites are disabled */
> 
> Why? Please write in the comment.

Actually that's a leftover from before I reordered some of my patches.
In a later stage I want to track sprite status in intel_pipe_wm, so the
comment was meant to tell the reader why we don't populate that
information here. And the real reason for not populating that
information is that I'm lazy and figured sprites will never be enabled
when we load the driver.

But for now, I'll just kill the comment since it's utter nonsense at the
moment.

> 
> 
> > +
> > +       if (intel_crtc_active(crtc)) {
> > +               u32 tmp = hw->wm_pipe[pipe];
> > +
> > +               /*
> > +                * For active pipes LP0 watermark is marked as
> > +                * enabled, and LP1+ watermaks as disabled since
> > +                * we can't really reverse compute them in case
> > +                * multiple pipes are active.
> > +                */
> > +               active->wm[0].enable = true;
> > +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
> > +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
> > +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
> > +               active->linetime = hw->wm_linetime[pipe];
> > +       } else {
> > +               int level, max_level = ilk_wm_max_level(dev);
> > +
> > +               /*
> > +                * For inactive pipes, all watermark levels
> > +                * should be marked as enabled but zeroed,
> > +                * which is what we'd comoute them to.
> > +                */
> > +               for (level = 0; level <= max_level; level++)
> > +                       active->wm[level].enable = true;
> 
> Why exactly do we compute them like this?

The assumption is that for a disabled pipe all watermarks are zero,
which means all the levels are valid.

> 
> One thing that I noticed is that, both on current -nightly (without
> your series) and with your series, when we disable all the screens we
> zero all the watermarks, but leave the "enable" bits of the LP
> watermarks enabled. IMHO we should treat this as a bug and fix it. I
> wonder if the comment above is related with this problem.

Why is that a problem?

> 
> 
> > +       }
> > +}
> > +
> > +void ilk_init_wm(struct drm_device *dev)
> 
> IMHO, maintaining the _get_hw_state nomenclature would be an improvement.

OK.

> 
> 
> > +{
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> > +       struct drm_crtc *crtc;
> > +
> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> > +               ilk_init_pipe_wm(crtc);
> > +
> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> > +
> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> > +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> > +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> > +
> > +       hw->partitioning =
> > +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
> 
> This is a little bit dangerous... We never know if we're not going to
> add a 4_6 partition type in the middle of the enum for Gen 17. And if
> we add it, I'm 100% sure we'll forget to patch this line. I usually
> try to avoid these things.

I happen to know that we won't get such a thing ;) Well, unless the
hardware designers start backpedaling after a few gens.

So how would you write this?

> 
> 
> > +
> > +       hw->enable_fbc_wm =
> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> > +}
> > +
> >  /**
> >   * intel_update_watermarks - update FIFO watermark values based on current modes
> 
> Also, this patch makes me wonder about those places where we change
> the HW state directly (init_clock_gating, for example) without
> touching the struct you just added. That specific init_clock_gating is
> run before we call ilk_init_wm, so it shouldn't be a problem on
> boot/resume, but it still leaves me worried...

One option would be to kill the WM stuff from init_clock_gating. I think
it's just a safety measure to have it there, but I don't really see much
reason to keep it.

> 
> Also, perhaps we could have one of those functions that try to check
> if the tracked state is really the HW state...

Yeah, that should be doable. But the watermark update is going to become
a staged process when I'm through with it, so we need to be careful
where we do the check to make sure we compare with the right sw state.

> 
> >   *
> > --
> > 1.8.1.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled
  2013-10-11 12:26       ` [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled ville.syrjala
@ 2013-10-11 17:21         ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 17:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Using the 5/6 DDB split make sense only when sprites are enabled.
> So check that before we waste any cycles computing the merged
> watermarks with the 5/6 DDB split.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 211a946..214a8de 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2958,7 +2958,8 @@ static void haswell_update_wm(struct drm_crtc *crtc)
>         ilk_wm_merge(dev, &max, &lp_wm_1_2);
>
>         /* 5/6 split only in single pipe config on IVB+ */
> -       if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) {
> +       if (INTEL_INFO(dev)->gen >= 7 &&
> +           config.num_pipes_active == 1 && config.sprites_enabled) {
>                 ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
>                 ilk_wm_merge(dev, &max, &lp_wm_5_6);
>
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 10/16] drm/i915: Improve watermark dirtyness checks
  2013-10-11 16:39         ` [PATCH v2 " ville.syrjala
@ 2013-10-11 17:57           ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 17:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development, Paulo Zanoni

2013/10/11  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Currently hsw_write_vm_values() may write to certain watermark
> registers needlessly. For instance if only, say, LP3 changes,
> the current code will again disable all LP1+ watermarks even
> though only LP3 needs to be reconfigured.
>
> Add an easy to read function that will compute the dirtyness of the
> watermarks, and use that information to further optimize the watermark
> programming.
>
> v2: Disable LP1+ watermarks around changing LP0 watermarks for Paulo

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 98 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 80 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index bed96fb..c3e5c0b 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2776,6 +2776,66 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
>         }
>  }
>
> +/* dirty bits used to track which watermarks need changes */
> +#define WM_DIRTY_PIPE(pipe) (1 << (pipe))
> +#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe)))
> +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp)))
> +#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3))
> +#define WM_DIRTY_FBC (1 << 24)
> +#define WM_DIRTY_DDB (1 << 25)
> +
> +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> +                                        const struct hsw_wm_values *old,
> +                                        const struct hsw_wm_values *new)
> +{
> +       unsigned int dirty = 0;
> +       enum pipe pipe;
> +       int wm_lp;
> +
> +       for_each_pipe(pipe) {
> +               if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) {
> +                       dirty |= WM_DIRTY_LINETIME(pipe);
> +                       /* Must disable LP1+ watermarks too */
> +                       dirty |= WM_DIRTY_LP_ALL;
> +               }
> +
> +               if (old->wm_pipe[pipe] != new->wm_pipe[pipe]) {
> +                       dirty |= WM_DIRTY_PIPE(pipe);
> +                       /* Must disable LP1+ watermarks too */
> +                       dirty |= WM_DIRTY_LP_ALL;
> +               }
> +       }
> +
> +       if (old->enable_fbc_wm != new->enable_fbc_wm) {
> +               dirty |= WM_DIRTY_FBC;
> +               /* Must disable LP1+ watermarks too */
> +               dirty |= WM_DIRTY_LP_ALL;
> +       }
> +
> +       if (old->partitioning != new->partitioning) {
> +               dirty |= WM_DIRTY_DDB;
> +               /* Must disable LP1+ watermarks too */
> +               dirty |= WM_DIRTY_LP_ALL;
> +       }
> +
> +       /* LP1+ watermarks already deemed dirty, no need to continue */
> +       if (dirty & WM_DIRTY_LP_ALL)
> +               return dirty;
> +
> +       /* Find the lowest numbered LP1+ watermark in need of an update... */
> +       for (wm_lp = 1; wm_lp <= 3; wm_lp++) {
> +               if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] ||
> +                   old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1])
> +                       break;
> +       }
> +
> +       /* ...and mark it and all higher numbered LP1+ watermarks as dirty */
> +       for (; wm_lp <= 3; wm_lp++)
> +               dirty |= WM_DIRTY_LP(wm_lp);
> +
> +       return dirty;
> +}
> +
>  /*
>   * The spec says we shouldn't write when we don't need, because every write
>   * causes WMs to be re-evaluated, expending some power.
> @@ -2784,6 +2844,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                                 struct hsw_wm_values *results)
>  {
>         struct hsw_wm_values previous;
> +       unsigned int dirty;
>         uint32_t val;
>
>         previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> @@ -2804,31 +2865,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>
>         previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>
> -       if (memcmp(results, &previous, sizeof(*results)) == 0)
> +       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> +       if (!dirty)
>                 return;
>
> -       if (previous.wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, 0);
> -       if (previous.wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, 0);
> -       if (previous.wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, 0);
>
> -       if (previous.wm_pipe[0] != results->wm_pipe[0])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_A))
>                 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
> -       if (previous.wm_pipe[1] != results->wm_pipe[1])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_B))
>                 I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]);
> -       if (previous.wm_pipe[2] != results->wm_pipe[2])
> +       if (dirty & WM_DIRTY_PIPE(PIPE_C))
>                 I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]);
>
> -       if (previous.wm_linetime[0] != results->wm_linetime[0])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_A))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]);
> -       if (previous.wm_linetime[1] != results->wm_linetime[1])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_B))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]);
> -       if (previous.wm_linetime[2] != results->wm_linetime[2])
> +       if (dirty & WM_DIRTY_LINETIME(PIPE_C))
>                 I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
>
> -       if (previous.partitioning != results->partitioning) {
> +       if (dirty & WM_DIRTY_DDB) {
>                 val = I915_READ(WM_MISC);
>                 if (results->partitioning == INTEL_DDB_PART_1_2)
>                         val &= ~WM_MISC_DATA_PARTITION_5_6;
> @@ -2837,7 +2899,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(WM_MISC, val);
>         }
>
> -       if (previous.enable_fbc_wm != results->enable_fbc_wm) {
> +       if (dirty & WM_DIRTY_FBC) {
>                 val = I915_READ(DISP_ARB_CTL);
>                 if (results->enable_fbc_wm)
>                         val &= ~DISP_FBC_WM_DIS;
> @@ -2846,18 +2908,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(DISP_ARB_CTL, val);
>         }
>
> -       if (previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> +       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> -       if (previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> +       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> -       if (previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> +       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>
> -       if (results->wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
> -       if (results->wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
> -       if (results->wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
>
>         dev_priv->wm.hw = *results;
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 17:15     ` Ville Syrjälä
@ 2013-10-11 18:15       ` Paulo Zanoni
  2013-10-11 19:12         ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 18:15 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Fri, Oct 11, 2013 at 01:45:27PM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Fill out the HSW watermark s/w tracking structures with the current
>> > hardware state in intel_modeset_setup_hw_state(). This allows us to skip
>> > the HW state readback during watermark programming and just use the values
>> > we keep around in dev_priv->wm. Reduces the overhead of the watermark
>> > programming quite a bit.
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_display.c |   3 +
>> >  drivers/gpu/drm/i915/intel_drv.h     |   1 +
>> >  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
>> >  3 files changed, 82 insertions(+), 26 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> > index 27f98bc..194f933 100644
>> > --- a/drivers/gpu/drm/i915/intel_display.c
>> > +++ b/drivers/gpu/drm/i915/intel_display.c
>> > @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>> >                 pll->on = false;
>> >         }
>> >
>> > +       if (IS_HASWELL(dev))
>> > +               ilk_init_wm(dev);
>>
>> If is_HSW, then ILK_something is quite confusing :) Not everybody is
>> aware of your greater plans for total watermarks domination.
>>
>>
>> > +
>> >         if (force_restore) {
>> >                 i915_redisable_vga(dev);
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> > index 3325b0b..bdb1708 100644
>> > --- a/drivers/gpu/drm/i915/intel_drv.h
>> > +++ b/drivers/gpu/drm/i915/intel_drv.h
>> > @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>> >  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
>> > +void ilk_init_wm(struct drm_device *dev);
>> >
>> >
>> >  /* intel_sdvo.c */
>> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> > index 5bd8c73..cebd9b4 100644
>> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> > @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>> >  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >                                 struct hsw_wm_values *results)
>> >  {
>> > -       struct hsw_wm_values previous;
>> > +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
>> >         unsigned int dirty;
>> >         uint32_t val;
>> >
>> > -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
>> > -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
>> > -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
>> > -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
>> > -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
>> > -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
>> > -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
>> > -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
>> > -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
>> > -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
>> > -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
>> > -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
>> > -
>> > -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
>> > -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
>> > -
>> > -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> > -
>> > -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
>> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
>> >         if (!dirty)
>> >                 return;
>> >
>> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
>> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
>> >                 I915_WRITE(WM3_LP_ILK, 0);
>> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
>> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
>> >                 I915_WRITE(WM2_LP_ILK, 0);
>> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
>> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
>> >                 I915_WRITE(WM1_LP_ILK, 0);
>> >
>> >         if (dirty & WM_DIRTY_PIPE(PIPE_A))
>> > @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >                 I915_WRITE(DISP_ARB_CTL, val);
>> >         }
>> >
>> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
>> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
>> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
>> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
>> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
>> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>> >
>> >         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
>> > @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
>> >         I915_WRITE(WM3S_LP_IVB, sprite_wm);
>> >  }
>> >
>> > +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
>> > +{
>> > +       struct drm_device *dev = crtc->dev;
>> > +       struct drm_i915_private *dev_priv = dev->dev_private;
>> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
>> > +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> > +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
>> > +       enum pipe pipe = intel_crtc->pipe;
>> > +       static const unsigned int wm0_pipe_reg[] = {
>> > +               [PIPE_A] = WM0_PIPEA_ILK,
>> > +               [PIPE_B] = WM0_PIPEB_ILK,
>> > +               [PIPE_C] = WM0_PIPEC_IVB,
>> > +       };
>> > +
>> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
>> > +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
>> > +
>> > +       /* Assume sprites are disabled */
>>
>> Why? Please write in the comment.
>
> Actually that's a leftover from before I reordered some of my patches.
> In a later stage I want to track sprite status in intel_pipe_wm, so the
> comment was meant to tell the reader why we don't populate that
> information here. And the real reason for not populating that
> information is that I'm lazy and figured sprites will never be enabled
> when we load the driver.
>
> But for now, I'll just kill the comment since it's utter nonsense at the
> moment.
>
>>
>>
>> > +
>> > +       if (intel_crtc_active(crtc)) {
>> > +               u32 tmp = hw->wm_pipe[pipe];
>> > +
>> > +               /*
>> > +                * For active pipes LP0 watermark is marked as
>> > +                * enabled, and LP1+ watermaks as disabled since
>> > +                * we can't really reverse compute them in case
>> > +                * multiple pipes are active.
>> > +                */
>> > +               active->wm[0].enable = true;
>> > +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
>> > +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
>> > +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
>> > +               active->linetime = hw->wm_linetime[pipe];
>> > +       } else {
>> > +               int level, max_level = ilk_wm_max_level(dev);
>> > +
>> > +               /*
>> > +                * For inactive pipes, all watermark levels
>> > +                * should be marked as enabled but zeroed,
>> > +                * which is what we'd comoute them to.
>> > +                */
>> > +               for (level = 0; level <= max_level; level++)
>> > +                       active->wm[level].enable = true;
>>
>> Why exactly do we compute them like this?
>
> The assumption is that for a disabled pipe all watermarks are zero,
> which means all the levels are valid.

But valid != enabled. This is the confusing part IMHO.


>
>>
>> One thing that I noticed is that, both on current -nightly (without
>> your series) and with your series, when we disable all the screens we
>> zero all the watermarks, but leave the "enable" bits of the LP
>> watermarks enabled. IMHO we should treat this as a bug and fix it. I
>> wonder if the comment above is related with this problem.
>
> Why is that a problem?

Because it relies on something that's only implied by the
specification and probably not really thoroughly validated (or
validated at all). I really don't like abusing the HW like that. Just
take a look at the amount of HW workarounds we already have for the
"happy cases"... I really prefer to be on the safer side.


>
>>
>>
>> > +       }
>> > +}
>> > +
>> > +void ilk_init_wm(struct drm_device *dev)
>>
>> IMHO, maintaining the _get_hw_state nomenclature would be an improvement.
>
> OK.
>
>>
>>
>> > +{
>> > +       struct drm_i915_private *dev_priv = dev->dev_private;
>> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
>> > +       struct drm_crtc *crtc;
>> > +
>> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
>> > +               ilk_init_pipe_wm(crtc);
>> > +
>> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
>> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
>> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
>> > +
>> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
>> > +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
>> > +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
>> > +
>> > +       hw->partitioning =
>> > +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
>>
>> This is a little bit dangerous... We never know if we're not going to
>> add a 4_6 partition type in the middle of the enum for Gen 17. And if
>> we add it, I'm 100% sure we'll forget to patch this line. I usually
>> try to avoid these things.
>
> I happen to know that we won't get such a thing ;) Well, unless the
> hardware designers start backpedaling after a few gens.
>
> So how would you write this?

With the simpler form:

hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;

Even if the enum value changes, the code will remain correct on
Haswell, I hope :)


>
>>
>>
>> > +
>> > +       hw->enable_fbc_wm =
>> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> > +}
>> > +
>> >  /**
>> >   * intel_update_watermarks - update FIFO watermark values based on current modes
>>
>> Also, this patch makes me wonder about those places where we change
>> the HW state directly (init_clock_gating, for example) without
>> touching the struct you just added. That specific init_clock_gating is
>> run before we call ilk_init_wm, so it shouldn't be a problem on
>> boot/resume, but it still leaves me worried...
>
> One option would be to kill the WM stuff from init_clock_gating. I think
> it's just a safety measure to have it there, but I don't really see much
> reason to keep it.

Yeah, I always wonder if that's really needed or not.

Advantages of keeping it:
- it reduces our possibility of triggering an underrun when we do the
other clock_gating stuff
- if the BIOS does it wrong, we can minimize its failure

Disadvantages:
- we may want the possible underruns when we do the other clock_gating
stuff, since they're probably wrong anyway
- if we ever get to a point where we do zero modesets when loading the
driver, we'll just mess the watermarks.

To counter the second advantage of keeping it, we could even write
intel_sanitize_watermarks :)

But that's all material for future patches.

>
>>
>> Also, perhaps we could have one of those functions that try to check
>> if the tracked state is really the HW state...
>
> Yeah, that should be doable. But the watermark update is going to become
> a staged process when I'm through with it, so we need to be careful
> where we do the check to make sure we compare with the right sw state.

Let's focus on merging your current plans first, then we think about
these things then.


>
>>
>> >   *
>> > --
>> > 1.8.1.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 18:15       ` Paulo Zanoni
@ 2013-10-11 19:12         ` Ville Syrjälä
  2013-10-11 19:46           ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-11 19:12 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 03:15:48PM -0300, Paulo Zanoni wrote:
> 2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> > On Fri, Oct 11, 2013 at 01:45:27PM -0300, Paulo Zanoni wrote:
> >> 2013/10/9  <ville.syrjala@linux.intel.com>:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Fill out the HSW watermark s/w tracking structures with the current
> >> > hardware state in intel_modeset_setup_hw_state(). This allows us to skip
> >> > the HW state readback during watermark programming and just use the values
> >> > we keep around in dev_priv->wm. Reduces the overhead of the watermark
> >> > programming quite a bit.
> >> >
> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> > ---
> >> >  drivers/gpu/drm/i915/intel_display.c |   3 +
> >> >  drivers/gpu/drm/i915/intel_drv.h     |   1 +
> >> >  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
> >> >  3 files changed, 82 insertions(+), 26 deletions(-)
> >> >
> >> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> > index 27f98bc..194f933 100644
> >> > --- a/drivers/gpu/drm/i915/intel_display.c
> >> > +++ b/drivers/gpu/drm/i915/intel_display.c
> >> > @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
> >> >                 pll->on = false;
> >> >         }
> >> >
> >> > +       if (IS_HASWELL(dev))
> >> > +               ilk_init_wm(dev);
> >>
> >> If is_HSW, then ILK_something is quite confusing :) Not everybody is
> >> aware of your greater plans for total watermarks domination.
> >>
> >>
> >> > +
> >> >         if (force_restore) {
> >> >                 i915_redisable_vga(dev);
> >> >
> >> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> > index 3325b0b..bdb1708 100644
> >> > --- a/drivers/gpu/drm/i915/intel_drv.h
> >> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> >> > @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
> >> >  void gen6_rps_boost(struct drm_i915_private *dev_priv);
> >> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> >> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> >> > +void ilk_init_wm(struct drm_device *dev);
> >> >
> >> >
> >> >  /* intel_sdvo.c */
> >> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> >> > index 5bd8c73..cebd9b4 100644
> >> > --- a/drivers/gpu/drm/i915/intel_pm.c
> >> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> >> > @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> >> >  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >> >                                 struct hsw_wm_values *results)
> >> >  {
> >> > -       struct hsw_wm_values previous;
> >> > +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
> >> >         unsigned int dirty;
> >> >         uint32_t val;
> >> >
> >> > -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> >> > -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> >> > -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> >> > -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> >> > -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> >> > -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> >> > -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> >> > -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> >> > -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> >> > -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> >> > -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> >> > -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> >> > -
> >> > -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> >> > -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> >> > -
> >> > -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> >> > -
> >> > -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> >> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
> >> >         if (!dirty)
> >> >                 return;
> >> >
> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
> >> >                 I915_WRITE(WM3_LP_ILK, 0);
> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
> >> >                 I915_WRITE(WM2_LP_ILK, 0);
> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
> >> >                 I915_WRITE(WM1_LP_ILK, 0);
> >> >
> >> >         if (dirty & WM_DIRTY_PIPE(PIPE_A))
> >> > @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >> >                 I915_WRITE(DISP_ARB_CTL, val);
> >> >         }
> >> >
> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
> >> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
> >> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
> >> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
> >> >
> >> >         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> >> > @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
> >> >         I915_WRITE(WM3S_LP_IVB, sprite_wm);
> >> >  }
> >> >
> >> > +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
> >> > +{
> >> > +       struct drm_device *dev = crtc->dev;
> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> >> > +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >> > +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
> >> > +       enum pipe pipe = intel_crtc->pipe;
> >> > +       static const unsigned int wm0_pipe_reg[] = {
> >> > +               [PIPE_A] = WM0_PIPEA_ILK,
> >> > +               [PIPE_B] = WM0_PIPEB_ILK,
> >> > +               [PIPE_C] = WM0_PIPEC_IVB,
> >> > +       };
> >> > +
> >> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> >> > +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> >> > +
> >> > +       /* Assume sprites are disabled */
> >>
> >> Why? Please write in the comment.
> >
> > Actually that's a leftover from before I reordered some of my patches.
> > In a later stage I want to track sprite status in intel_pipe_wm, so the
> > comment was meant to tell the reader why we don't populate that
> > information here. And the real reason for not populating that
> > information is that I'm lazy and figured sprites will never be enabled
> > when we load the driver.
> >
> > But for now, I'll just kill the comment since it's utter nonsense at the
> > moment.
> >
> >>
> >>
> >> > +
> >> > +       if (intel_crtc_active(crtc)) {
> >> > +               u32 tmp = hw->wm_pipe[pipe];
> >> > +
> >> > +               /*
> >> > +                * For active pipes LP0 watermark is marked as
> >> > +                * enabled, and LP1+ watermaks as disabled since
> >> > +                * we can't really reverse compute them in case
> >> > +                * multiple pipes are active.
> >> > +                */
> >> > +               active->wm[0].enable = true;
> >> > +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
> >> > +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
> >> > +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
> >> > +               active->linetime = hw->wm_linetime[pipe];
> >> > +       } else {
> >> > +               int level, max_level = ilk_wm_max_level(dev);
> >> > +
> >> > +               /*
> >> > +                * For inactive pipes, all watermark levels
> >> > +                * should be marked as enabled but zeroed,
> >> > +                * which is what we'd comoute them to.
> >> > +                */
> >> > +               for (level = 0; level <= max_level; level++)
> >> > +                       active->wm[level].enable = true;
> >>
> >> Why exactly do we compute them like this?
> >
> > The assumption is that for a disabled pipe all watermarks are zero,
> > which means all the levels are valid.
> 
> But valid != enabled. This is the confusing part IMHO.

I blame you for that ;) I called this sucker 'valid' in my original
monster RFC patch, but your HSW watermark rework had pretty much the
same thing but called 'enable' and that's what we have now.

> 
> 
> >
> >>
> >> One thing that I noticed is that, both on current -nightly (without
> >> your series) and with your series, when we disable all the screens we
> >> zero all the watermarks, but leave the "enable" bits of the LP
> >> watermarks enabled. IMHO we should treat this as a bug and fix it. I
> >> wonder if the comment above is related with this problem.
> >
> > Why is that a problem?
> 
> Because it relies on something that's only implied by the
> specification and probably not really thoroughly validated (or
> validated at all). I really don't like abusing the HW like that. Just
> take a look at the amount of HW workarounds we already have for the
> "happy cases"... I really prefer to be on the safer side.

Well, we can't really "fix" it unless we reorganize the rtc_enable/disable
code. The plane enable/disable should get moved for everyrhing like we
did for HSW, so that it's clear when we no longer depend on the
watermarks. And after that we'd need to either move the crtc->active=false
assignment earlier in the .crtc_disable, or we need to add some other
knob for the watermark code to check.

> 
> 
> >
> >>
> >>
> >> > +       }
> >> > +}
> >> > +
> >> > +void ilk_init_wm(struct drm_device *dev)
> >>
> >> IMHO, maintaining the _get_hw_state nomenclature would be an improvement.
> >
> > OK.
> >
> >>
> >>
> >> > +{
> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> >> > +       struct drm_crtc *crtc;
> >> > +
> >> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> >> > +               ilk_init_pipe_wm(crtc);
> >> > +
> >> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> >> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> >> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> >> > +
> >> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> >> > +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> >> > +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> >> > +
> >> > +       hw->partitioning =
> >> > +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
> >>
> >> This is a little bit dangerous... We never know if we're not going to
> >> add a 4_6 partition type in the middle of the enum for Gen 17. And if
> >> we add it, I'm 100% sure we'll forget to patch this line. I usually
> >> try to avoid these things.
> >
> > I happen to know that we won't get such a thing ;) Well, unless the
> > hardware designers start backpedaling after a few gens.
> >
> > So how would you write this?
> 
> With the simpler form:
> 
> hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> 
> Even if the enum value changes, the code will remain correct on
> Haswell, I hope :)

OK.

> 
> 
> >
> >>
> >>
> >> > +
> >> > +       hw->enable_fbc_wm =
> >> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> >> > +}
> >> > +
> >> >  /**
> >> >   * intel_update_watermarks - update FIFO watermark values based on current modes
> >>
> >> Also, this patch makes me wonder about those places where we change
> >> the HW state directly (init_clock_gating, for example) without
> >> touching the struct you just added. That specific init_clock_gating is
> >> run before we call ilk_init_wm, so it shouldn't be a problem on
> >> boot/resume, but it still leaves me worried...
> >
> > One option would be to kill the WM stuff from init_clock_gating. I think
> > it's just a safety measure to have it there, but I don't really see much
> > reason to keep it.
> 
> Yeah, I always wonder if that's really needed or not.
> 
> Advantages of keeping it:
> - it reduces our possibility of triggering an underrun when we do the
> other clock_gating stuff
> - if the BIOS does it wrong, we can minimize its failure
> 
> Disadvantages:
> - we may want the possible underruns when we do the other clock_gating
> stuff, since they're probably wrong anyway
> - if we ever get to a point where we do zero modesets when loading the
> driver, we'll just mess the watermarks.
> 
> To counter the second advantage of keeping it, we could even write
> intel_sanitize_watermarks :)
> 
> But that's all material for future patches.
> 
> >
> >>
> >> Also, perhaps we could have one of those functions that try to check
> >> if the tracked state is really the HW state...
> >
> > Yeah, that should be doable. But the watermark update is going to become
> > a staged process when I'm through with it, so we need to be careful
> > where we do the check to make sure we compare with the right sw state.
> 
> Let's focus on merging your current plans first, then we think about
> these things then.
> 
> 
> >
> >>
> >> >   *
> >> > --
> >> > 1.8.1.5
> >> >
> >> > _______________________________________________
> >> > Intel-gfx mailing list
> >> > Intel-gfx@lists.freedesktop.org
> >> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >>
> >>
> >>
> >> --
> >> Paulo Zanoni
> >
> > --
> > Ville Syrjälä
> > Intel OTC
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/16] drm/i915: Add watermark tracepoints
  2013-10-09 16:18 ` [PATCH 14/16] drm/i915: Add watermark tracepoints ville.syrjala
@ 2013-10-11 19:40   ` Paulo Zanoni
  2013-10-15  8:43     ` Daniel Vetter
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 19:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/9  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@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@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@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@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 19:12         ` Ville Syrjälä
@ 2013-10-11 19:46           ` Paulo Zanoni
  2013-10-14 11:21             ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-11 19:46 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> On Fri, Oct 11, 2013 at 03:15:48PM -0300, Paulo Zanoni wrote:
>> 2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
>> > On Fri, Oct 11, 2013 at 01:45:27PM -0300, Paulo Zanoni wrote:
>> >> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >> >
>> >> > Fill out the HSW watermark s/w tracking structures with the current
>> >> > hardware state in intel_modeset_setup_hw_state(). This allows us to skip
>> >> > the HW state readback during watermark programming and just use the values
>> >> > we keep around in dev_priv->wm. Reduces the overhead of the watermark
>> >> > programming quite a bit.
>> >> >
>> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >> > ---
>> >> >  drivers/gpu/drm/i915/intel_display.c |   3 +
>> >> >  drivers/gpu/drm/i915/intel_drv.h     |   1 +
>> >> >  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
>> >> >  3 files changed, 82 insertions(+), 26 deletions(-)
>> >> >
>> >> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> >> > index 27f98bc..194f933 100644
>> >> > --- a/drivers/gpu/drm/i915/intel_display.c
>> >> > +++ b/drivers/gpu/drm/i915/intel_display.c
>> >> > @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>> >> >                 pll->on = false;
>> >> >         }
>> >> >
>> >> > +       if (IS_HASWELL(dev))
>> >> > +               ilk_init_wm(dev);
>> >>
>> >> If is_HSW, then ILK_something is quite confusing :) Not everybody is
>> >> aware of your greater plans for total watermarks domination.
>> >>
>> >>
>> >> > +
>> >> >         if (force_restore) {
>> >> >                 i915_redisable_vga(dev);
>> >> >
>> >> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> >> > index 3325b0b..bdb1708 100644
>> >> > --- a/drivers/gpu/drm/i915/intel_drv.h
>> >> > +++ b/drivers/gpu/drm/i915/intel_drv.h
>> >> > @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>> >> >  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>> >> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>> >> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
>> >> > +void ilk_init_wm(struct drm_device *dev);
>> >> >
>> >> >
>> >> >  /* intel_sdvo.c */
>> >> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> >> > index 5bd8c73..cebd9b4 100644
>> >> > --- a/drivers/gpu/drm/i915/intel_pm.c
>> >> > +++ b/drivers/gpu/drm/i915/intel_pm.c
>> >> > @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>> >> >  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >> >                                 struct hsw_wm_values *results)
>> >> >  {
>> >> > -       struct hsw_wm_values previous;
>> >> > +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
>> >> >         unsigned int dirty;
>> >> >         uint32_t val;
>> >> >
>> >> > -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
>> >> > -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
>> >> > -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
>> >> > -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
>> >> > -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
>> >> > -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
>> >> > -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
>> >> > -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
>> >> > -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
>> >> > -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
>> >> > -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
>> >> > -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
>> >> > -
>> >> > -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
>> >> > -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
>> >> > -
>> >> > -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> >> > -
>> >> > -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
>> >> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
>> >> >         if (!dirty)
>> >> >                 return;
>> >> >
>> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
>> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
>> >> >                 I915_WRITE(WM3_LP_ILK, 0);
>> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
>> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
>> >> >                 I915_WRITE(WM2_LP_ILK, 0);
>> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
>> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
>> >> >                 I915_WRITE(WM1_LP_ILK, 0);
>> >> >
>> >> >         if (dirty & WM_DIRTY_PIPE(PIPE_A))
>> >> > @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>> >> >                 I915_WRITE(DISP_ARB_CTL, val);
>> >> >         }
>> >> >
>> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
>> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
>> >> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
>> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
>> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
>> >> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
>> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
>> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
>> >> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>> >> >
>> >> >         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
>> >> > @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
>> >> >         I915_WRITE(WM3S_LP_IVB, sprite_wm);
>> >> >  }
>> >> >
>> >> > +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
>> >> > +{
>> >> > +       struct drm_device *dev = crtc->dev;
>> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
>> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
>> >> > +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> >> > +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
>> >> > +       enum pipe pipe = intel_crtc->pipe;
>> >> > +       static const unsigned int wm0_pipe_reg[] = {
>> >> > +               [PIPE_A] = WM0_PIPEA_ILK,
>> >> > +               [PIPE_B] = WM0_PIPEB_ILK,
>> >> > +               [PIPE_C] = WM0_PIPEC_IVB,
>> >> > +       };
>> >> > +
>> >> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
>> >> > +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
>> >> > +
>> >> > +       /* Assume sprites are disabled */
>> >>
>> >> Why? Please write in the comment.
>> >
>> > Actually that's a leftover from before I reordered some of my patches.
>> > In a later stage I want to track sprite status in intel_pipe_wm, so the
>> > comment was meant to tell the reader why we don't populate that
>> > information here. And the real reason for not populating that
>> > information is that I'm lazy and figured sprites will never be enabled
>> > when we load the driver.
>> >
>> > But for now, I'll just kill the comment since it's utter nonsense at the
>> > moment.
>> >
>> >>
>> >>
>> >> > +
>> >> > +       if (intel_crtc_active(crtc)) {
>> >> > +               u32 tmp = hw->wm_pipe[pipe];
>> >> > +
>> >> > +               /*
>> >> > +                * For active pipes LP0 watermark is marked as
>> >> > +                * enabled, and LP1+ watermaks as disabled since
>> >> > +                * we can't really reverse compute them in case
>> >> > +                * multiple pipes are active.
>> >> > +                */
>> >> > +               active->wm[0].enable = true;
>> >> > +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
>> >> > +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
>> >> > +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
>> >> > +               active->linetime = hw->wm_linetime[pipe];
>> >> > +       } else {
>> >> > +               int level, max_level = ilk_wm_max_level(dev);
>> >> > +
>> >> > +               /*
>> >> > +                * For inactive pipes, all watermark levels
>> >> > +                * should be marked as enabled but zeroed,
>> >> > +                * which is what we'd comoute them to.
>> >> > +                */
>> >> > +               for (level = 0; level <= max_level; level++)
>> >> > +                       active->wm[level].enable = true;
>> >>
>> >> Why exactly do we compute them like this?
>> >
>> > The assumption is that for a disabled pipe all watermarks are zero,
>> > which means all the levels are valid.
>>
>> But valid != enabled. This is the confusing part IMHO.
>
> I blame you for that ;) I called this sucker 'valid' in my original
> monster RFC patch, but your HSW watermark rework had pretty much the
> same thing but called 'enable' and that's what we have now.

I have to be honest, I thought it would be waaaay easier for you to
reuse my watermarks code.

>
>>
>>
>> >
>> >>
>> >> One thing that I noticed is that, both on current -nightly (without
>> >> your series) and with your series, when we disable all the screens we
>> >> zero all the watermarks, but leave the "enable" bits of the LP
>> >> watermarks enabled. IMHO we should treat this as a bug and fix it. I
>> >> wonder if the comment above is related with this problem.
>> >
>> > Why is that a problem?
>>
>> Because it relies on something that's only implied by the
>> specification and probably not really thoroughly validated (or
>> validated at all). I really don't like abusing the HW like that. Just
>> take a look at the amount of HW workarounds we already have for the
>> "happy cases"... I really prefer to be on the safer side.
>
> Well, we can't really "fix" it unless we reorganize the rtc_enable/disable
> code. The plane enable/disable should get moved for everyrhing like we
> did for HSW, so that it's clear when we no longer depend on the
> watermarks. And after that we'd need to either move the crtc->active=false
> assignment earlier in the .crtc_disable, or we need to add some other
> knob for the watermark code to check.

I thought it was a simple regression since my original code didn't do this...

>
>>
>>
>> >
>> >>
>> >>
>> >> > +       }
>> >> > +}
>> >> > +
>> >> > +void ilk_init_wm(struct drm_device *dev)
>> >>
>> >> IMHO, maintaining the _get_hw_state nomenclature would be an improvement.
>> >
>> > OK.
>> >
>> >>
>> >>
>> >> > +{
>> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
>> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
>> >> > +       struct drm_crtc *crtc;
>> >> > +
>> >> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
>> >> > +               ilk_init_pipe_wm(crtc);
>> >> > +
>> >> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
>> >> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
>> >> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
>> >> > +
>> >> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
>> >> > +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
>> >> > +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
>> >> > +
>> >> > +       hw->partitioning =
>> >> > +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
>> >>
>> >> This is a little bit dangerous... We never know if we're not going to
>> >> add a 4_6 partition type in the middle of the enum for Gen 17. And if
>> >> we add it, I'm 100% sure we'll forget to patch this line. I usually
>> >> try to avoid these things.
>> >
>> > I happen to know that we won't get such a thing ;) Well, unless the
>> > hardware designers start backpedaling after a few gens.
>> >
>> > So how would you write this?
>>
>> With the simpler form:
>>
>> hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
>> INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
>>
>> Even if the enum value changes, the code will remain correct on
>> Haswell, I hope :)
>
> OK.
>
>>
>>
>> >
>> >>
>> >>
>> >> > +
>> >> > +       hw->enable_fbc_wm =
>> >> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> >> > +}
>> >> > +
>> >> >  /**
>> >> >   * intel_update_watermarks - update FIFO watermark values based on current modes
>> >>
>> >> Also, this patch makes me wonder about those places where we change
>> >> the HW state directly (init_clock_gating, for example) without
>> >> touching the struct you just added. That specific init_clock_gating is
>> >> run before we call ilk_init_wm, so it shouldn't be a problem on
>> >> boot/resume, but it still leaves me worried...
>> >
>> > One option would be to kill the WM stuff from init_clock_gating. I think
>> > it's just a safety measure to have it there, but I don't really see much
>> > reason to keep it.
>>
>> Yeah, I always wonder if that's really needed or not.
>>
>> Advantages of keeping it:
>> - it reduces our possibility of triggering an underrun when we do the
>> other clock_gating stuff
>> - if the BIOS does it wrong, we can minimize its failure
>>
>> Disadvantages:
>> - we may want the possible underruns when we do the other clock_gating
>> stuff, since they're probably wrong anyway
>> - if we ever get to a point where we do zero modesets when loading the
>> driver, we'll just mess the watermarks.
>>
>> To counter the second advantage of keeping it, we could even write
>> intel_sanitize_watermarks :)
>>
>> But that's all material for future patches.
>>
>> >
>> >>
>> >> Also, perhaps we could have one of those functions that try to check
>> >> if the tracked state is really the HW state...
>> >
>> > Yeah, that should be doable. But the watermark update is going to become
>> > a staged process when I'm through with it, so we need to be careful
>> > where we do the check to make sure we compare with the right sw state.
>>
>> Let's focus on merging your current plans first, then we think about
>> these things then.
>>
>>
>> >
>> >>
>> >> >   *
>> >> > --
>> >> > 1.8.1.5
>> >> >
>> >> > _______________________________________________
>> >> > Intel-gfx mailing list
>> >> > Intel-gfx@lists.freedesktop.org
>> >> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> >>
>> >>
>> >>
>> >> --
>> >> Paulo Zanoni
>> >
>> > --
>> > Ville Syrjälä
>> > Intel OTC
>>
>>
>>
>> --
>> Paulo Zanoni
>
> --
> Ville Syrjälä
> Intel OTC



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 19:46           ` Paulo Zanoni
@ 2013-10-14 11:21             ` Ville Syrjälä
  0 siblings, 0 replies; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-14 11:21 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 04:46:58PM -0300, Paulo Zanoni wrote:
> 2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> > On Fri, Oct 11, 2013 at 03:15:48PM -0300, Paulo Zanoni wrote:
> >> 2013/10/11 Ville Syrjälä <ville.syrjala@linux.intel.com>:
> >> > On Fri, Oct 11, 2013 at 01:45:27PM -0300, Paulo Zanoni wrote:
> >> >> 2013/10/9  <ville.syrjala@linux.intel.com>:
> >> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >> >
> >> >> > Fill out the HSW watermark s/w tracking structures with the current
> >> >> > hardware state in intel_modeset_setup_hw_state(). This allows us to skip
> >> >> > the HW state readback during watermark programming and just use the values
> >> >> > we keep around in dev_priv->wm. Reduces the overhead of the watermark
> >> >> > programming quite a bit.
> >> >> >
> >> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >> > ---
> >> >> >  drivers/gpu/drm/i915/intel_display.c |   3 +
> >> >> >  drivers/gpu/drm/i915/intel_drv.h     |   1 +
> >> >> >  drivers/gpu/drm/i915/intel_pm.c      | 104 ++++++++++++++++++++++++++---------
> >> >> >  3 files changed, 82 insertions(+), 26 deletions(-)
> >> >> >
> >> >> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> >> > index 27f98bc..194f933 100644
> >> >> > --- a/drivers/gpu/drm/i915/intel_display.c
> >> >> > +++ b/drivers/gpu/drm/i915/intel_display.c
> >> >> > @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
> >> >> >                 pll->on = false;
> >> >> >         }
> >> >> >
> >> >> > +       if (IS_HASWELL(dev))
> >> >> > +               ilk_init_wm(dev);
> >> >>
> >> >> If is_HSW, then ILK_something is quite confusing :) Not everybody is
> >> >> aware of your greater plans for total watermarks domination.
> >> >>
> >> >>
> >> >> > +
> >> >> >         if (force_restore) {
> >> >> >                 i915_redisable_vga(dev);
> >> >> >
> >> >> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> >> > index 3325b0b..bdb1708 100644
> >> >> > --- a/drivers/gpu/drm/i915/intel_drv.h
> >> >> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> >> >> > @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
> >> >> >  void gen6_rps_boost(struct drm_i915_private *dev_priv);
> >> >> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> >> >> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> >> >> > +void ilk_init_wm(struct drm_device *dev);
> >> >> >
> >> >> >
> >> >> >  /* intel_sdvo.c */
> >> >> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> >> >> > index 5bd8c73..cebd9b4 100644
> >> >> > --- a/drivers/gpu/drm/i915/intel_pm.c
> >> >> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> >> >> > @@ -2840,37 +2840,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
> >> >> >  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >> >> >                                 struct hsw_wm_values *results)
> >> >> >  {
> >> >> > -       struct hsw_wm_values previous;
> >> >> > +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
> >> >> >         unsigned int dirty;
> >> >> >         uint32_t val;
> >> >> >
> >> >> > -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> >> >> > -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> >> >> > -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> >> >> > -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> >> >> > -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> >> >> > -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> >> >> > -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> >> >> > -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> >> >> > -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> >> >> > -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> >> >> > -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> >> >> > -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> >> >> > -
> >> >> > -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> >> >> > -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> >> >> > -
> >> >> > -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> >> >> > -
> >> >> > -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> >> >> > +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
> >> >> >         if (!dirty)
> >> >> >                 return;
> >> >> >
> >> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> >> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
> >> >> >                 I915_WRITE(WM3_LP_ILK, 0);
> >> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> >> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
> >> >> >                 I915_WRITE(WM2_LP_ILK, 0);
> >> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> >> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
> >> >> >                 I915_WRITE(WM1_LP_ILK, 0);
> >> >> >
> >> >> >         if (dirty & WM_DIRTY_PIPE(PIPE_A))
> >> >> > @@ -2905,11 +2887,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
> >> >> >                 I915_WRITE(DISP_ARB_CTL, val);
> >> >> >         }
> >> >> >
> >> >> > -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> >> >> > +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
> >> >> >                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> >> >> > -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> >> >> > +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
> >> >> >                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> >> >> > -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> >> >> > +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
> >> >> >                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
> >> >> >
> >> >> >         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> >> >> > @@ -3142,6 +3124,76 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
> >> >> >         I915_WRITE(WM3S_LP_IVB, sprite_wm);
> >> >> >  }
> >> >> >
> >> >> > +static void ilk_init_pipe_wm(struct drm_crtc *crtc)
> >> >> > +{
> >> >> > +       struct drm_device *dev = crtc->dev;
> >> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> >> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> >> >> > +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >> >> > +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
> >> >> > +       enum pipe pipe = intel_crtc->pipe;
> >> >> > +       static const unsigned int wm0_pipe_reg[] = {
> >> >> > +               [PIPE_A] = WM0_PIPEA_ILK,
> >> >> > +               [PIPE_B] = WM0_PIPEB_ILK,
> >> >> > +               [PIPE_C] = WM0_PIPEC_IVB,
> >> >> > +       };
> >> >> > +
> >> >> > +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> >> >> > +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> >> >> > +
> >> >> > +       /* Assume sprites are disabled */
> >> >>
> >> >> Why? Please write in the comment.
> >> >
> >> > Actually that's a leftover from before I reordered some of my patches.
> >> > In a later stage I want to track sprite status in intel_pipe_wm, so the
> >> > comment was meant to tell the reader why we don't populate that
> >> > information here. And the real reason for not populating that
> >> > information is that I'm lazy and figured sprites will never be enabled
> >> > when we load the driver.
> >> >
> >> > But for now, I'll just kill the comment since it's utter nonsense at the
> >> > moment.
> >> >
> >> >>
> >> >>
> >> >> > +
> >> >> > +       if (intel_crtc_active(crtc)) {
> >> >> > +               u32 tmp = hw->wm_pipe[pipe];
> >> >> > +
> >> >> > +               /*
> >> >> > +                * For active pipes LP0 watermark is marked as
> >> >> > +                * enabled, and LP1+ watermaks as disabled since
> >> >> > +                * we can't really reverse compute them in case
> >> >> > +                * multiple pipes are active.
> >> >> > +                */
> >> >> > +               active->wm[0].enable = true;
> >> >> > +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
> >> >> > +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
> >> >> > +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
> >> >> > +               active->linetime = hw->wm_linetime[pipe];
> >> >> > +       } else {
> >> >> > +               int level, max_level = ilk_wm_max_level(dev);
> >> >> > +
> >> >> > +               /*
> >> >> > +                * For inactive pipes, all watermark levels
> >> >> > +                * should be marked as enabled but zeroed,
> >> >> > +                * which is what we'd comoute them to.
> >> >> > +                */
> >> >> > +               for (level = 0; level <= max_level; level++)
> >> >> > +                       active->wm[level].enable = true;
> >> >>
> >> >> Why exactly do we compute them like this?
> >> >
> >> > The assumption is that for a disabled pipe all watermarks are zero,
> >> > which means all the levels are valid.
> >>
> >> But valid != enabled. This is the confusing part IMHO.
> >
> > I blame you for that ;) I called this sucker 'valid' in my original
> > monster RFC patch, but your HSW watermark rework had pretty much the
> > same thing but called 'enable' and that's what we have now.
> 
> I have to be honest, I thought it would be waaaay easier for you to
> reuse my watermarks code.

It's quite possible I've made it harder on myself by sticking a bit too
closely to my original vision :)

> 
> >
> >>
> >>
> >> >
> >> >>
> >> >> One thing that I noticed is that, both on current -nightly (without
> >> >> your series) and with your series, when we disable all the screens we
> >> >> zero all the watermarks, but leave the "enable" bits of the LP
> >> >> watermarks enabled. IMHO we should treat this as a bug and fix it. I
> >> >> wonder if the comment above is related with this problem.
> >> >
> >> > Why is that a problem?
> >>
> >> Because it relies on something that's only implied by the
> >> specification and probably not really thoroughly validated (or
> >> validated at all). I really don't like abusing the HW like that. Just
> >> take a look at the amount of HW workarounds we already have for the
> >> "happy cases"... I really prefer to be on the safer side.
> >
> > Well, we can't really "fix" it unless we reorganize the rtc_enable/disable
> > code. The plane enable/disable should get moved for everyrhing like we
> > did for HSW, so that it's clear when we no longer depend on the
> > watermarks. And after that we'd need to either move the crtc->active=false
> > assignment earlier in the .crtc_disable, or we need to add some other
> > knob for the watermark code to check.
> 
> I thought it was a simple regression since my original code didn't do this...


> 
> >
> >>
> >>
> >> >
> >> >>
> >> >>
> >> >> > +       }
> >> >> > +}
> >> >> > +
> >> >> > +void ilk_init_wm(struct drm_device *dev)
> >> >>
> >> >> IMHO, maintaining the _get_hw_state nomenclature would be an improvement.
> >> >
> >> > OK.
> >> >
> >> >>
> >> >>
> >> >> > +{
> >> >> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> >> >> > +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> >> >> > +       struct drm_crtc *crtc;
> >> >> > +
> >> >> > +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> >> >> > +               ilk_init_pipe_wm(crtc);
> >> >> > +
> >> >> > +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> >> >> > +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> >> >> > +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> >> >> > +
> >> >> > +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> >> >> > +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> >> >> > +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> >> >> > +
> >> >> > +       hw->partitioning =
> >> >> > +               !!(I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6);
> >> >>
> >> >> This is a little bit dangerous... We never know if we're not going to
> >> >> add a 4_6 partition type in the middle of the enum for Gen 17. And if
> >> >> we add it, I'm 100% sure we'll forget to patch this line. I usually
> >> >> try to avoid these things.
> >> >
> >> > I happen to know that we won't get such a thing ;) Well, unless the
> >> > hardware designers start backpedaling after a few gens.
> >> >
> >> > So how would you write this?
> >>
> >> With the simpler form:
> >>
> >> hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> >> INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> >>
> >> Even if the enum value changes, the code will remain correct on
> >> Haswell, I hope :)
> >
> > OK.
> >
> >>
> >>
> >> >
> >> >>
> >> >>
> >> >> > +
> >> >> > +       hw->enable_fbc_wm =
> >> >> > +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> >> >> > +}
> >> >> > +
> >> >> >  /**
> >> >> >   * intel_update_watermarks - update FIFO watermark values based on current modes
> >> >>
> >> >> Also, this patch makes me wonder about those places where we change
> >> >> the HW state directly (init_clock_gating, for example) without
> >> >> touching the struct you just added. That specific init_clock_gating is
> >> >> run before we call ilk_init_wm, so it shouldn't be a problem on
> >> >> boot/resume, but it still leaves me worried...
> >> >
> >> > One option would be to kill the WM stuff from init_clock_gating. I think
> >> > it's just a safety measure to have it there, but I don't really see much
> >> > reason to keep it.
> >>
> >> Yeah, I always wonder if that's really needed or not.
> >>
> >> Advantages of keeping it:
> >> - it reduces our possibility of triggering an underrun when we do the
> >> other clock_gating stuff
> >> - if the BIOS does it wrong, we can minimize its failure
> >>
> >> Disadvantages:
> >> - we may want the possible underruns when we do the other clock_gating
> >> stuff, since they're probably wrong anyway
> >> - if we ever get to a point where we do zero modesets when loading the
> >> driver, we'll just mess the watermarks.
> >>
> >> To counter the second advantage of keeping it, we could even write
> >> intel_sanitize_watermarks :)
> >>
> >> But that's all material for future patches.
> >>
> >> >
> >> >>
> >> >> Also, perhaps we could have one of those functions that try to check
> >> >> if the tracked state is really the HW state...
> >> >
> >> > Yeah, that should be doable. But the watermark update is going to become
> >> > a staged process when I'm through with it, so we need to be careful
> >> > where we do the check to make sure we compare with the right sw state.
> >>
> >> Let's focus on merging your current plans first, then we think about
> >> these things then.
> >>
> >>
> >> >
> >> >>
> >> >> >   *
> >> >> > --
> >> >> > 1.8.1.5
> >> >> >
> >> >> > _______________________________________________
> >> >> > Intel-gfx mailing list
> >> >> > Intel-gfx@lists.freedesktop.org
> >> >> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >> >>
> >> >>
> >> >>
> >> >> --
> >> >> Paulo Zanoni
> >> >
> >> > --
> >> > Ville Syrjälä
> >> > Intel OTC
> >>
> >>
> >>
> >> --
> >> Paulo Zanoni
> >
> > --
> > Ville Syrjälä
> > Intel OTC
> 
> 
> 
> -- 
> Paulo Zanoni

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v2 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-11 16:45   ` Paulo Zanoni
  2013-10-11 17:15     ` Ville Syrjälä
@ 2013-10-14 11:55     ` ville.syrjala
  2013-10-14 13:56       ` Paulo Zanoni
  1 sibling, 1 reply; 59+ messages in thread
From: ville.syrjala @ 2013-10-14 11:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Fill out the HSW watermark s/w tracking structures with the current
hardware state in intel_modeset_setup_hw_state(). This allows us to skip
the HW state readback during watermark programming and just use the values
we keep around in dev_priv->wm. Reduces the overhead of the watermark
programming quite a bit.

v2: s/init_wm/wm_get_hw_state
    Remove stale comment about sprites
    Make DDB partitioning readout safer

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   3 ++
 drivers/gpu/drm/i915/intel_drv.h     |   1 +
 drivers/gpu/drm/i915/intel_pm.c      | 102 ++++++++++++++++++++++++++---------
 3 files changed, 80 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 27f98bc..fada569 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 		pll->on = false;
 	}
 
+	if (IS_HASWELL(dev))
+		ilk_wm_get_hw_state(dev);
+
 	if (force_restore) {
 		i915_redisable_vga(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3325b0b..a652075 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c3e5c0b..098f803 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2843,37 +2843,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
 static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 				struct hsw_wm_values *results)
 {
-	struct hsw_wm_values previous;
+	struct hsw_wm_values *previous = &dev_priv->wm.hw;
 	unsigned int dirty;
 	uint32_t val;
 
-	previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
-	previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
-	previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
-	previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
-	previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
-	previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
-	previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
-	previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
-	previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
-	previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
-	previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
-
-	previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-				INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-
-	previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
-
-	dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
+	dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
 	if (!dirty)
 		return;
 
-	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
+	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
 		I915_WRITE(WM3_LP_ILK, 0);
-	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
+	if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
 		I915_WRITE(WM2_LP_ILK, 0);
-	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
+	if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
 		I915_WRITE(WM1_LP_ILK, 0);
 
 	if (dirty & WM_DIRTY_PIPE(PIPE_A))
@@ -2908,11 +2890,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
 		I915_WRITE(DISP_ARB_CTL, val);
 	}
 
-	if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
+	if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
 		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-	if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
+	if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
 		I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-	if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
+	if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
 		I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
 	if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
@@ -3145,6 +3127,74 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
 	I915_WRITE(WM3S_LP_IVB, sprite_wm);
 }
 
+static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct hsw_wm_values *hw = &dev_priv->wm.hw;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_pipe_wm *active = &intel_crtc->wm.active;
+	enum pipe pipe = intel_crtc->pipe;
+	static const unsigned int wm0_pipe_reg[] = {
+		[PIPE_A] = WM0_PIPEA_ILK,
+		[PIPE_B] = WM0_PIPEB_ILK,
+		[PIPE_C] = WM0_PIPEC_IVB,
+	};
+
+	hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
+	hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+
+	if (intel_crtc_active(crtc)) {
+		u32 tmp = hw->wm_pipe[pipe];
+
+		/*
+		 * For active pipes LP0 watermark is marked as
+		 * enabled, and LP1+ watermaks as disabled since
+		 * we can't really reverse compute them in case
+		 * multiple pipes are active.
+		 */
+		active->wm[0].enable = true;
+		active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
+		active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
+		active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
+		active->linetime = hw->wm_linetime[pipe];
+	} else {
+		int level, max_level = ilk_wm_max_level(dev);
+
+		/*
+		 * For inactive pipes, all watermark levels
+		 * should be marked as enabled but zeroed,
+		 * which is what we'd compute them to.
+		 */
+		for (level = 0; level <= max_level; level++)
+			active->wm[level].enable = true;
+	}
+}
+
+void ilk_wm_get_hw_state(struct drm_device *dev)
+{
+ 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct hsw_wm_values *hw = &dev_priv->wm.hw;
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		ilk_pipe_wm_get_hw_state(crtc);
+
+	hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
+	hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
+	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
+
+	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
+	hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
+	hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
+
+	hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
+		INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+
+	hw->enable_fbc_wm =
+		!(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
+}
+
 /**
  * intel_update_watermarks - update FIFO watermark values based on current modes
  *
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v2 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state()
  2013-10-14 11:55     ` [PATCH v2 " ville.syrjala
@ 2013-10-14 13:56       ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-14 13:56 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development, Paulo Zanoni

2013/10/14  <ville.syrjala@linux.intel.com>:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Fill out the HSW watermark s/w tracking structures with the current
> hardware state in intel_modeset_setup_hw_state(). This allows us to skip
> the HW state readback during watermark programming and just use the values
> we keep around in dev_priv->wm. Reduces the overhead of the watermark
> programming quite a bit.
>
> v2: s/init_wm/wm_get_hw_state
>     Remove stale comment about sprites
>     Make DDB partitioning readout safer
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

That finishes the series, I guess?

> ---
>  drivers/gpu/drm/i915/intel_display.c |   3 ++
>  drivers/gpu/drm/i915/intel_drv.h     |   1 +
>  drivers/gpu/drm/i915/intel_pm.c      | 102 ++++++++++++++++++++++++++---------
>  3 files changed, 80 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 27f98bc..fada569 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -10820,6 +10820,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>                 pll->on = false;
>         }
>
> +       if (IS_HASWELL(dev))
> +               ilk_wm_get_hw_state(dev);
> +
>         if (force_restore) {
>                 i915_redisable_vga(dev);
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 3325b0b..a652075 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -818,6 +818,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> +void ilk_wm_get_hw_state(struct drm_device *dev);
>
>
>  /* intel_sdvo.c */
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c3e5c0b..098f803 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2843,37 +2843,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
>  static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                                 struct hsw_wm_values *results)
>  {
> -       struct hsw_wm_values previous;
> +       struct hsw_wm_values *previous = &dev_priv->wm.hw;
>         unsigned int dirty;
>         uint32_t val;
>
> -       previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK);
> -       previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK);
> -       previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB);
> -       previous.wm_lp[0] = I915_READ(WM1_LP_ILK);
> -       previous.wm_lp[1] = I915_READ(WM2_LP_ILK);
> -       previous.wm_lp[2] = I915_READ(WM3_LP_ILK);
> -       previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> -       previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> -       previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> -       previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A));
> -       previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B));
> -       previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C));
> -
> -       previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> -                               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> -
> -       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> -
> -       dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results);
> +       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
>         if (!dirty)
>                 return;
>
> -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0)
> +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
>                 I915_WRITE(WM3_LP_ILK, 0);
> -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0)
> +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
>                 I915_WRITE(WM2_LP_ILK, 0);
> -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0)
> +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
>                 I915_WRITE(WM1_LP_ILK, 0);
>
>         if (dirty & WM_DIRTY_PIPE(PIPE_A))
> @@ -2908,11 +2890,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
>                 I915_WRITE(DISP_ARB_CTL, val);
>         }
>
> -       if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0])
> +       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
>                 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
> -       if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1])
> +       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
>                 I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
> -       if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2])
> +       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
>                 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
>
>         if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
> @@ -3145,6 +3127,74 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
>         I915_WRITE(WM3S_LP_IVB, sprite_wm);
>  }
>
> +static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct intel_pipe_wm *active = &intel_crtc->wm.active;
> +       enum pipe pipe = intel_crtc->pipe;
> +       static const unsigned int wm0_pipe_reg[] = {
> +               [PIPE_A] = WM0_PIPEA_ILK,
> +               [PIPE_B] = WM0_PIPEB_ILK,
> +               [PIPE_C] = WM0_PIPEC_IVB,
> +       };
> +
> +       hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
> +       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
> +
> +       if (intel_crtc_active(crtc)) {
> +               u32 tmp = hw->wm_pipe[pipe];
> +
> +               /*
> +                * For active pipes LP0 watermark is marked as
> +                * enabled, and LP1+ watermaks as disabled since
> +                * we can't really reverse compute them in case
> +                * multiple pipes are active.
> +                */
> +               active->wm[0].enable = true;
> +               active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT;
> +               active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT;
> +               active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
> +               active->linetime = hw->wm_linetime[pipe];
> +       } else {
> +               int level, max_level = ilk_wm_max_level(dev);
> +
> +               /*
> +                * For inactive pipes, all watermark levels
> +                * should be marked as enabled but zeroed,
> +                * which is what we'd compute them to.
> +                */
> +               for (level = 0; level <= max_level; level++)
> +                       active->wm[level].enable = true;
> +       }
> +}
> +
> +void ilk_wm_get_hw_state(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct hsw_wm_values *hw = &dev_priv->wm.hw;
> +       struct drm_crtc *crtc;
> +
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> +               ilk_pipe_wm_get_hw_state(crtc);
> +
> +       hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
> +       hw->wm_lp[1] = I915_READ(WM2_LP_ILK);
> +       hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
> +
> +       hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
> +       hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
> +       hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
> +
> +       hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
> +               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
> +
> +       hw->enable_fbc_wm =
> +               !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> +}
> +
>  /**
>   * intel_update_watermarks - update FIFO watermark values based on current modes
>   *
> --
> 1.8.1.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm
  2013-10-11 14:21   ` Paulo Zanoni
@ 2013-10-15  8:24     ` Daniel Vetter
  2013-10-15 16:49       ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: Daniel Vetter @ 2013-10-15  8:24 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 11:21:04AM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:

[snip]

> > +       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
> > +
> > +       if (memcmp(results, &previous, sizeof(*results)) == 0)
> 
> This may cause problems since we're also comparing the structure
> paddings. It seems "results" is already zero-initialized, so if you
> also zero-initialize "previous" we'll probably be fine with the
> memcmp(). But my fear is that future code changes will break this, so
> if you stick with the new memcmp please add a comment remembering us
> that we rely on zero-initializing stuff. Or maybe keep the
> old-big-ugly code.

I've added a comment about this and then smashed your presumed r-b onto
the patch. Please scream if the patch as merged isn't good enough.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/16] drm/i915: Add watermark tracepoints
  2013-10-11 19:40   ` Paulo Zanoni
@ 2013-10-15  8:43     ` Daniel Vetter
  2013-10-15 10:11       ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Daniel Vetter @ 2013-10-15  8:43 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 04:40:24PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@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@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@intel.com>

I'm not sold on tracepoints being the right tool here. DRM_DEBUG_KMS
probably isn't it, since that would needlessly spam dmesg since it's way
too coarse. But the kernel has this neat dynamic debug subsystem, which
has the upshot that it's all nicely inline with the other modeset debug
noise in dmesg.

I'll punt on this for now.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level
  2013-10-11 17:08   ` Paulo Zanoni
@ 2013-10-15  9:16     ` Daniel Vetter
  2013-10-15 17:01       ` Paulo Zanoni
  0 siblings, 1 reply; 59+ messages in thread
From: Daniel Vetter @ 2013-10-15  9:16 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Fri, Oct 11, 2013 at 02:08:07PM -0300, Paulo Zanoni wrote:
> 2013/10/9  <ville.syrjala@linux.intel.com>:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Makes the behaviour of the function more clear.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Thanks :)
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

With the exception of the tracepoint patch I've merged the entire series,
thanks for patches&review.

Now all these watermark changes start to freak me out since we seem to
fully rely on Paulo's sharp eyes to check them. I really think it's time
to blow through a few cycles to independently check all this stuff. Some
ideas:

- Enable the fifo underrun stuff and make it really load. Maybe only on
  haswell for a start. If this starts to hit issues in the wild we might
  need some form of display error state which captures all the
  sprites/cursor/planes/crtc/wm/... state. Maybe we could do this as part
  of the error state stuff we already have, but with the GT side of things
  not enabled (since presumably the GT is really busy and we shouldn't
  unduly poke it).

- The hw state readout needs cross-checking. We now rely on the read out
  wm state (for the first modeset at least, but there's always fastboot).
  Experienc says that without cross checks this will get broken eventually
  and lead to fun-to-debug bugs.

- I'm not sure whether there's a sane way to dump out the wm settings and
  check them in userspace. Duplicating the entire calculation is pointless
  and we can't really integrate the excel spreadsheet from the hw guys
  into igt. And using a set of interesting corner-cases to test all the
  basic modes (one pipe, sprite splits, ...) is probably too inflexible.
  But if we can get stable watermark settings by e.g. injecting an special
  edid somewhere so that we know the exact dotclocks this might be
  interesting.

- At least exercising some of the special cases (and then relying on the
  state cross-checker and fifo underrun reporting to catch fallout) from
  userspace would be good.


I'm running a bit low on good stuff here, so better ideas highly welcome.
It's not really an area I've wreak much havoc in at all ...

One other thing I've noticed is that we still have calls to
intel_crtc_active sprinkled throughout the hsw wm functions. Should we be
able to ditch those and replace them with a plain crtc->active check, now
that we have wm state readout?

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/16] drm/i915: Add watermark tracepoints
  2013-10-15  8:43     ` Daniel Vetter
@ 2013-10-15 10:11       ` Ville Syrjälä
  2013-10-15 10:59         ` Daniel Vetter
  0 siblings, 1 reply; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-15 10:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Tue, Oct 15, 2013 at 10:43:31AM +0200, Daniel Vetter wrote:
> On Fri, Oct 11, 2013 at 04:40:24PM -0300, Paulo Zanoni wrote:
> > 2013/10/9  <ville.syrjala@linux.intel.com>:
> > > From: Ville Syrjälä <ville.syrjala@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@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@intel.com>
> 
> I'm not sold on tracepoints being the right tool here. DRM_DEBUG_KMS
> probably isn't it, since that would needlessly spam dmesg since it's way
> too coarse. But the kernel has this neat dynamic debug subsystem, which
> has the upshot that it's all nicely inline with the other modeset debug
> noise in dmesg.

I need to trace the watermark updates in relation to plane updates and
vblanks. Tracepoints seem like a good tool to me, though it does make
it a bit less useful for bug reports and such. I'm just worried that
regular printks add too much overhead to be all that useful for such
timing sensitive work with potentially quite a bit of trace data.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 14/16] drm/i915: Add watermark tracepoints
  2013-10-15 10:11       ` Ville Syrjälä
@ 2013-10-15 10:59         ` Daniel Vetter
  0 siblings, 0 replies; 59+ messages in thread
From: Daniel Vetter @ 2013-10-15 10:59 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Intel Graphics Development

On Tue, Oct 15, 2013 at 01:11:49PM +0300, Ville Syrjälä wrote:
> On Tue, Oct 15, 2013 at 10:43:31AM +0200, Daniel Vetter wrote:
> > On Fri, Oct 11, 2013 at 04:40:24PM -0300, Paulo Zanoni wrote:
> > > 2013/10/9  <ville.syrjala@linux.intel.com>:
> > > > From: Ville Syrjälä <ville.syrjala@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@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@intel.com>
> > 
> > I'm not sold on tracepoints being the right tool here. DRM_DEBUG_KMS
> > probably isn't it, since that would needlessly spam dmesg since it's way
> > too coarse. But the kernel has this neat dynamic debug subsystem, which
> > has the upshot that it's all nicely inline with the other modeset debug
> > noise in dmesg.
> 
> I need to trace the watermark updates in relation to plane updates and
> vblanks. Tracepoints seem like a good tool to me, though it does make
> it a bit less useful for bug reports and such. I'm just worried that
> regular printks add too much overhead to be all that useful for such
> timing sensitive work with potentially quite a bit of trace data.

Hm, I've thought we'd only dump the wm state once it's computed before we
bash it into the hw. That part doesn't really feel timing critical, at
least as long as we have the printks disabled by default. Otherwise
syslogd will bring the system down ;-) Now I haven't really played around
with it yet, but the dynamic printk stuff seemed to fit that bill.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm
  2013-10-15  8:24     ` Daniel Vetter
@ 2013-10-15 16:49       ` Paulo Zanoni
  0 siblings, 0 replies; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-15 16:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

2013/10/15 Daniel Vetter <daniel@ffwll.ch>:
> On Fri, Oct 11, 2013 at 11:21:04AM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>
> [snip]
>
>> > +       previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
>> > +
>> > +       if (memcmp(results, &previous, sizeof(*results)) == 0)
>>
>> This may cause problems since we're also comparing the structure
>> paddings. It seems "results" is already zero-initialized, so if you
>> also zero-initialize "previous" we'll probably be fine with the
>> memcmp(). But my fear is that future code changes will break this, so
>> if you stick with the new memcmp please add a comment remembering us
>> that we rely on zero-initializing stuff. Or maybe keep the
>> old-big-ugly code.
>
> I've added a comment about this and then smashed your presumed r-b onto
> the patch. Please scream if the patch as merged isn't good enough.

Patch 10 removes the memcmp, so the problem is fixed. You should then
remove the comment on that patch.

> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level
  2013-10-15  9:16     ` Daniel Vetter
@ 2013-10-15 17:01       ` Paulo Zanoni
  2013-10-15 17:46         ` Ville Syrjälä
  0 siblings, 1 reply; 59+ messages in thread
From: Paulo Zanoni @ 2013-10-15 17:01 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

2013/10/15 Daniel Vetter <daniel@ffwll.ch>:
> On Fri, Oct 11, 2013 at 02:08:07PM -0300, Paulo Zanoni wrote:
>> 2013/10/9  <ville.syrjala@linux.intel.com>:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Makes the behaviour of the function more clear.
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> Thanks :)
>>
>> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> With the exception of the tracepoint patch I've merged the entire series,
> thanks for patches&review.
>
> Now all these watermark changes start to freak me out since we seem to
> fully rely on Paulo's sharp eyes to check them. I really think it's time
> to blow through a few cycles to independently check all this stuff. Some
> ideas:

Before reviewing each of Ville's series I usually dump the current WM
configurations of eDP-only, eDP+DP, nothing, DP+something with
intel-reg-dumper and then apply his patches and compare the results.
So far we're good, the only change I have noticed was already
discussed here. Also, all this code only runs on Haswell right now
(even though the goal is to run it on ILK+), so checking regressions
is not really that hard today. Of course, I don't do full corner-case
checking.

I always thought about writing some IGT test to check watermarks, but
the problem is that we'd have to reimplement the WM code on user space
if we want to validate the Kernel code, so not really a feasible
solution.

>
> - Enable the fifo underrun stuff and make it really load. Maybe only on
>   haswell for a start. If this starts to hit issues in the wild we might
>   need some form of display error state which captures all the
>   sprites/cursor/planes/crtc/wm/... state. Maybe we could do this as part
>   of the error state stuff we already have, but with the GT side of things
>   not enabled (since presumably the GT is really busy and we shouldn't
>   unduly poke it).

That was already suggested, but since Ville seems to have the code to
properly set watermarks on ILK+ already written, I think we should
just wait for it.

>
> - The hw state readout needs cross-checking. We now rely on the read out
>   wm state (for the first modeset at least, but there's always fastboot).
>   Experienc says that without cross checks this will get broken eventually
>   and lead to fun-to-debug bugs.

The nice thing of this series is that it adds the infrastructure to do
the HW state readout + check. I even suggested this already. Maybe
it's already on Ville's TODO list :)

>
> - I'm not sure whether there's a sane way to dump out the wm settings and
>   check them in userspace. Duplicating the entire calculation is pointless
>   and we can't really integrate the excel spreadsheet from the hw guys
>   into igt. And using a set of interesting corner-cases to test all the
>   basic modes (one pipe, sprite splits, ...) is probably too inflexible.
>   But if we can get stable watermark settings by e.g. injecting an special
>   edid somewhere so that we know the exact dotclocks this might be
>   interesting.

Watermarks also depend on the machine memory configuration (SSKPD) so
that's not really easy... The intel-reg-dumper tools dumps all the
relevant registers and can be easily be used to compare against the
spreadsheed.

OTOH, we could "hardcode" the common SSKPD values (at least from QA's
machines) and the values for some common modes (1024x768, 1920x1080,
etc) and check the state set by the Kernel against our hardcoded
state... It's not the best solution, but at least it's something.

>
> - At least exercising some of the special cases (and then relying on the
>   state cross-checker and fifo underrun reporting to catch fallout) from
>   userspace would be good.
>
>
> I'm running a bit low on good stuff here, so better ideas highly welcome.
> It's not really an area I've wreak much havoc in at all ...
>
> One other thing I've noticed is that we still have calls to
> intel_crtc_active sprinkled throughout the hsw wm functions. Should we be
> able to ditch those and replace them with a plain crtc->active check, now
> that we have wm state readout?
>
> Cheers, Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level
  2013-10-15 17:01       ` Paulo Zanoni
@ 2013-10-15 17:46         ` Ville Syrjälä
  0 siblings, 0 replies; 59+ messages in thread
From: Ville Syrjälä @ 2013-10-15 17:46 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On Tue, Oct 15, 2013 at 02:01:39PM -0300, Paulo Zanoni wrote:
> 2013/10/15 Daniel Vetter <daniel@ffwll.ch>:
> > On Fri, Oct 11, 2013 at 02:08:07PM -0300, Paulo Zanoni wrote:
> >> 2013/10/9  <ville.syrjala@linux.intel.com>:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Makes the behaviour of the function more clear.
> >> >
> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>
> >> Thanks :)
> >>
> >> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >
> > With the exception of the tracepoint patch I've merged the entire series,
> > thanks for patches&review.
> >
> > Now all these watermark changes start to freak me out since we seem to
> > fully rely on Paulo's sharp eyes to check them. I really think it's time
> > to blow through a few cycles to independently check all this stuff. Some
> > ideas:
> 
> Before reviewing each of Ville's series I usually dump the current WM
> configurations of eDP-only, eDP+DP, nothing, DP+something with
> intel-reg-dumper and then apply his patches and compare the results.
> So far we're good, the only change I have noticed was already
> discussed here. Also, all this code only runs on Haswell right now
> (even though the goal is to run it on ILK+), so checking regressions
> is not really that hard today. Of course, I don't do full corner-case
> checking.
> 
> I always thought about writing some IGT test to check watermarks, but
> the problem is that we'd have to reimplement the WM code on user space
> if we want to validate the Kernel code, so not really a feasible
> solution.
> 
> >
> > - Enable the fifo underrun stuff and make it really load. Maybe only on
> >   haswell for a start. If this starts to hit issues in the wild we might
> >   need some form of display error state which captures all the
> >   sprites/cursor/planes/crtc/wm/... state. Maybe we could do this as part
> >   of the error state stuff we already have, but with the GT side of things
> >   not enabled (since presumably the GT is really busy and we shouldn't
> >   unduly poke it).
> 
> That was already suggested, but since Ville seems to have the code to
> properly set watermarks on ILK+ already written, I think we should
> just wait for it.

The current code is still unsafe wrt. underruns, even on HSW. So if we
extend underrun reporting at this point, we're sure to get some extra
noise. I'm working on the safe update mechnism, and it's starting to
look fairly decent, although it does make the whole thing a notch more
complex again.

I still had some sprite underrun issues on ILK, but I think I just
discovered the magic sequence to fix that. Now I have the watermarks
for all planes set up dynamically depending on the current need. Eg.
if you disable the cursor even the cursor watermarks get zeroed out.
Also it seems I've accidentally fixed the 5/6 DDB split on IVB.
Previously I had issues with it, but that may have been a simple bug
in my earlier code since I'm not seeing it currently. But I do need to
run some more tests on all affected machines to make sure I haven't
missed something.

I could post the basic ILK/SNB/IVB enabling patches already. I don't think
they can severly regress the current situation, so in that sense they
should be fairly OK to push in. I just figured I'd give you a few days to
catch your breath :)

> >
> > - The hw state readout needs cross-checking. We now rely on the read out
> >   wm state (for the first modeset at least, but there's always fastboot).
> >   Experienc says that without cross checks this will get broken eventually
> >   and lead to fun-to-debug bugs.
> 
> The nice thing of this series is that it adds the infrastructure to do
> the HW state readout + check. I even suggested this already. Maybe
> it's already on Ville's TODO list :)
> 
> >
> > - I'm not sure whether there's a sane way to dump out the wm settings and
> >   check them in userspace. Duplicating the entire calculation is pointless
> >   and we can't really integrate the excel spreadsheet from the hw guys
> >   into igt. And using a set of interesting corner-cases to test all the
> >   basic modes (one pipe, sprite splits, ...) is probably too inflexible.
> >   But if we can get stable watermark settings by e.g. injecting an special
> >   edid somewhere so that we know the exact dotclocks this might be
> >   interesting.
> 
> Watermarks also depend on the machine memory configuration (SSKPD) so
> that's not really easy... The intel-reg-dumper tools dumps all the
> relevant registers and can be easily be used to compare against the
> spreadsheed.
> 
> OTOH, we could "hardcode" the common SSKPD values (at least from QA's
> machines) and the values for some common modes (1024x768, 1920x1080,
> etc) and check the state set by the Kernel against our hardcoded
> state... It's not the best solution, but at least it's something.

We'd need to add a debugfs file to override the latency values since I
changed the code to use the copies stored in dev_priv. But that could be
a generally useful underrun debug mechanism anyway. I suppose the file
contents could just reflect the MLTR/SSKPD register value, or we could
try to come up with something a bit more user friendly.

> 
> >
> > - At least exercising some of the special cases (and then relying on the
> >   state cross-checker and fifo underrun reporting to catch fallout) from
> >   userspace would be good.
> >
> >
> > I'm running a bit low on good stuff here, so better ideas highly welcome.
> > It's not really an area I've wreak much havoc in at all ...
> >
> > One other thing I've noticed is that we still have calls to
> > intel_crtc_active sprinkled throughout the hsw wm functions. Should we be
> > able to ditch those and replace them with a plain crtc->active check, now
> > that we have wm state readout?

It all depends whether someone can still call the watermark code without
clock or fb. I don't think I can fix that part by frobbing the watermark
code.

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2013-10-15 17:46 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-09 16:17 [PATCH 00/16] drm/i915: More HSW watermark prep work v2 ville.syrjala
2013-10-09 16:17 ` [PATCH v2 01/16] drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute ville.syrjala
2013-10-10 21:43   ` Paulo Zanoni
2013-10-11  8:07     ` Ville Syrjälä
2013-10-11 13:51       ` Paulo Zanoni
2013-10-09 16:17 ` [PATCH 02/16] drm/i915: Don't re-compute pipe watermarks except for the affected pipe ville.syrjala
2013-10-10 21:57   ` Paulo Zanoni
2013-10-09 16:17 ` [PATCH 03/16] drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results() ville.syrjala
2013-10-10 22:04   ` Paulo Zanoni
2013-10-09 16:17 ` [PATCH 04/16] drm/i915: Use intel_pipe_wm in hsw_find_best_results ville.syrjala
2013-10-10 22:20   ` Paulo Zanoni
2013-10-09 16:17 ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() ville.syrjala
2013-10-10 22:34   ` Paulo Zanoni
2013-10-11  8:26     ` Ville Syrjälä
2013-10-11 12:26       ` [PATCH 17/16] drm/i915: Check 5/6 DDB split only when sprites are enabled ville.syrjala
2013-10-11 17:21         ` Paulo Zanoni
2013-10-11 13:53       ` [PATCH 05/16] drm/i915: Move some computations out from hsw_compute_wm_parameters() Paulo Zanoni
2013-10-09 16:18 ` [PATCH 06/16] drm/i915: Don't compute 5/6 DDB split w/ zero active pipes ville.syrjala
2013-10-10 22:38   ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 07/16] drm/i915: Refactor wm_lp to level calculation ville.syrjala
2013-10-10 22:42   ` Paulo Zanoni
2013-10-11  8:10     ` Ville Syrjälä
2013-10-09 16:18 ` [PATCH 08/16] drm/i915: Kill fbc_wm_enabled from intel_wm_config ville.syrjala
2013-10-10 22:45   ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 09/16] drm/i915: Store current watermark state in dev_priv->wm ville.syrjala
2013-10-11 14:21   ` Paulo Zanoni
2013-10-15  8:24     ` Daniel Vetter
2013-10-15 16:49       ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 10/16] drm/i915: Improve watermark dirtyness checks ville.syrjala
2013-10-11 15:02   ` Paulo Zanoni
2013-10-11 15:48     ` Ville Syrjälä
2013-10-11 16:12       ` Paulo Zanoni
2013-10-11 16:39         ` [PATCH v2 " ville.syrjala
2013-10-11 17:57           ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 11/16] drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state() ville.syrjala
2013-10-11 16:45   ` Paulo Zanoni
2013-10-11 17:15     ` Ville Syrjälä
2013-10-11 18:15       ` Paulo Zanoni
2013-10-11 19:12         ` Ville Syrjälä
2013-10-11 19:46           ` Paulo Zanoni
2013-10-14 11:21             ` Ville Syrjälä
2013-10-14 11:55     ` [PATCH v2 " ville.syrjala
2013-10-14 13:56       ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 12/16] drm/i915: Remove a somewhat silly debug print from watermark code ville.syrjala
2013-10-11 16:48   ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH v2 13/16] drm/i915: Adjust watermark register masks ville.syrjala
2013-10-11 17:02   ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 14/16] drm/i915: Add watermark tracepoints ville.syrjala
2013-10-11 19:40   ` Paulo Zanoni
2013-10-15  8:43     ` Daniel Vetter
2013-10-15 10:11       ` Ville Syrjälä
2013-10-15 10:59         ` Daniel Vetter
2013-10-09 16:18 ` [PATCH 15/16] drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums ville.syrjala
2013-10-11 17:07   ` Paulo Zanoni
2013-10-09 16:18 ` [PATCH 16/16] drm/i915: Rename ilk_check_wm to ilk_validate_wm_level ville.syrjala
2013-10-11 17:08   ` Paulo Zanoni
2013-10-15  9:16     ` Daniel Vetter
2013-10-15 17:01       ` Paulo Zanoni
2013-10-15 17:46         ` Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.