All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL
@ 2019-12-13 13:02 Stanislav Lisovskiy
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
                   ` (5 more replies)
  0 siblings, 6 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 13:02 UTC (permalink / raw)
  To: intel-gfx

Those patch series, do some initial preparation DBuf manipulating code
cleanups, i.e remove redundant structures/code, switch to mask
based DBuf manupulation, get into use DBuf assignment according to
BSpec rules.

Stanislav Lisovskiy (4):
  drm/i915: Remove skl_ddl_allocation struct
  drm/i915: Move dbuf slice update to proper place
  drm/i915: Manipulate DBuf slices properly
  drm/i915: Correctly map DBUF slices to pipes

 drivers/gpu/drm/i915/display/intel_display.c  |  53 ++--
 .../drm/i915/display/intel_display_power.c    | 100 +++---
 .../drm/i915/display/intel_display_power.h    |   5 +
 .../drm/i915/display/intel_display_types.h    |   3 +
 drivers/gpu/drm/i915/i915_drv.h               |   7 +-
 drivers/gpu/drm/i915/i915_pci.c               |   6 +-
 drivers/gpu/drm/i915/intel_device_info.h      |   1 +
 drivers/gpu/drm/i915/intel_pm.c               | 291 ++++++++++++++----
 drivers/gpu/drm/i915/intel_pm.h               |   6 +-
 9 files changed, 334 insertions(+), 138 deletions(-)

-- 
2.17.1

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

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

* [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
@ 2019-12-13 13:02 ` Stanislav Lisovskiy
  2019-12-13 16:59   ` Matt Roper
  2019-12-18 18:01   ` Ville Syrjälä
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place Stanislav Lisovskiy
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 13:02 UTC (permalink / raw)
  To: intel-gfx

Current consensus that it is redundant as
we already have skl_ddb_values struct out there,
also this struct contains only single member
which makes it unnecessary.

v2: As dirty_pipes soon going to be nuked away
    from skl_ddb_values, evacuating enabled_slices
    to safer in dev_priv.

v3: Changed "enabled_slices" to be "enabled_dbuf_slices_num"
    (Matt Roper)

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  | 16 +++----
 .../drm/i915/display/intel_display_power.c    |  8 ++--
 .../drm/i915/display/intel_display_types.h    |  3 ++
 drivers/gpu/drm/i915/i915_drv.h               |  7 +--
 drivers/gpu/drm/i915/intel_pm.c               | 44 +++++++++----------
 drivers/gpu/drm/i915/intel_pm.h               |  6 +--
 6 files changed, 39 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0f37f1d2026d..62e33bca7014 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -13339,14 +13339,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
 	struct skl_hw_state {
 		struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
 		struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
-		struct skl_ddb_allocation ddb;
 		struct skl_pipe_wm wm;
 	} *hw;
-	struct skl_ddb_allocation *sw_ddb;
 	struct skl_pipe_wm *sw_wm;
 	struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
 	const enum pipe pipe = crtc->pipe;
 	int plane, level, max_level = ilk_wm_max_level(dev_priv);
+	u8 hw_enabled_slices;
 
 	if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active)
 		return;
@@ -13360,14 +13359,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
 
 	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
 
-	skl_ddb_get_hw_state(dev_priv, &hw->ddb);
-	sw_ddb = &dev_priv->wm.skl_hw.ddb;
+	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 11 &&
-	    hw->ddb.enabled_slices != sw_ddb->enabled_slices)
+	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
 		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
-			  sw_ddb->enabled_slices,
-			  hw->ddb.enabled_slices);
+			  dev_priv->enabled_dbuf_slices_num,
+			  hw_enabled_slices);
 
 	/* planes */
 	for_each_universal_plane(dev_priv, pipe, plane) {
@@ -14553,8 +14551,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc *crtc;
 	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
-	u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
-	u8 required_slices = state->wm_results.ddb.enabled_slices;
+	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
+	u8 required_slices = state->enabled_dbuf_slices_num;
 	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
 	u8 dirty_pipes = 0;
 	int i;
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 0b3dd2a3b94d..b8983422a882 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -4264,7 +4264,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 			    u8 req_slices)
 {
-	const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
+	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
 	bool ret;
 
 	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
@@ -4281,7 +4281,7 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
 
 	if (ret)
-		dev_priv->wm.skl_hw.ddb.enabled_slices = req_slices;
+		dev_priv->enabled_dbuf_slices_num = req_slices;
 }
 
 static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
@@ -4300,7 +4300,7 @@ static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
 		 * FIXME: for now pretend that we only have 1 slice, see
 		 * intel_enabled_dbuf_slices_num().
 		 */
-		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
+		dev_priv->enabled_dbuf_slices_num = 1;
 }
 
 static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
@@ -4319,7 +4319,7 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
 		 * FIXME: for now pretend that the first slice is always
 		 * enabled, see intel_enabled_dbuf_slices_num().
 		 */
-		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
+		dev_priv->enabled_dbuf_slices_num = 1;
 }
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 83ea04149b77..70e65c2d525d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -517,6 +517,9 @@ struct intel_atomic_state {
 	/* Gen9+ only */
 	struct skl_ddb_values wm_results;
 
+	/* Number of enabled DBuf slices */
+	u8 enabled_dbuf_slices_num;
+
 	struct i915_sw_fence commit_ready;
 
 	struct llist_node freed;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0781b6326b8c..7a2d9fa5a9a6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -798,13 +798,8 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
 	return false;
 }
 
-struct skl_ddb_allocation {
-	u8 enabled_slices; /* GEN11 has configurable 2 slices */
-};
-
 struct skl_ddb_values {
 	unsigned dirty_pipes;
-	struct skl_ddb_allocation ddb;
 };
 
 struct skl_wm_level {
@@ -1215,6 +1210,8 @@ struct drm_i915_private {
 		bool distrust_bios_wm;
 	} wm;
 
+	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */
+
 	struct dram_info {
 		bool valid;
 		bool is_16gb_dimm;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ccbbdf4a6aab..c2510978ccdf 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3616,16 +3616,16 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
 	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
 }
 
-static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
+u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
 {
-	u8 enabled_slices;
+	u8 enabled_dbuf_slices_num;
 
 	/* Slice 1 will always be enabled */
-	enabled_slices = 1;
+	enabled_dbuf_slices_num = 1;
 
 	/* Gen prior to GEN11 have only one DBuf slice */
 	if (INTEL_GEN(dev_priv) < 11)
-		return enabled_slices;
+		return enabled_dbuf_slices_num;
 
 	/*
 	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
@@ -3633,9 +3633,9 @@ static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
 	 * toggling of the second slice.
 	 */
 	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
-		enabled_slices++;
+		enabled_dbuf_slices_num++;
 
-	return enabled_slices;
+	return enabled_dbuf_slices_num;
 }
 
 /*
@@ -3839,9 +3839,10 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
 static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 			      const struct intel_crtc_state *crtc_state,
 			      const u64 total_data_rate,
-			      const int num_active,
-			      struct skl_ddb_allocation *ddb)
+			      const int num_active)
 {
+	struct drm_atomic_state *state = crtc_state->uapi.state;
+	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	const struct drm_display_mode *adjusted_mode;
 	u64 total_data_bw;
 	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
@@ -3863,9 +3864,9 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 	 * - should validate we stay within the hw bandwidth limits
 	 */
 	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
-		ddb->enabled_slices = 2;
+		intel_state->enabled_dbuf_slices_num = 2;
 	} else {
-		ddb->enabled_slices = 1;
+		intel_state->enabled_dbuf_slices_num = 1;
 		ddb_size /= 2;
 	}
 
@@ -3876,7 +3877,6 @@ static void
 skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 				   const struct intel_crtc_state *crtc_state,
 				   const u64 total_data_rate,
-				   struct skl_ddb_allocation *ddb,
 				   struct skl_ddb_entry *alloc, /* out */
 				   int *num_active /* out */)
 {
@@ -3902,7 +3902,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 		*num_active = hweight8(dev_priv->active_pipes);
 
 	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
-				      *num_active, ddb);
+				      *num_active);
 
 	/*
 	 * If the state doesn't change the active CRTC's or there is no
@@ -4063,10 +4063,9 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 	intel_display_power_put(dev_priv, power_domain, wakeref);
 }
 
-void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
-			  struct skl_ddb_allocation *ddb /* out */)
+void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
 {
-	ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
+	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);
 }
 
 /*
@@ -4243,8 +4242,7 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state,
 }
 
 static int
-skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
-		      struct skl_ddb_allocation *ddb /* out */)
+skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
 {
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct drm_crtc *crtc = crtc_state->uapi.crtc;
@@ -4286,7 +4284,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
 
 
 	skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state, total_data_rate,
-					   ddb, alloc, &num_active);
+					   alloc, &num_active);
 	alloc_size = skl_ddb_entry_size(alloc);
 	if (alloc_size == 0)
 		return 0;
@@ -5200,18 +5198,17 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
 static int
 skl_compute_ddb(struct intel_atomic_state *state)
 {
-	const struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc_state *old_crtc_state;
 	struct intel_crtc_state *new_crtc_state;
 	struct intel_crtc *crtc;
 	int ret, i;
 
-	memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
+	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
-		ret = skl_allocate_pipe_ddb(new_crtc_state, ddb);
+		ret = skl_allocate_pipe_ddb(new_crtc_state);
 		if (ret)
 			return ret;
 
@@ -5683,11 +5680,10 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
 void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
 {
 	struct skl_ddb_values *hw = &dev_priv->wm.skl_hw;
-	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
 	struct intel_crtc *crtc;
 	struct intel_crtc_state *crtc_state;
 
-	skl_ddb_get_hw_state(dev_priv, ddb);
+	skl_ddb_get_hw_state(dev_priv);
 	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		crtc_state = to_intel_crtc_state(crtc->base.state);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
index c06c6a846d9a..a476f6c730e9 100644
--- a/drivers/gpu/drm/i915/intel_pm.h
+++ b/drivers/gpu/drm/i915/intel_pm.h
@@ -17,8 +17,8 @@ struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_plane;
-struct skl_ddb_allocation;
 struct skl_ddb_entry;
+struct skl_ddb_values;
 struct skl_pipe_wm;
 struct skl_wm_level;
 
@@ -33,11 +33,11 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
+u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
 void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 			       struct skl_ddb_entry *ddb_y,
 			       struct skl_ddb_entry *ddb_uv);
-void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
-			  struct skl_ddb_allocation *ddb /* out */);
+void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv);
 void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
 			      struct skl_pipe_wm *out);
 void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
-- 
2.17.1

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

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

* [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
@ 2019-12-13 13:02 ` Stanislav Lisovskiy
  2019-12-13 17:08   ` Matt Roper
  2019-12-18 18:12   ` Ville Syrjälä
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly Stanislav Lisovskiy
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 13:02 UTC (permalink / raw)
  To: intel-gfx

Current DBuf slices update wasn't done in proper
plane, especially its "post" part, which should
disable those only once vblank had passed and
all other changes are committed.

v2: Fix to use dev_priv and intel_atomic_state
    instead of skl_ddb_values
    (to be nuked in Villes patch)

v3: Renamed "enabled_slices" to "enabled_dbuf_slices_num"
    (Matt Roper)

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 38 ++++++++++++++------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 62e33bca7014..0e09d0c23b1d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -14546,13 +14546,33 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
 				       state);
 }
 
+static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
+	u8 required_slices = state->enabled_dbuf_slices_num;
+
+	/* If 2nd DBuf slice required, enable it here */
+	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
+		icl_dbuf_slices_update(dev_priv, required_slices);
+}
+
+static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
+	u8 required_slices = state->enabled_dbuf_slices_num;
+
+	/* If 2nd DBuf slice is no more required disable it */
+	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
+		icl_dbuf_slices_update(dev_priv, required_slices);
+}
+
 static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc *crtc;
 	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
-	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
-	u8 required_slices = state->enabled_dbuf_slices_num;
 	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
 	u8 dirty_pipes = 0;
 	int i;
@@ -14565,10 +14585,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 			dirty_pipes |= BIT(crtc->pipe);
 	}
 
-	/* If 2nd DBuf slice required, enable it here */
-	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
-		icl_dbuf_slices_update(dev_priv, required_slices);
-
 	/*
 	 * Whenever the number of active pipes changes, we need to make sure we
 	 * update the pipes in the right order so that their ddb allocations
@@ -14617,10 +14633,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 				intel_wait_for_vblank(dev_priv, pipe);
 		}
 	}
-
-	/* If 2nd DBuf slice is no more required disable it */
-	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
-		icl_dbuf_slices_update(dev_priv, required_slices);
 }
 
 static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
@@ -14750,6 +14762,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 	if (state->modeset)
 		intel_encoders_update_prepare(state);
 
+	/* Enable all new slices, we might need */
+	icl_dbuf_slice_pre_update(state);
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.commit_modeset_enables(state);
 
@@ -14825,6 +14840,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 	if (state->modeset && intel_can_enable_sagv(state))
 		intel_enable_sagv(dev_priv);
 
+	/* Disable all slices, we don't need */
+	icl_dbuf_slice_post_update(state);
+
 	drm_atomic_helper_commit_hw_done(&state->base);
 
 	if (state->modeset) {
-- 
2.17.1

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

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

* [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place Stanislav Lisovskiy
@ 2019-12-13 13:02 ` Stanislav Lisovskiy
  2019-12-13 19:01   ` Matt Roper
  2019-12-18 18:00   ` Ville Syrjälä
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 13:02 UTC (permalink / raw)
  To: intel-gfx

Start manipulating DBuf slices as a mask,
but not as a total number, as current approach
doesn't give us full control on all combinations
of slices, which we might need(like enabling S2
only can't enabled by setting enabled_slices=1).

Removed wrong code from intel_get_ddb_size as
it doesn't match to BSpec. For now still just
use DBuf slice until proper algorithm is implemented.

Other minor code refactoring to get prepared
for major DBuf assignment changes landed:
- As now enabled slices contain a mask
  we still need some value which should
  reflect how much DBuf slices are supported
  by the platform, now device info contains
  num_supported_dbuf_slices.
- Removed unneeded assertion as we are now
  manipulating slices in a more proper way.

v2: Start using enabled_slices in dev_priv

v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
    as this now sits in dev_priv independently.

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
 .../drm/i915/display/intel_display_power.c    | 100 ++++++++----------
 .../drm/i915/display/intel_display_power.h    |   5 +
 .../drm/i915/display/intel_display_types.h    |   2 +-
 drivers/gpu/drm/i915/i915_drv.h               |   2 +-
 drivers/gpu/drm/i915/i915_pci.c               |   6 +-
 drivers/gpu/drm/i915/intel_device_info.h      |   1 +
 drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
 drivers/gpu/drm/i915/intel_pm.h               |   2 +-
 9 files changed, 84 insertions(+), 106 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0e09d0c23b1d..42a0ea540d4f 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -13359,12 +13359,12 @@ static void verify_wm_state(struct intel_crtc *crtc,
 
 	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
 
-	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
+	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 11 &&
-	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
-		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
-			  dev_priv->enabled_dbuf_slices_num,
+	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
+		DRM_ERROR("mismatch in DBUF Slices (expected %x, got %x)\n",
+			  dev_priv->enabled_dbuf_slices_mask,
 			  hw_enabled_slices);
 
 	/* planes */
@@ -14549,22 +14549,23 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
 static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
-	u8 required_slices = state->enabled_dbuf_slices_num;
+	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
+	u8 required_slices = state->enabled_dbuf_slices_mask;
+	u8 slices_union = hw_enabled_slices | required_slices;
 
 	/* If 2nd DBuf slice required, enable it here */
-	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
-		icl_dbuf_slices_update(dev_priv, required_slices);
+	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)
+		icl_dbuf_slices_update(dev_priv, slices_union);
 }
 
 static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
-	u8 required_slices = state->enabled_dbuf_slices_num;
+	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
+	u8 required_slices = state->enabled_dbuf_slices_mask;
 
 	/* If 2nd DBuf slice is no more required disable it */
-	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
+	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)
 		icl_dbuf_slices_update(dev_priv, required_slices);
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index b8983422a882..ba384a5315f8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -1031,15 +1031,6 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
 		(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
 }
 
-static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
-{
-	u32 tmp = I915_READ(DBUF_CTL);
-
-	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
-	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
-	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
-}
-
 static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
 {
 	struct intel_cdclk_state cdclk_state = {};
@@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
 	/* Can't read out voltage_level so can't use intel_cdclk_changed() */
 	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state));
 
-	gen9_assert_dbuf_enabled(dev_priv);
-
 	if (IS_GEN9_LP(dev_priv))
 		bxt_verify_ddi_phy_power_wells(dev_priv);
 
@@ -4254,72 +4243,71 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
 	intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
 }
 
-static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
+int intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
 {
-	if (INTEL_GEN(dev_priv) < 11)
-		return 1;
-	return 2;
+	return INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
+}
+
+void icl_program_dbuf_slices(struct drm_i915_private *dev_priv)
+{
+	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
+
+	icl_dbuf_slices_update(dev_priv, hw_enabled_slices);
 }
 
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 			    u8 req_slices)
 {
-	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
-	bool ret;
+	int i;
+	int max_slices = intel_dbuf_max_slices(dev_priv);
 
-	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
+	if (hweight8(req_slices) > intel_dbuf_max_slices(dev_priv)) {
 		DRM_ERROR("Invalid number of dbuf slices requested\n");
 		return;
 	}
 
-	if (req_slices == hw_enabled_slices || req_slices == 0)
-		return;
+	DRM_DEBUG_KMS("Updating dbuf slices to %x\n", req_slices);
 
-	if (req_slices > hw_enabled_slices)
-		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
-	else
-		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
+	for (i = 0; i < max_slices; i++) {
+		int slice_bit = BIT(i);
+		bool slice_set = (slice_bit & req_slices) != 0;
+
+		switch (slice_bit) {
+		case DBUF_S1_BIT:
+			intel_dbuf_slice_set(dev_priv,
+					     DBUF_CTL_S1,
+					     slice_set);
+			break;
+		case DBUF_S2_BIT:
+			intel_dbuf_slice_set(dev_priv,
+					     DBUF_CTL_S2,
+					     slice_set);
+			break;
+		default:
+			MISSING_CASE(slice_bit);
+		}
+	}
 
-	if (ret)
-		dev_priv->enabled_dbuf_slices_num = req_slices;
+	dev_priv->enabled_dbuf_slices_mask = req_slices;
 }
 
 static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST);
-	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST);
-	POSTING_READ(DBUF_CTL_S2);
-
-	udelay(10);
-
-	if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
-	    !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
-		DRM_ERROR("DBuf power enable timeout\n");
-	else
-		/*
-		 * FIXME: for now pretend that we only have 1 slice, see
-		 * intel_enabled_dbuf_slices_num().
-		 */
-		dev_priv->enabled_dbuf_slices_num = 1;
+	/*
+	 * Just power up 1 slice, we will
+	 * figure out later which slices we have and what we need.
+	 */
+	dev_priv->enabled_dbuf_slices_mask = DBUF_S1_BIT;
+	icl_program_dbuf_slices(dev_priv);
 }
 
 static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST);
-	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST);
-	POSTING_READ(DBUF_CTL_S2);
-
-	udelay(10);
-
-	if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
-	    (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
-		DRM_ERROR("DBuf power disable timeout!\n");
-	else
-		/*
-		 * FIXME: for now pretend that the first slice is always
-		 * enabled, see intel_enabled_dbuf_slices_num().
-		 */
-		dev_priv->enabled_dbuf_slices_num = 1;
+	/*
+	 * Disable all slices
+	 */
+	dev_priv->enabled_dbuf_slices_mask = 0;
+	icl_program_dbuf_slices(dev_priv);
 }
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index 1da04f3e0fb3..0d9f87607eac 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -311,8 +311,13 @@ intel_display_power_put_async(struct drm_i915_private *i915,
 	for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
 	     intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
 
+#define DBUF_S1_BIT			BIT(0)
+#define DBUF_S2_BIT			BIT(1)
+
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 			    u8 req_slices);
+void icl_program_dbuf_slices(struct drm_i915_private *dev_priv);
+int intel_dbuf_max_slices(struct drm_i915_private *dev_priv);
 
 void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 			     bool override, unsigned int mask);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 70e65c2d525d..ba2e41a03051 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -518,7 +518,7 @@ struct intel_atomic_state {
 	struct skl_ddb_values wm_results;
 
 	/* Number of enabled DBuf slices */
-	u8 enabled_dbuf_slices_num;
+	u8 enabled_dbuf_slices_mask;
 
 	struct i915_sw_fence commit_ready;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7a2d9fa5a9a6..ec4b9e3cef79 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1210,7 +1210,7 @@ struct drm_i915_private {
 		bool distrust_bios_wm;
 	} wm;
 
-	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */
+	u8 enabled_dbuf_slices_mask; /* GEN11 has configurable 2 slices */
 
 	struct dram_info {
 		bool valid;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 877560b1031e..2068aac5ab6a 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -614,7 +614,8 @@ static const struct intel_device_info intel_cherryview_info = {
 	.has_gt_uc = 1, \
 	.display.has_hdcp = 1, \
 	.display.has_ipc = 1, \
-	.ddb_size = 896
+	.ddb_size = 896, \
+	.num_supported_dbuf_slices = 1
 
 #define SKL_PLATFORM \
 	GEN9_FEATURES, \
@@ -649,6 +650,7 @@ static const struct intel_device_info intel_skylake_gt4_info = {
 #define GEN9_LP_FEATURES \
 	GEN(9), \
 	.is_lp = 1, \
+	.num_supported_dbuf_slices = 1, \
 	.display.has_hotplug = 1, \
 	.engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \
 	.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
@@ -737,6 +739,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info = {
 	GEN9_FEATURES, \
 	GEN(10), \
 	.ddb_size = 1024, \
+	.num_supported_dbuf_slices = 1, \
 	.display.has_dsc = 1, \
 	.has_coherent_ggtt = false, \
 	GLK_COLORS
@@ -773,6 +776,7 @@ static const struct intel_device_info intel_cannonlake_info = {
 	}, \
 	GEN(11), \
 	.ddb_size = 2048, \
+	.num_supported_dbuf_slices = 2, \
 	.has_logical_ring_elsq = 1, \
 	.color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
 
diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
index 2725cb7fc169..7d4d122d2182 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -180,6 +180,7 @@ struct intel_device_info {
 	} display;
 
 	u16 ddb_size; /* in blocks */
+	u8 num_supported_dbuf_slices; /* number of DBuf slices */
 
 	/* Register offsets for the various display pipes and transcoders */
 	int pipe_offsets[I915_MAX_TRANSCODERS];
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c2510978ccdf..111bcafd6e4c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3616,26 +3616,22 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
 	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
 }
 
-u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
+u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv)
 {
-	u8 enabled_dbuf_slices_num;
-
-	/* Slice 1 will always be enabled */
-	enabled_dbuf_slices_num = 1;
+	u8 enabled_slices_mask = 0;
 
 	/* Gen prior to GEN11 have only one DBuf slice */
 	if (INTEL_GEN(dev_priv) < 11)
-		return enabled_dbuf_slices_num;
+		return DBUF_S1_BIT;
 
-	/*
-	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
-	 * only that 1 slice enabled until we have a proper way for on-demand
-	 * toggling of the second slice.
-	 */
-	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
-		enabled_dbuf_slices_num++;
+	/* Check if second DBuf slice is enabled */
+	if (I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE)
+		enabled_slices_mask |= DBUF_S1_BIT;
 
-	return enabled_dbuf_slices_num;
+	if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
+		enabled_slices_mask |= DBUF_S2_BIT;
+
+	return enabled_slices_mask;
 }
 
 /*
@@ -3843,8 +3839,6 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 {
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	const struct drm_display_mode *adjusted_mode;
-	u64 total_data_bw;
 	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
 
 	WARN_ON(ddb_size == 0);
@@ -3852,23 +3846,8 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 	if (INTEL_GEN(dev_priv) < 11)
 		return ddb_size - 4; /* 4 blocks for bypass path allocation */
 
-	adjusted_mode = &crtc_state->hw.adjusted_mode;
-	total_data_bw = total_data_rate * drm_mode_vrefresh(adjusted_mode);
-
-	/*
-	 * 12GB/s is maximum BW supported by single DBuf slice.
-	 *
-	 * FIXME dbuf slice code is broken:
-	 * - must wait for planes to stop using the slice before powering it off
-	 * - plane straddling both slices is illegal in multi-pipe scenarios
-	 * - should validate we stay within the hw bandwidth limits
-	 */
-	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
-		intel_state->enabled_dbuf_slices_num = 2;
-	} else {
-		intel_state->enabled_dbuf_slices_num = 1;
-		ddb_size /= 2;
-	}
+	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
+	ddb_size /= 2;
 
 	return ddb_size;
 }
@@ -4065,7 +4044,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
 {
-	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);
+	dev_priv->enabled_dbuf_slices_mask = intel_enabled_dbuf_slices_mask(dev_priv);
 }
 
 /*
@@ -5204,7 +5183,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
 	struct intel_crtc *crtc;
 	int ret, i;
 
-	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
+	state->enabled_dbuf_slices_mask = dev_priv->enabled_dbuf_slices_mask;
 
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
index a476f6c730e9..7a7494d1224f 100644
--- a/drivers/gpu/drm/i915/intel_pm.h
+++ b/drivers/gpu/drm/i915/intel_pm.h
@@ -33,7 +33,7 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
-u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
+u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv);
 void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 			       struct skl_ddb_entry *ddb_y,
 			       struct skl_ddb_entry *ddb_uv);
-- 
2.17.1

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

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

* [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
                   ` (2 preceding siblings ...)
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly Stanislav Lisovskiy
@ 2019-12-13 13:02 ` Stanislav Lisovskiy
  2019-12-14  0:52   ` Matt Roper
  2019-12-18 18:05   ` Ville Syrjälä
  2019-12-13 13:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success for Enable second DBuf slice for ICL and TGL (rev8) Patchwork
  2019-12-14  7:04 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
  5 siblings, 2 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 13:02 UTC (permalink / raw)
  To: intel-gfx

Added proper DBuf slice mapping to correspondent
pipes, depending on pipe configuration as stated
in BSpec.

v2:
    - Remove unneeded braces
    - Stop using macro for DBuf assignments as
      it seems to reduce readability.

v3: Start using enabled slices mask in dev_priv

v4: Renamed "enabled_slices" used in dev_priv
    to "enabled_dbuf_slices_mask"(Matt Roper)

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 226 ++++++++++++++++++++++++++++++--
 1 file changed, 216 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 111bcafd6e4c..a13052b2c2ef 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
 	return true;
 }
 
+/*
+ * Calculate initial DBuf slice offset, based on slice size
+ * and mask(i.e if slice size is 1024 and second slice is enabled
+ * offset would be 1024)
+ */
+static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
+					   u32 slice_size, u32 ddb_size)
+{
+	u32 offset = 0;
+
+	if (!dbuf_slice_mask)
+		return 0;
+
+	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
+
+	WARN_ON(offset >= ddb_size);
+	return offset;
+}
+
 static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 			      const struct intel_crtc_state *crtc_state,
 			      const u64 total_data_rate,
 			      const int num_active)
 {
-	struct drm_atomic_state *state = crtc_state->uapi.state;
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
 
 	WARN_ON(ddb_size == 0);
@@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 	if (INTEL_GEN(dev_priv) < 11)
 		return ddb_size - 4; /* 4 blocks for bypass path allocation */
 
-	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
-	ddb_size /= 2;
-
 	return ddb_size;
 }
 
+u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
+			      int pipe, u32 active_pipes,
+			      const struct intel_crtc_state *crtc_state);
+
 static void
 skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 				   const struct intel_crtc_state *crtc_state,
@@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
 	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
 	u16 ddb_size;
+	u32 ddb_range_size;
 	u32 i;
+	u32 dbuf_slice_mask;
+	u32 active_pipes;
+	u32 offset;
+	u32 slice_size;
+	u32 total_slice_mask;
+	u32 start, end;
 
 	if (WARN_ON(!state) || !crtc_state->hw.active) {
 		alloc->start = 0;
@@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	if (intel_state->active_pipe_changes)
+	if (intel_state->active_pipe_changes) {
 		*num_active = hweight8(intel_state->active_pipes);
-	else
+		active_pipes = intel_state->active_pipes;
+	} else {
 		*num_active = hweight8(dev_priv->active_pipes);
+		active_pipes = dev_priv->active_pipes;
+	}
 
 	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
 				      *num_active);
 
+	slice_size = ddb_size / INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
+
 	/*
 	 * If the state doesn't change the active CRTC's or there is no
 	 * modeset request, then there's no need to recalculate;
@@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 		return;
 	}
 
+	/*
+	 * Get allowed DBuf slices for correspondent pipe and platform.
+	 */
+	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
+						    active_pipes, crtc_state);
+
+	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
+		      dbuf_slice_mask,
+		      for_pipe, active_pipes);
+
+	/*
+	 * Figure out at which DBuf slice we start, i.e if we start at Dbuf S2
+	 * and slice size is 1024, the offset would be 1024
+	 */
+	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
+						 slice_size, ddb_size);
+
+	/*
+	 * Figure out total size of allowed DBuf slices, which is basically
+	 * a number of allowed slices for that pipe multiplied by slice size.
+	 * Inside of this
+	 * range ddb entries are still allocated in proportion to display width.
+	 */
+	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
+
 	/*
 	 * Watermark/ddb requirement highly depends upon width of the
 	 * framebuffer, So instead of allocating DDB equally among pipes
 	 * distribute DDB based on resolution/width of the display.
 	 */
+	total_slice_mask = dbuf_slice_mask;
 	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
 		const struct drm_display_mode *adjusted_mode =
 			&crtc_state->hw.adjusted_mode;
 		enum pipe pipe = crtc->pipe;
 		int hdisplay, vdisplay;
+		u32 pipe_dbuf_slice_mask =
+					i915_possible_dbuf_slices(dev_priv,
+								  pipe,
+								  active_pipes,
+								  crtc_state);
+
+		if (!crtc_state->hw.active)
+			continue;
+
+		/*
+		 * According to BSpec pipe can share one dbuf slice with another
+		 * pipes or pipe can use multiple dbufs, in both cases we
+		 * account for other pipes only if they have exactly same mask.
+		 * However we need to account how many slices we should enable
+		 * in total.
+		 */
+		total_slice_mask |= pipe_dbuf_slice_mask;
 
-		if (!crtc_state->hw.enable)
+		/*
+		 * Do not account pipes using other slice sets
+		 * luckily as of current BSpec slice sets do not partially
+		 * intersect(pipes share either same one slice or same slice set
+		 * i.e no partial intersection), so it is enough to check for
+		 * equality for now.
+		 */
+		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
 			continue;
 
 		drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
@@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 			pipe_width = hdisplay;
 	}
 
-	alloc->start = ddb_size * width_before_pipe / total_width;
-	alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width;
+	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
+
+	start = ddb_range_size * width_before_pipe / total_width;
+	end = ddb_range_size * (width_before_pipe + pipe_width) / total_width;
+
+	alloc->start = offset + start;
+	alloc->end = offset + end;
+
+	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
+		      alloc->start, alloc->end);
+	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
+		      intel_state->enabled_dbuf_slices_mask,
+		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
 }
 
 static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
@@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state,
 	return mul_fixed16(downscale_w, downscale_h);
 }
 
+struct dbuf_slice_conf_entry {
+	u32 active_pipes;
+	u32 dbuf_mask[I915_MAX_PIPES];
+};
+
+/*
+ * Table taken from Bspec 12716
+ * Pipes do have some preferred DBuf slice affinity,
+ * plus there are some hardcoded requirements on how
+ * those should be distributed for multipipe scenarios.
+ * For more DBuf slices algorithm can get even more messy
+ * and less readable, so decided to use a table almost
+ * as is from BSpec itself - that way it is at least easier
+ * to compare, change and check.
+ */
+static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
+	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
+	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
+	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
+};
+
+/*
+ * Table taken from Bspec 49255
+ * Pipes do have some preferred DBuf slice affinity,
+ * plus there are some hardcoded requirements on how
+ * those should be distributed for multipipe scenarios.
+ * For more DBuf slices algorithm can get even more messy
+ * and less readable, so decided to use a table almost
+ * as is from BSpec itself - that way it is at least easier
+ * to compare, change and check.
+ */
+static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
+	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
+	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
+	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
+};
+
+static u32 i915_find_pipe_conf(int pipe,
+			       u32 active_pipes,
+			       const struct dbuf_slice_conf_entry *dbuf_slices,
+			       int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (dbuf_slices[i].active_pipes == active_pipes)
+			return dbuf_slices[i].dbuf_mask[pipe];
+	}
+	return 0;
+}
+
+/*
+ * This function finds an entry with same enabled pipe configuration and
+ * returns correspondent DBuf slice mask as stated in BSpec for particular
+ * platform.
+ */
+static u32 icl_possible_dbuf_slices(int pipe,
+				    u32 active_pipes,
+				    const struct intel_crtc_state *crtc_state)
+{
+	return i915_find_pipe_conf(pipe, active_pipes,
+				   icl_allowed_dbufs,
+				   ARRAY_SIZE(icl_allowed_dbufs));
+}
+
+static u32 tgl_possible_dbuf_slices(int pipe,
+				    u32 active_pipes,
+				    const struct intel_crtc_state *crtc_state)
+{
+	return i915_find_pipe_conf(pipe, active_pipes,
+				   tgl_allowed_dbufs,
+				   ARRAY_SIZE(tgl_allowed_dbufs));
+}
+
+u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
+			      int pipe, u32 active_pipes,
+			      const struct intel_crtc_state *crtc_state)
+{
+	if (IS_GEN(dev_priv, 11))
+		return icl_possible_dbuf_slices(pipe,
+						active_pipes,
+						crtc_state);
+	else if (IS_GEN(dev_priv, 12))
+		return tgl_possible_dbuf_slices(pipe,
+						active_pipes,
+						crtc_state);
+	/*
+	 * For anything else just return one slice yet.
+	 * Should be extended for other platforms.
+	 */
+	return DBUF_S1_BIT;
+}
+
 static u64
 skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
 			     const struct intel_plane_state *plane_state,
-- 
2.17.1

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

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

* [Intel-gfx] ✓ Fi.CI.BAT: success for Enable second DBuf slice for ICL and TGL (rev8)
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
                   ` (3 preceding siblings ...)
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy
@ 2019-12-13 13:52 ` Patchwork
  2019-12-14  7:04 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
  5 siblings, 0 replies; 23+ messages in thread
From: Patchwork @ 2019-12-13 13:52 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

== Series Details ==

Series: Enable second DBuf slice for ICL and TGL (rev8)
URL   : https://patchwork.freedesktop.org/series/70059/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7558 -> Patchwork_15742
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/index.html

Known issues
------------

  Here are the changes found in Patchwork_15742 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_pm_rpm@module-reload:
    - fi-skl-6770hq:      [PASS][1] -> [FAIL][2] ([i915#178])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-skl-6770hq/igt@i915_pm_rpm@module-reload.html

  * igt@i915_selftest@live_gem_contexts:
    - fi-byt-j1900:       [PASS][3] -> [DMESG-FAIL][4] ([i915#722])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-byt-j1900/igt@i915_selftest@live_gem_contexts.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-byt-j1900/igt@i915_selftest@live_gem_contexts.html

  
#### Possible fixes ####

  * igt@gem_ctx_create@basic-files:
    - {fi-tgl-guc}:       [INCOMPLETE][5] ([fdo#111735]) -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-tgl-guc/igt@gem_ctx_create@basic-files.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-tgl-guc/igt@gem_ctx_create@basic-files.html

  * igt@i915_selftest@live_gem_contexts:
    - fi-cfl-guc:         [INCOMPLETE][7] ([fdo#106070] / [i915#424]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-cfl-guc/igt@i915_selftest@live_gem_contexts.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-cfl-guc/igt@i915_selftest@live_gem_contexts.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       [FAIL][9] ([fdo#111096] / [i915#323]) -> [PASS][10]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html

  
#### Warnings ####

  * igt@i915_selftest@live_blt:
    - fi-hsw-4770r:       [DMESG-FAIL][11] -> [DMESG-FAIL][12] ([i915#725])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-hsw-4770r/igt@i915_selftest@live_blt.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-hsw-4770r/igt@i915_selftest@live_blt.html

  * igt@i915_selftest@live_gem_contexts:
    - fi-byt-n2820:       [DMESG-FAIL][13] ([i915#722]) -> [INCOMPLETE][14] ([i915#45])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-byt-n2820/igt@i915_selftest@live_gem_contexts.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-byt-n2820/igt@i915_selftest@live_gem_contexts.html

  * igt@kms_cursor_legacy@basic-flip-after-cursor-legacy:
    - fi-kbl-x1275:       [DMESG-WARN][15] ([i915#62] / [i915#92] / [i915#95]) -> [DMESG-WARN][16] ([i915#62] / [i915#92]) +5 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-modeset:
    - fi-kbl-x1275:       [DMESG-WARN][17] ([i915#62] / [i915#92]) -> [DMESG-WARN][18] ([i915#62] / [i915#92] / [i915#95]) +8 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#106070]: https://bugs.freedesktop.org/show_bug.cgi?id=106070
  [fdo#111096]: https://bugs.freedesktop.org/show_bug.cgi?id=111096
  [fdo#111735]: https://bugs.freedesktop.org/show_bug.cgi?id=111735
  [fdo#111736]: https://bugs.freedesktop.org/show_bug.cgi?id=111736
  [i915#178]: https://gitlab.freedesktop.org/drm/intel/issues/178
  [i915#323]: https://gitlab.freedesktop.org/drm/intel/issues/323
  [i915#424]: https://gitlab.freedesktop.org/drm/intel/issues/424
  [i915#45]: https://gitlab.freedesktop.org/drm/intel/issues/45
  [i915#460]: https://gitlab.freedesktop.org/drm/intel/issues/460
  [i915#62]: https://gitlab.freedesktop.org/drm/intel/issues/62
  [i915#722]: https://gitlab.freedesktop.org/drm/intel/issues/722
  [i915#725]: https://gitlab.freedesktop.org/drm/intel/issues/725
  [i915#92]: https://gitlab.freedesktop.org/drm/intel/issues/92
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95


Participating hosts (54 -> 46)
------------------------------

  Additional (1): fi-tgl-y 
  Missing    (9): fi-icl-1065g7 fi-ilk-m540 fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus fi-snb-2600 


Build changes
-------------

  * CI: CI-20190529 -> None
  * Linux: CI_DRM_7558 -> Patchwork_15742

  CI-20190529: 20190529
  CI_DRM_7558: 1adb846ba2ead1c3f7bb7ed753e11f7d9ee28688 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5349: 048f58513d8b8ec6bb307a939f0ac959bc0f0e10 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_15742: 7d264ac2e1f1726dacaceefc6d41d52ee2ef8a08 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

7d264ac2e1f1 drm/i915: Correctly map DBUF slices to pipes
01eaf9dd8822 drm/i915: Manipulate DBuf slices properly
a119afd20cb2 drm/i915: Move dbuf slice update to proper place
fa13416ebff5 drm/i915: Remove skl_ddl_allocation struct

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/index.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
@ 2019-12-13 16:59   ` Matt Roper
  2019-12-18 18:01   ` Ville Syrjälä
  1 sibling, 0 replies; 23+ messages in thread
From: Matt Roper @ 2019-12-13 16:59 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:25PM +0200, Stanislav Lisovskiy wrote:
> Current consensus that it is redundant as
> we already have skl_ddb_values struct out there,
> also this struct contains only single member
> which makes it unnecessary.
> 
> v2: As dirty_pipes soon going to be nuked away
>     from skl_ddb_values, evacuating enabled_slices
>     to safer in dev_priv.
> 
> v3: Changed "enabled_slices" to be "enabled_dbuf_slices_num"
>     (Matt Roper)
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  | 16 +++----
>  .../drm/i915/display/intel_display_power.c    |  8 ++--
>  .../drm/i915/display/intel_display_types.h    |  3 ++
>  drivers/gpu/drm/i915/i915_drv.h               |  7 +--
>  drivers/gpu/drm/i915/intel_pm.c               | 44 +++++++++----------
>  drivers/gpu/drm/i915/intel_pm.h               |  6 +--
>  6 files changed, 39 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0f37f1d2026d..62e33bca7014 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -13339,14 +13339,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  	struct skl_hw_state {
>  		struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
>  		struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
> -		struct skl_ddb_allocation ddb;
>  		struct skl_pipe_wm wm;
>  	} *hw;
> -	struct skl_ddb_allocation *sw_ddb;
>  	struct skl_pipe_wm *sw_wm;
>  	struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
>  	const enum pipe pipe = crtc->pipe;
>  	int plane, level, max_level = ilk_wm_max_level(dev_priv);
> +	u8 hw_enabled_slices;
>  
>  	if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active)
>  		return;
> @@ -13360,14 +13359,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  
>  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
>  
> -	skl_ddb_get_hw_state(dev_priv, &hw->ddb);
> -	sw_ddb = &dev_priv->wm.skl_hw.ddb;
> +	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 11 &&
> -	    hw->ddb.enabled_slices != sw_ddb->enabled_slices)
> +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
>  		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
> -			  sw_ddb->enabled_slices,
> -			  hw->ddb.enabled_slices);
> +			  dev_priv->enabled_dbuf_slices_num,
> +			  hw_enabled_slices);
>  
>  	/* planes */
>  	for_each_universal_plane(dev_priv, pipe, plane) {
> @@ -14553,8 +14551,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
> -	u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
> -	u8 required_slices = state->wm_results.ddb.enabled_slices;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
>  	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
>  	u8 dirty_pipes = 0;
>  	int i;
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index 0b3dd2a3b94d..b8983422a882 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -4264,7 +4264,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices)
>  {
> -	const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
> +	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
>  	bool ret;
>  
>  	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> @@ -4281,7 +4281,7 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
>  
>  	if (ret)
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = req_slices;
> +		dev_priv->enabled_dbuf_slices_num = req_slices;
>  }
>  
>  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
> @@ -4300,7 +4300,7 @@ static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
>  		 * FIXME: for now pretend that we only have 1 slice, see
>  		 * intel_enabled_dbuf_slices_num().
>  		 */
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
> +		dev_priv->enabled_dbuf_slices_num = 1;
>  }
>  
>  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
> @@ -4319,7 +4319,7 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
>  		 * FIXME: for now pretend that the first slice is always
>  		 * enabled, see intel_enabled_dbuf_slices_num().
>  		 */
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
> +		dev_priv->enabled_dbuf_slices_num = 1;
>  }
>  
>  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 83ea04149b77..70e65c2d525d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -517,6 +517,9 @@ struct intel_atomic_state {
>  	/* Gen9+ only */
>  	struct skl_ddb_values wm_results;
>  
> +	/* Number of enabled DBuf slices */
> +	u8 enabled_dbuf_slices_num;
> +
>  	struct i915_sw_fence commit_ready;
>  
>  	struct llist_node freed;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 0781b6326b8c..7a2d9fa5a9a6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -798,13 +798,8 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
>  	return false;
>  }
>  
> -struct skl_ddb_allocation {
> -	u8 enabled_slices; /* GEN11 has configurable 2 slices */
> -};
> -
>  struct skl_ddb_values {
>  	unsigned dirty_pipes;
> -	struct skl_ddb_allocation ddb;
>  };
>  
>  struct skl_wm_level {
> @@ -1215,6 +1210,8 @@ struct drm_i915_private {
>  		bool distrust_bios_wm;
>  	} wm;
>  
> +	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */
> +
>  	struct dram_info {
>  		bool valid;
>  		bool is_16gb_dimm;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ccbbdf4a6aab..c2510978ccdf 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3616,16 +3616,16 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
>  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
>  }
>  
> -static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
> +u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
>  {
> -	u8 enabled_slices;
> +	u8 enabled_dbuf_slices_num;
>  
>  	/* Slice 1 will always be enabled */
> -	enabled_slices = 1;
> +	enabled_dbuf_slices_num = 1;
>  
>  	/* Gen prior to GEN11 have only one DBuf slice */
>  	if (INTEL_GEN(dev_priv) < 11)
> -		return enabled_slices;
> +		return enabled_dbuf_slices_num;
>  
>  	/*
>  	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
> @@ -3633,9 +3633,9 @@ static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
>  	 * toggling of the second slice.
>  	 */
>  	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> -		enabled_slices++;
> +		enabled_dbuf_slices_num++;
>  
> -	return enabled_slices;
> +	return enabled_dbuf_slices_num;
>  }
>  
>  /*
> @@ -3839,9 +3839,10 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
>  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  			      const struct intel_crtc_state *crtc_state,
>  			      const u64 total_data_rate,
> -			      const int num_active,
> -			      struct skl_ddb_allocation *ddb)
> +			      const int num_active)
>  {
> +	struct drm_atomic_state *state = crtc_state->uapi.state;
> +	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	const struct drm_display_mode *adjusted_mode;
>  	u64 total_data_bw;
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> @@ -3863,9 +3864,9 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	 * - should validate we stay within the hw bandwidth limits
>  	 */
>  	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> -		ddb->enabled_slices = 2;
> +		intel_state->enabled_dbuf_slices_num = 2;
>  	} else {
> -		ddb->enabled_slices = 1;
> +		intel_state->enabled_dbuf_slices_num = 1;
>  		ddb_size /= 2;
>  	}
>  
> @@ -3876,7 +3877,6 @@ static void
>  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  				   const struct intel_crtc_state *crtc_state,
>  				   const u64 total_data_rate,
> -				   struct skl_ddb_allocation *ddb,
>  				   struct skl_ddb_entry *alloc, /* out */
>  				   int *num_active /* out */)
>  {
> @@ -3902,7 +3902,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		*num_active = hweight8(dev_priv->active_pipes);
>  
>  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
> -				      *num_active, ddb);
> +				      *num_active);
>  
>  	/*
>  	 * If the state doesn't change the active CRTC's or there is no
> @@ -4063,10 +4063,9 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  	intel_display_power_put(dev_priv, power_domain, wakeref);
>  }
>  
> -void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> -			  struct skl_ddb_allocation *ddb /* out */)
> +void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
>  {
> -	ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> +	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);

I think you may want to wrap this line to keep it under 80 chars.

>  }
>  
>  /*
> @@ -4243,8 +4242,7 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state,
>  }
>  
>  static int
> -skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
> -		      struct skl_ddb_allocation *ddb /* out */)
> +skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
>  {
>  	struct drm_atomic_state *state = crtc_state->uapi.state;
>  	struct drm_crtc *crtc = crtc_state->uapi.crtc;
> @@ -4286,7 +4284,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
>  
>  
>  	skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state, total_data_rate,
> -					   ddb, alloc, &num_active);
> +					   alloc, &num_active);
>  	alloc_size = skl_ddb_entry_size(alloc);
>  	if (alloc_size == 0)
>  		return 0;
> @@ -5200,18 +5198,17 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
>  static int
>  skl_compute_ddb(struct intel_atomic_state *state)
>  {
> -	const struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc_state *old_crtc_state;
>  	struct intel_crtc_state *new_crtc_state;
>  	struct intel_crtc *crtc;
>  	int ret, i;
>  
> -	memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
> +	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
>  
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
> -		ret = skl_allocate_pipe_ddb(new_crtc_state, ddb);
> +		ret = skl_allocate_pipe_ddb(new_crtc_state);
>  		if (ret)
>  			return ret;
>  
> @@ -5683,11 +5680,10 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
>  {
>  	struct skl_ddb_values *hw = &dev_priv->wm.skl_hw;
> -	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *crtc_state;
>  
> -	skl_ddb_get_hw_state(dev_priv, ddb);
> +	skl_ddb_get_hw_state(dev_priv);
>  	for_each_intel_crtc(&dev_priv->drm, crtc) {
>  		crtc_state = to_intel_crtc_state(crtc->base.state);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
> index c06c6a846d9a..a476f6c730e9 100644
> --- a/drivers/gpu/drm/i915/intel_pm.h
> +++ b/drivers/gpu/drm/i915/intel_pm.h
> @@ -17,8 +17,8 @@ struct intel_atomic_state;
>  struct intel_crtc;
>  struct intel_crtc_state;
>  struct intel_plane;
> -struct skl_ddb_allocation;
>  struct skl_ddb_entry;
> +struct skl_ddb_values;

Do we actually need to add this here?  It doesn't seem like this patch
has started using this type anywhere that it wasn't already available.

Aside from that and the linewrap mentioned farther up,

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>



>  struct skl_pipe_wm;
>  struct skl_wm_level;
>  
> @@ -33,11 +33,11 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> +u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
>  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  			       struct skl_ddb_entry *ddb_y,
>  			       struct skl_ddb_entry *ddb_uv);
> -void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> -			  struct skl_ddb_allocation *ddb /* out */);
> +void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
>  			      struct skl_pipe_wm *out);
>  void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
> -- 
> 2.17.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place Stanislav Lisovskiy
@ 2019-12-13 17:08   ` Matt Roper
  2019-12-18 18:12   ` Ville Syrjälä
  1 sibling, 0 replies; 23+ messages in thread
From: Matt Roper @ 2019-12-13 17:08 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:26PM +0200, Stanislav Lisovskiy wrote:
> Current DBuf slices update wasn't done in proper
> plane, especially its "post" part, which should

Oh, I forgot to point it out on my previous review, but I think you
meant "place" here rather than "plane?"  I was very confused about what
we were supposedly doing on the wrong display plane until I figured out
it was a typo.  :-)


Matt

> disable those only once vblank had passed and
> all other changes are committed.
> 
> v2: Fix to use dev_priv and intel_atomic_state
>     instead of skl_ddb_values
>     (to be nuked in Villes patch)
> 
> v3: Renamed "enabled_slices" to "enabled_dbuf_slices_num"
>     (Matt Roper)
> 
> Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 38 ++++++++++++++------
>  1 file changed, 28 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 62e33bca7014..0e09d0c23b1d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -14546,13 +14546,33 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
>  				       state);
>  }
>  
> +static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
> +
> +	/* If 2nd DBuf slice required, enable it here */
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> +		icl_dbuf_slices_update(dev_priv, required_slices);
> +}
> +
> +static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
> +
> +	/* If 2nd DBuf slice is no more required disable it */
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> +		icl_dbuf_slices_update(dev_priv, required_slices);
> +}
> +
>  static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
>  	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
>  	u8 dirty_pipes = 0;
>  	int i;
> @@ -14565,10 +14585,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  			dirty_pipes |= BIT(crtc->pipe);
>  	}
>  
> -	/* If 2nd DBuf slice required, enable it here */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
> -
>  	/*
>  	 * Whenever the number of active pipes changes, we need to make sure we
>  	 * update the pipes in the right order so that their ddb allocations
> @@ -14617,10 +14633,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  				intel_wait_for_vblank(dev_priv, pipe);
>  		}
>  	}
> -
> -	/* If 2nd DBuf slice is no more required disable it */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
>  }
>  
>  static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
> @@ -14750,6 +14762,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  	if (state->modeset)
>  		intel_encoders_update_prepare(state);
>  
> +	/* Enable all new slices, we might need */
> +	icl_dbuf_slice_pre_update(state);
> +
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
>  	dev_priv->display.commit_modeset_enables(state);
>  
> @@ -14825,6 +14840,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  	if (state->modeset && intel_can_enable_sagv(state))
>  		intel_enable_sagv(dev_priv);
>  
> +	/* Disable all slices, we don't need */
> +	icl_dbuf_slice_post_update(state);
> +
>  	drm_atomic_helper_commit_hw_done(&state->base);
>  
>  	if (state->modeset) {
> -- 
> 2.17.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly Stanislav Lisovskiy
@ 2019-12-13 19:01   ` Matt Roper
  2019-12-16 15:07     ` Lisovskiy, Stanislav
  2019-12-18 18:00   ` Ville Syrjälä
  1 sibling, 1 reply; 23+ messages in thread
From: Matt Roper @ 2019-12-13 19:01 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy wrote:
> Start manipulating DBuf slices as a mask,
> but not as a total number, as current approach
> doesn't give us full control on all combinations
> of slices, which we might need(like enabling S2
> only can't enabled by setting enabled_slices=1).
> 
> Removed wrong code from intel_get_ddb_size as
> it doesn't match to BSpec. For now still just
> use DBuf slice until proper algorithm is implemented.
> 
> Other minor code refactoring to get prepared
> for major DBuf assignment changes landed:
> - As now enabled slices contain a mask
>   we still need some value which should
>   reflect how much DBuf slices are supported
>   by the platform, now device info contains
>   num_supported_dbuf_slices.
> - Removed unneeded assertion as we are now
>   manipulating slices in a more proper way.
> 
> v2: Start using enabled_slices in dev_priv
> 
> v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
>     as this now sits in dev_priv independently.
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
>  .../drm/i915/display/intel_display_power.c    | 100 ++++++++----------
>  .../drm/i915/display/intel_display_power.h    |   5 +
>  .../drm/i915/display/intel_display_types.h    |   2 +-
>  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
>  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
>  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
>  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
>  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
>  9 files changed, 84 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0e09d0c23b1d..42a0ea540d4f 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  
>  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
>  
> -	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> +	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 11 &&
> -	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
> -		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
> -			  dev_priv->enabled_dbuf_slices_num,
> +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
> +		DRM_ERROR("mismatch in DBUF Slices (expected %x, got %x)\n",

Minor nitpick:  I'd write these with "0x%x" to make it more obvious to
the person reading the message that the value is hex and thus a bitmask
rather than a count.

> +			  dev_priv->enabled_dbuf_slices_mask,
>  			  hw_enabled_slices);
>  
>  	/* planes */
> @@ -14549,22 +14549,23 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
>  static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> +	u8 required_slices = state->enabled_dbuf_slices_mask;
> +	u8 slices_union = hw_enabled_slices | required_slices;
>  
>  	/* If 2nd DBuf slice required, enable it here */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)

Should this be hw_enabled_slices != slices_union so that we only process
it when we're adding new slices and not in cases where we're only going
to be taking slices away?

> +		icl_dbuf_slices_update(dev_priv, slices_union);
>  }
>  
>  static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> +	u8 required_slices = state->enabled_dbuf_slices_mask;
>  
>  	/* If 2nd DBuf slice is no more required disable it */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)
>  		icl_dbuf_slices_update(dev_priv, required_slices);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index b8983422a882..ba384a5315f8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -1031,15 +1031,6 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
>  		(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
>  }
>  
> -static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
> -{
> -	u32 tmp = I915_READ(DBUF_CTL);
> -
> -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> -	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
> -}
> -
>  static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_cdclk_state cdclk_state = {};
> @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
>  	/* Can't read out voltage_level so can't use intel_cdclk_changed() */
>  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state));
>  
> -	gen9_assert_dbuf_enabled(dev_priv);
> -

I'm undecided on whether dropping the assertion completely is a good
idea or not.  If I understand correctly, it was never meant to check
that our own handling of the dbuf is correct (and it was added back when
we only ever had a single dbuf slice on gen9), but rather than the DMC
did the right thing when enabling/disabling the dbuf around DC state
transitions.  As far as I know, the DMC has been pretty solid recently,
but extra paranoia around firmware we don't directly control still seems
like a good idea to me.


>  	if (IS_GEN9_LP(dev_priv))
>  		bxt_verify_ddi_phy_power_wells(dev_priv);
>  
> @@ -4254,72 +4243,71 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
>  	intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
>  }
>  
> -static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv)

I don't see any new usage of this function outside this file.  I think
we can keep this static?

>  {
> -	if (INTEL_GEN(dev_priv) < 11)
> -		return 1;
> -	return 2;
> +	return INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> +}
> +
> +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv)

It looks like this never gets used outside this file either, so it could
probably be static.  Or it's simple enough that we could just drop it
completely and inline the icl_dbuf_slices_update() directly at the
callsites.

> +{
> +	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> +
> +	icl_dbuf_slices_update(dev_priv, hw_enabled_slices);
>  }
>  
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices)
>  {
> -	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	bool ret;
> +	int i;
> +	int max_slices = intel_dbuf_max_slices(dev_priv);
>  
> -	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> +	if (hweight8(req_slices) > intel_dbuf_max_slices(dev_priv)) {
>  		DRM_ERROR("Invalid number of dbuf slices requested\n");
>  		return;
>  	}
>  
> -	if (req_slices == hw_enabled_slices || req_slices == 0)
> -		return;
> +	DRM_DEBUG_KMS("Updating dbuf slices to %x\n", req_slices);

As noted above, I prefer "0x%x" to make it more obvious the number is a
bitmask.  Up to you though.

>  
> -	if (req_slices > hw_enabled_slices)
> -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
> -	else
> -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
> +	for (i = 0; i < max_slices; i++) {
> +		int slice_bit = BIT(i);
> +		bool slice_set = (slice_bit & req_slices) != 0;

Technically you could drop the "!= 0" part since anything non-zero will
be evaluated as 'true.'  Doesn't really matter though.

> +
> +		switch (slice_bit) {
> +		case DBUF_S1_BIT:
> +			intel_dbuf_slice_set(dev_priv,
> +					     DBUF_CTL_S1,
> +					     slice_set);
> +			break;
> +		case DBUF_S2_BIT:
> +			intel_dbuf_slice_set(dev_priv,
> +					     DBUF_CTL_S2,
> +					     slice_set);
> +			break;
> +		default:
> +			MISSING_CASE(slice_bit);
> +		}

It might be worth parameterizing DBUF_CTL so that we can simplify code
like this to just

        intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), slice_set);

or even just

        intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), req_slices & BIT(i))

as we do with other types of registers.  That will also future-proof a
bit in case we ever get platforms with more dbuf slices.

> +	}
>  
> -	if (ret)
> -		dev_priv->enabled_dbuf_slices_num = req_slices;
> +	dev_priv->enabled_dbuf_slices_mask = req_slices;
>  }
>  
>  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
>  {
> -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST);
> -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST);
> -	POSTING_READ(DBUF_CTL_S2);
> -
> -	udelay(10);
> -
> -	if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> -	    !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> -		DRM_ERROR("DBuf power enable timeout\n");
> -	else
> -		/*
> -		 * FIXME: for now pretend that we only have 1 slice, see
> -		 * intel_enabled_dbuf_slices_num().
> -		 */
> -		dev_priv->enabled_dbuf_slices_num = 1;
> +	/*
> +	 * Just power up 1 slice, we will
> +	 * figure out later which slices we have and what we need.
> +	 */
> +	dev_priv->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> +	icl_program_dbuf_slices(dev_priv);
>  }
>  
>  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
>  {
> -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST);
> -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST);
> -	POSTING_READ(DBUF_CTL_S2);
> -
> -	udelay(10);
> -
> -	if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> -	    (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> -		DRM_ERROR("DBuf power disable timeout!\n");
> -	else
> -		/*
> -		 * FIXME: for now pretend that the first slice is always
> -		 * enabled, see intel_enabled_dbuf_slices_num().
> -		 */
> -		dev_priv->enabled_dbuf_slices_num = 1;
> +	/*
> +	 * Disable all slices
> +	 */
> +	dev_priv->enabled_dbuf_slices_mask = 0;
> +	icl_program_dbuf_slices(dev_priv);
>  }
>  
>  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
> index 1da04f3e0fb3..0d9f87607eac 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> @@ -311,8 +311,13 @@ intel_display_power_put_async(struct drm_i915_private *i915,
>  	for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
>  	     intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
>  
> +#define DBUF_S1_BIT			BIT(0)
> +#define DBUF_S2_BIT			BIT(1)
> +
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices);
> +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv);
> +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv);
>  
>  void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>  			     bool override, unsigned int mask);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 70e65c2d525d..ba2e41a03051 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -518,7 +518,7 @@ struct intel_atomic_state {
>  	struct skl_ddb_values wm_results;
>  
>  	/* Number of enabled DBuf slices */
> -	u8 enabled_dbuf_slices_num;
> +	u8 enabled_dbuf_slices_mask;
>  
>  	struct i915_sw_fence commit_ready;
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7a2d9fa5a9a6..ec4b9e3cef79 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1210,7 +1210,7 @@ struct drm_i915_private {
>  		bool distrust_bios_wm;
>  	} wm;
>  
> -	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */
> +	u8 enabled_dbuf_slices_mask; /* GEN11 has configurable 2 slices */
>  
>  	struct dram_info {
>  		bool valid;
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> index 877560b1031e..2068aac5ab6a 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -614,7 +614,8 @@ static const struct intel_device_info intel_cherryview_info = {
>  	.has_gt_uc = 1, \
>  	.display.has_hdcp = 1, \
>  	.display.has_ipc = 1, \
> -	.ddb_size = 896
> +	.ddb_size = 896, \
> +	.num_supported_dbuf_slices = 1
>  
>  #define SKL_PLATFORM \
>  	GEN9_FEATURES, \
> @@ -649,6 +650,7 @@ static const struct intel_device_info intel_skylake_gt4_info = {
>  #define GEN9_LP_FEATURES \
>  	GEN(9), \
>  	.is_lp = 1, \
> +	.num_supported_dbuf_slices = 1, \
>  	.display.has_hotplug = 1, \
>  	.engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \
>  	.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
> @@ -737,6 +739,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info = {
>  	GEN9_FEATURES, \
>  	GEN(10), \
>  	.ddb_size = 1024, \
> +	.num_supported_dbuf_slices = 1, \

GEN10_FEATURES inherits everything from GEN9_FEATURES, so I think we can
drop this one.


>  	.display.has_dsc = 1, \
>  	.has_coherent_ggtt = false, \
>  	GLK_COLORS
> @@ -773,6 +776,7 @@ static const struct intel_device_info intel_cannonlake_info = {
>  	}, \
>  	GEN(11), \
>  	.ddb_size = 2048, \
> +	.num_supported_dbuf_slices = 2, \
>  	.has_logical_ring_elsq = 1, \
>  	.color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
>  
> diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
> index 2725cb7fc169..7d4d122d2182 100644
> --- a/drivers/gpu/drm/i915/intel_device_info.h
> +++ b/drivers/gpu/drm/i915/intel_device_info.h
> @@ -180,6 +180,7 @@ struct intel_device_info {
>  	} display;
>  
>  	u16 ddb_size; /* in blocks */
> +	u8 num_supported_dbuf_slices; /* number of DBuf slices */
>  
>  	/* Register offsets for the various display pipes and transcoders */
>  	int pipe_offsets[I915_MAX_TRANSCODERS];
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c2510978ccdf..111bcafd6e4c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3616,26 +3616,22 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
>  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
>  }
>  
> -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
> +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv)
>  {
> -	u8 enabled_dbuf_slices_num;
> -
> -	/* Slice 1 will always be enabled */
> -	enabled_dbuf_slices_num = 1;
> +	u8 enabled_slices_mask = 0;
>  
>  	/* Gen prior to GEN11 have only one DBuf slice */
>  	if (INTEL_GEN(dev_priv) < 11)
> -		return enabled_dbuf_slices_num;
> +		return DBUF_S1_BIT;

Do we want to assume this or should we just read it anyway to make sure?
As noted before, we might get into a disagreement with the DMC or
something and it would be good to know how the hardware is actually set.

> -	/*
> -	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
> -	 * only that 1 slice enabled until we have a proper way for on-demand
> -	 * toggling of the second slice.
> -	 */
> -	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> -		enabled_dbuf_slices_num++;
> +	/* Check if second DBuf slice is enabled */
> +	if (I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE)
> +		enabled_slices_mask |= DBUF_S1_BIT;

You have the comment about the second slice before your check of the
first slice...  I think you can just drop the comment in this case.

>  
> -	return enabled_dbuf_slices_num;
> +	if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> +		enabled_slices_mask |= DBUF_S2_BIT;
> +
> +	return enabled_slices_mask;
>  }
>  
>  /*
> @@ -3843,8 +3839,6 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  {
>  	struct drm_atomic_state *state = crtc_state->uapi.state;
>  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
> -	const struct drm_display_mode *adjusted_mode;
> -	u64 total_data_bw;
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
>  
>  	WARN_ON(ddb_size == 0);
> @@ -3852,23 +3846,8 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	if (INTEL_GEN(dev_priv) < 11)
>  		return ddb_size - 4; /* 4 blocks for bypass path allocation */
>  
> -	adjusted_mode = &crtc_state->hw.adjusted_mode;
> -	total_data_bw = total_data_rate * drm_mode_vrefresh(adjusted_mode);
> -
> -	/*
> -	 * 12GB/s is maximum BW supported by single DBuf slice.
> -	 *
> -	 * FIXME dbuf slice code is broken:
> -	 * - must wait for planes to stop using the slice before powering it off
> -	 * - plane straddling both slices is illegal in multi-pipe scenarios
> -	 * - should validate we stay within the hw bandwidth limits
> -	 */
> -	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> -		intel_state->enabled_dbuf_slices_num = 2;
> -	} else {
> -		intel_state->enabled_dbuf_slices_num = 1;
> -		ddb_size /= 2;
> -	}
> +	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> +	ddb_size /= 2;
>  
>  	return ddb_size;
>  }
> @@ -4065,7 +4044,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  
>  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
>  {
> -	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);
> +	dev_priv->enabled_dbuf_slices_mask = intel_enabled_dbuf_slices_mask(dev_priv);
>  }
>  
>  /*
> @@ -5204,7 +5183,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
>  	struct intel_crtc *crtc;
>  	int ret, i;
>  
> -	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
> +	state->enabled_dbuf_slices_mask = dev_priv->enabled_dbuf_slices_mask;
>  
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
> diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
> index a476f6c730e9..7a7494d1224f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.h
> +++ b/drivers/gpu/drm/i915/intel_pm.h
> @@ -33,7 +33,7 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
> +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv);
>  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  			       struct skl_ddb_entry *ddb_y,
>  			       struct skl_ddb_entry *ddb_uv);
> -- 
> 2.17.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy
@ 2019-12-14  0:52   ` Matt Roper
  2019-12-16 14:31     ` Lisovskiy, Stanislav
  2019-12-18 18:05   ` Ville Syrjälä
  1 sibling, 1 reply; 23+ messages in thread
From: Matt Roper @ 2019-12-14  0:52 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:28PM +0200, Stanislav Lisovskiy wrote:
> Added proper DBuf slice mapping to correspondent
> pipes, depending on pipe configuration as stated
> in BSpec.
> 
> v2:
>     - Remove unneeded braces
>     - Stop using macro for DBuf assignments as
>       it seems to reduce readability.
> 
> v3: Start using enabled slices mask in dev_priv
> 
> v4: Renamed "enabled_slices" used in dev_priv
>     to "enabled_dbuf_slices_mask"(Matt Roper)
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 226 ++++++++++++++++++++++++++++++--
>  1 file changed, 216 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 111bcafd6e4c..a13052b2c2ef 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
>  	return true;
>  }
>  
> +/*
> + * Calculate initial DBuf slice offset, based on slice size
> + * and mask(i.e if slice size is 1024 and second slice is enabled
> + * offset would be 1024)
> + */
> +static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
> +					   u32 slice_size, u32 ddb_size)
> +{

It might be worth just passing the mask + dev_priv to this function and
let it get slice_size / ddb_size on its own to keep the logic simpler at
the callsite.

> +	u32 offset = 0;
> +
> +	if (!dbuf_slice_mask)
> +		return 0;
> +
> +	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
> +
> +	WARN_ON(offset >= ddb_size);
> +	return offset;
> +}
> +
>  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  			      const struct intel_crtc_state *crtc_state,
>  			      const u64 total_data_rate,
>  			      const int num_active)

I probably should have mentioned it on the previous patch, but most of
these parameters are no longer needed now.

>  {
> -	struct drm_atomic_state *state = crtc_state->uapi.state;
> -	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
>  
>  	WARN_ON(ddb_size == 0);
> @@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	if (INTEL_GEN(dev_priv) < 11)
>  		return ddb_size - 4; /* 4 blocks for bypass path allocation */
>  
> -	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> -	ddb_size /= 2;
> -
>  	return ddb_size;
>  }
>  
> +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> +			      int pipe, u32 active_pipes,
> +			      const struct intel_crtc_state *crtc_state);
> +
>  static void
>  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  				   const struct intel_crtc_state *crtc_state,
> @@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
>  	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
>  	u16 ddb_size;
> +	u32 ddb_range_size;
>  	u32 i;
> +	u32 dbuf_slice_mask;
> +	u32 active_pipes;
> +	u32 offset;
> +	u32 slice_size;
> +	u32 total_slice_mask;
> +	u32 start, end;
>  
>  	if (WARN_ON(!state) || !crtc_state->hw.active) {
>  		alloc->start = 0;
> @@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	if (intel_state->active_pipe_changes)
> +	if (intel_state->active_pipe_changes) {
>  		*num_active = hweight8(intel_state->active_pipes);
> -	else
> +		active_pipes = intel_state->active_pipes;
> +	} else {
>  		*num_active = hweight8(dev_priv->active_pipes);
> +		active_pipes = dev_priv->active_pipes;
> +	}

Might be slightly more intuitive to move the num_active assignment
outside the 'if' as

        *num_active = hweight8(active_pipes);

Up to you; doesn't really matter.

>  
>  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
>  				      *num_active);
>  
> +	slice_size = ddb_size / INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> +
>  	/*
>  	 * If the state doesn't change the active CRTC's or there is no
>  	 * modeset request, then there's no need to recalculate;
> @@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> +	/*
> +	 * Get allowed DBuf slices for correspondent pipe and platform.
> +	 */
> +	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
> +						    active_pipes, crtc_state);
> +
> +	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
> +		      dbuf_slice_mask,
> +		      for_pipe, active_pipes);
> +
> +	/*
> +	 * Figure out at which DBuf slice we start, i.e if we start at Dbuf S2
> +	 * and slice size is 1024, the offset would be 1024
> +	 */
> +	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
> +						 slice_size, ddb_size);
> +
> +	/*
> +	 * Figure out total size of allowed DBuf slices, which is basically
> +	 * a number of allowed slices for that pipe multiplied by slice size.
> +	 * Inside of this
> +	 * range ddb entries are still allocated in proportion to display width.
> +	 */
> +	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
> +
>  	/*
>  	 * Watermark/ddb requirement highly depends upon width of the
>  	 * framebuffer, So instead of allocating DDB equally among pipes
>  	 * distribute DDB based on resolution/width of the display.
>  	 */
> +	total_slice_mask = dbuf_slice_mask;
>  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
>  		const struct drm_display_mode *adjusted_mode =
>  			&crtc_state->hw.adjusted_mode;
>  		enum pipe pipe = crtc->pipe;
>  		int hdisplay, vdisplay;
> +		u32 pipe_dbuf_slice_mask =
> +					i915_possible_dbuf_slices(dev_priv,
> +								  pipe,
> +								  active_pipes,
> +								  crtc_state);
> +
> +		if (!crtc_state->hw.active)
> +			continue;

You might want to do this check before we go through the bother of
executing i915_possible_dbuf_slices.

> +
> +		/*
> +		 * According to BSpec pipe can share one dbuf slice with another
> +		 * pipes or pipe can use multiple dbufs, in both cases we
> +		 * account for other pipes only if they have exactly same mask.
> +		 * However we need to account how many slices we should enable
> +		 * in total.
> +		 */
> +		total_slice_mask |= pipe_dbuf_slice_mask;
>  
> -		if (!crtc_state->hw.enable)
> +		/*
> +		 * Do not account pipes using other slice sets
> +		 * luckily as of current BSpec slice sets do not partially
> +		 * intersect(pipes share either same one slice or same slice set
> +		 * i.e no partial intersection), so it is enough to check for
> +		 * equality for now.
> +		 */
> +		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
>  			continue;
>  
>  		drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
> @@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  			pipe_width = hdisplay;
>  	}
>  
> -	alloc->start = ddb_size * width_before_pipe / total_width;
> -	alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width;
> +	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
> +
> +	start = ddb_range_size * width_before_pipe / total_width;
> +	end = ddb_range_size * (width_before_pipe + pipe_width) / total_width;

I found it a bit confusing that "total_slice_mask" is a mask of all
active CRTCs, whereas total_width is only the width of the subset of
active CRTCs that share our slice mask (i.e., different meanings of
"total").  I think the logic here is correct, but some variable renaming
might make it more obvious what's going on?


> +
> +	alloc->start = offset + start;
> +	alloc->end = offset + end;
> +
> +	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
> +		      alloc->start, alloc->end);
> +	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
> +		      intel_state->enabled_dbuf_slices_mask,
> +		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
>  }
>  
>  static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
> @@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state,
>  	return mul_fixed16(downscale_w, downscale_h);
>  }
>  
> +struct dbuf_slice_conf_entry {
> +	u32 active_pipes;
> +	u32 dbuf_mask[I915_MAX_PIPES];
> +};
> +
> +/*
> + * Table taken from Bspec 12716
> + * Pipes do have some preferred DBuf slice affinity,
> + * plus there are some hardcoded requirements on how
> + * those should be distributed for multipipe scenarios.
> + * For more DBuf slices algorithm can get even more messy
> + * and less readable, so decided to use a table almost
> + * as is from BSpec itself - that way it is at least easier
> + * to compare, change and check.
> + */
> +static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
> +	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
> +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
> +	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }

I believe it's legal to leave ending array elements out of definitions,
in which case they'll just be 0.  So you can drop the fourth element of
all these dbuf_mask arrays since that's more intuitive given these
platforms only actually have three pipes.

> +};
> +
> +/*
> + * Table taken from Bspec 49255
> + * Pipes do have some preferred DBuf slice affinity,
> + * plus there are some hardcoded requirements on how
> + * those should be distributed for multipipe scenarios.
> + * For more DBuf slices algorithm can get even more messy
> + * and less readable, so decided to use a table almost
> + * as is from BSpec itself - that way it is at least easier
> + * to compare, change and check.
> + */
> +static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
> +	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
> +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
> +	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
                                             ^^^^^^^^^^^
I think this one is supposed to be S1 for pipe C.


> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> +};
> +
> +static u32 i915_find_pipe_conf(int pipe,
> +			       u32 active_pipes,
> +			       const struct dbuf_slice_conf_entry *dbuf_slices,
> +			       int size)
> +{
> +	int i;
> +
> +	for (i = 0; i < size; i++) {
> +		if (dbuf_slices[i].active_pipes == active_pipes)
> +			return dbuf_slices[i].dbuf_mask[pipe];
> +	}
> +	return 0;
> +}
> +
> +/*
> + * This function finds an entry with same enabled pipe configuration and
> + * returns correspondent DBuf slice mask as stated in BSpec for particular
> + * platform.
> + */
> +static u32 icl_possible_dbuf_slices(int pipe,
> +				    u32 active_pipes,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	return i915_find_pipe_conf(pipe, active_pipes,
> +				   icl_allowed_dbufs,
> +				   ARRAY_SIZE(icl_allowed_dbufs));

Should we be handling the <88.8% pipe ratio stuff here?  I.e., an extra
condition that if # pipes == 1 and the pipe ratio is less than 88.8%,
return both S1 and S2?  Or will that come in a future patch (in which
case a TODO/FIXME comment might be appropriate)?


> +}
> +
> +static u32 tgl_possible_dbuf_slices(int pipe,
> +				    u32 active_pipes,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	return i915_find_pipe_conf(pipe, active_pipes,
> +				   tgl_allowed_dbufs,
> +				   ARRAY_SIZE(tgl_allowed_dbufs));
> +}

Seems like these two functions (as currently written) are so simple that
we can just invoke i915_find_pipe_conf directly in
i915_possible_dbuf_slices.  Might also be worth considering using an
empty table entry as a terminator rather than requiring than an explicit
length be passed.

> +
> +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,

This can be static I think?

> +			      int pipe, u32 active_pipes,
> +			      const struct intel_crtc_state *crtc_state)
> +{
> +	if (IS_GEN(dev_priv, 11))
> +		return icl_possible_dbuf_slices(pipe,
> +						active_pipes,
> +						crtc_state);
> +	else if (IS_GEN(dev_priv, 12))
> +		return tgl_possible_dbuf_slices(pipe,
> +						active_pipes,
> +						crtc_state);
> +	/*
> +	 * For anything else just return one slice yet.
> +	 * Should be extended for other platforms.
> +	 */
> +	return DBUF_S1_BIT;
> +}

None of the three functions above seem to actually use crtc_state, so I
think we can drop that parameter.


> +
>  static u64
>  skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
>  			     const struct intel_plane_state *plane_state,
> -- 
> 2.17.1
> 

-- 
Matt Roper
Graphics Software Engineer
VTT-OSGC Platform Enablement
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [Intel-gfx] ✗ Fi.CI.IGT: failure for Enable second DBuf slice for ICL and TGL (rev8)
  2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
                   ` (4 preceding siblings ...)
  2019-12-13 13:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success for Enable second DBuf slice for ICL and TGL (rev8) Patchwork
@ 2019-12-14  7:04 ` Patchwork
  5 siblings, 0 replies; 23+ messages in thread
From: Patchwork @ 2019-12-14  7:04 UTC (permalink / raw)
  To: Lisovskiy, Stanislav; +Cc: intel-gfx

== Series Details ==

Series: Enable second DBuf slice for ICL and TGL (rev8)
URL   : https://patchwork.freedesktop.org/series/70059/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7558_full -> Patchwork_15742_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_15742_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_15742_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_15742_full:

### IGT changes ###

#### Possible regressions ####

  * igt@runner@aborted:
    - shard-apl:          NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/shard-apl8/igt@runner@aborted.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * {igt@gen9_exec_parse@allowed-single}:
    - shard-skl:          [PASS][2] -> [DMESG-WARN][3]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7558/shard-skl5/igt@gen9_exec_parse@allowed-single.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/shard-skl4/igt@gen9_exec_parse@allowed-single.html

  * {igt@gen9_exec_parse@bb-chained}:
    - shard-iclb:         NOTRUN -> [SKIP][4] +1 similar issue
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/shard-iclb6/igt@gen9_exec_parse@bb-chained.html

  * {igt@gen9_exec_parse@bb-start-param}:
    - shard-tglb:         NOTRUN -> [SKIP][5] +3 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/shard-tglb5/igt@gen9_exec_parse@bb-start-param.html

  

### Piglit changes ###

#### Possible regressions ####

  * spec@glsl-1.30@execution@texelfetch@fs-texelfetch-isampler1darray (NEW):
    - pig-hsw-4770r:      NOTRUN -> [FAIL][6] +1321 similar issues
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/pig-hsw-4770r/spec@glsl-1.30@execution@texelfetch@fs-texelfetch-isampler1darray.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7558_full and Patchwork_15742_full:

### New Piglit tests (1010) ###

  * hiz@hiz-depth-read-window-stencil1:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * object namespace pollution@texture with glbitmap:
    - Statuses : 1 fail(s)
    - Exec time: [0.24] s

  * object namespace pollution@texture with glclear:
    - Statuses : 1 fail(s)
    - Exec time: [0.19] s

  * object namespace pollution@texture with glcleartexsubimage:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * shaders@glsl-fs-floor:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * shaders@glsl-fs-texture2dproj-2:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@!opengl 1.2@copyteximage 3d:
    - Statuses : 1 fail(s)
    - Exec time: [0.32] s

  * spec@!opengl 1.2@getteximage-targets 3d:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@!opengl 1.2@levelclamp:
    - Statuses : 1 fail(s)
    - Exec time: [4.79] s

  * spec@!opengl 1.2@lodclamp:
    - Statuses : 1 fail(s)
    - Exec time: [4.74] s

  * spec@!opengl 1.2@mipmap-setup:
    - Statuses : 1 fail(s)
    - Exec time: [4.53] s

  * spec@!opengl 1.2@tex3d:
    - Statuses : 1 fail(s)
    - Exec time: [0.27] s

  * spec@!opengl 1.2@texture-packed-formats:
    - Statuses : 1 fail(s)
    - Exec time: [2.37] s

  * spec@!opengl 1.3@tex-border-1:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 1.4@draw-batch:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 1.4@gl-1.4-dlist-multidrawarrays:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@!opengl 1.4@gl-1.4-polygon-offset:
    - Statuses : 1 incomplete(s)
    - Exec time: [0.0] s

  * spec@!opengl 1.4@tex-miplevel-selection-lod:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@!opengl 1.4@tex-miplevel-selection-lod-bias:
    - Statuses : 1 fail(s)
    - Exec time: [1.13] s

  * spec@!opengl 1.5@depth-tex-compare:
    - Statuses : 1 fail(s)
    - Exec time: [0.28] s

  * spec@!opengl 1.5@draw-vertices:
    - Statuses : 1 fail(s)
    - Exec time: [0.21] s

  * spec@!opengl 1.5@draw-vertices-user:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@!opengl 2.0@attribs:
    - Statuses : 1 fail(s)
    - Exec time: [0.68] s

  * spec@!opengl 2.0@depth-tex-modes-glsl:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@!opengl 2.0@gl-2.0-two-sided-stencil:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@!opengl 2.0@max-samplers:
    - Statuses : 1 fail(s)
    - Exec time: [0.53] s

  * spec@!opengl 2.0@max-samplers border:
    - Statuses : 1 fail(s)
    - Exec time: [0.45] s

  * spec@!opengl 2.0@stencil-twoside:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@!opengl 2.0@tex3d-npot:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@!opengl 2.0@vertex-program-two-side enabled front back back2:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@!opengl 2.0@vertex-program-two-side enabled front front2 back2:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 2.1@pbo:
    - Statuses : 1 fail(s)
    - Exec time: [0.21] s

  * spec@!opengl 3.0@attribs:
    - Statuses : 1 fail(s)
    - Exec time: [0.25] s

  * spec@!opengl 3.0@clearbuffer-depth:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@!opengl 3.0@clearbuffer-depth-stencil:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@!opengl 3.0@clearbuffer-display-lists:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.0@clearbuffer-mixed-format:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@!opengl 3.0@clearbuffer-stencil:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@!opengl 3.0@gl-3.0-texture-integer:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.0@render-integer:
    - Statuses : 1 fail(s)
    - Exec time: [0.23] s

  * spec@!opengl 3.0@sampler-cube-shadow:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.2@coord-replace-doesnt-eliminate-frag-tex-coords:
    - Statuses : 1 fail(s)
    - Exec time: [0.56] s

  * spec@!opengl 3.2@layered-rendering@clear-color-all-types cube_map_array mipmapped:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.2@layered-rendering@framebuffertexture:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.2@layered-rendering@gl-layer:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@!opengl 3.2@layered-rendering@gl-layer-cube-map:
    - Statuses : 1 fail(s)
    - Exec time: [0.09] s

  * spec@!opengl 3.2@layered-rendering@gl-layer-render:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@!opengl 3.2@layered-rendering@gl-layer-render-clipped:
    - Statuses : 1 fail(s)
    - Exec time: [0.07] s

  * spec@3dfx_texture_compression_fxt1@compressedteximage gl_compressed_rgba_fxt1_3dfx:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@3dfx_texture_compression_fxt1@fbo-generatemipmap-formats:
    - Statuses : 1 fail(s)
    - Exec time: [0.23] s

  * spec@3dfx_texture_compression_fxt1@fxt1-teximage:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@amd_shader_trinary_minmax@execution@built-in-functions@fs-mid3-ivec2-ivec2-ivec2:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@amd_shader_trinary_minmax@execution@built-in-functions@fs-min3-int-int-int:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_arrays_of_arrays@execution@sampler@fs-initializer-const-index:
    - Statuses : 1 fail(s)
    - Exec time: [0.15] s

  * spec@arb_base_instance@arb_base_instance-drawarrays:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_blend_func_extended@arb_blend_func_extended-fbo-extended-blend:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@arb_blend_func_extended@arb_blend_func_extended-fbo-extended-blend-explicit:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_blend_func_extended@arb_blend_func_extended-fbo-extended-blend-explicit_gles3:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_blend_func_extended@arb_blend_func_extended-fbo-extended-blend_gles3:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_clear_texture@arb_clear_texture-base-formats:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_clip_control@arb_clip_control-clip-control:
    - Statuses : 1 fail(s)
    - Exec time: [0.22] s

  * spec@arb_clip_control@arb_clip_control-depth-precision:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@arb_clip_control@arb_clip_control-viewport:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_color_buffer_float@gl_rgba16f-render:
    - Statuses : 1 fail(s)
    - Exec time: [0.71] s

  * spec@arb_color_buffer_float@gl_rgba16f-render-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.76] s

  * spec@arb_color_buffer_float@gl_rgba16f-render-sanity:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@arb_color_buffer_float@gl_rgba16f-render-sanity-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@arb_color_buffer_float@gl_rgba32f-render:
    - Statuses : 1 fail(s)
    - Exec time: [0.64] s

  * spec@arb_color_buffer_float@gl_rgba32f-render-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.65] s

  * spec@arb_color_buffer_float@gl_rgba32f-render-sanity:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_color_buffer_float@gl_rgba8-render:
    - Statuses : 1 fail(s)
    - Exec time: [0.52] s

  * spec@arb_color_buffer_float@gl_rgba8-render-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.74] s

  * spec@arb_color_buffer_float@gl_rgba8-render-sanity:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@arb_color_buffer_float@gl_rgba8-render-sanity-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_color_buffer_float@gl_rgba8_snorm-probepixel:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_color_buffer_float@gl_rgba8_snorm-render:
    - Statuses : 1 fail(s)
    - Exec time: [0.81] s

  * spec@arb_color_buffer_float@gl_rgba8_snorm-render-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.77] s

  * spec@arb_color_buffer_float@gl_rgba8_snorm-render-sanity:
    - Statuses : 1 fail(s)
    - Exec time: [0.20] s

  * spec@arb_color_buffer_float@gl_rgba8_snorm-render-sanity-fog:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_color_buffer_float@mixed-mrt:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_compute_shader@render-and-compute:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_copy_buffer@overlap:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_copy_image@arb_copy_image-format-swizzle:
    - Statuses : 1 fail(s)
    - Exec time: [0.26] s

  * spec@arb_copy_image@arb_copy_image-formats --samples=2:
    - Statuses : 1 fail(s)
    - Exec time: [1.44] s

  * spec@arb_copy_image@arb_copy_image-formats --samples=4:
    - Statuses : 1 fail(s)
    - Exec time: [1.45] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_1d_array 32 1 12 gl_texture_2d_array 32 16 18 11 0 3 5 9 7 14 1 8:
    - Statuses : 1 fail(s)
    - Exec time: [0.21] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_1d_array 32 1 12 gl_texture_3d 32 16 18 11 0 3 5 9 2 14 1 7:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_1d_array 32 1 12 gl_texture_cube_map 32 32 6 11 0 3 5 17 2 14 1 3:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_1d_array 32 1 12 gl_texture_cube_map_array 32 32 18 11 0 3 5 17 2 14 1 7:
    - Statuses : 1 fail(s)
    - Exec time: [0.20] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d 32 32 1 gl_texture_1d_array 32 1 16 11 2 0 5 0 7 14 1 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d 32 32 1 gl_texture_2d 32 16 1 11 12 0 5 7 0 14 9 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d 32 32 1 gl_texture_3d 32 16 18 11 5 0 5 9 7 14 7 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d_array 32 32 15 gl_texture_2d_array 32 16 15 11 12 5 5 7 2 14 9 9:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d_array 32 32 15 gl_texture_3d 32 16 18 11 5 2 5 9 7 14 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.20] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_2d_array 32 32 15 gl_texture_cube_map_array 32 32 18 11 5 2 5 9 7 14 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.28] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_1d 32 1 1 11 23 7 5 0 0 14 1 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_1d_array 32 1 16 11 2 5 5 0 7 14 1 7:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_2d 32 16 1 11 12 13 5 7 0 14 7 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_2d_array 32 16 15 11 12 5 5 3 2 14 13 9:
    - Statuses : 1 fail(s)
    - Exec time: [0.28] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_3d 32 16 18 11 5 2 5 9 7 14 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.19] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_3d 32 32 17 gl_texture_cube_map_array 16 16 18 11 5 2 5 9 7 5 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.46] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map 32 32 6 gl_texture_1d 32 1 1 11 23 3 5 0 0 14 1 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map 32 32 6 gl_texture_2d_array 32 16 15 11 12 1 5 3 2 14 11 4:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map 32 32 6 gl_texture_3d 32 16 18 11 5 0 5 9 7 14 7 4:
    - Statuses : 1 fail(s)
    - Exec time: [0.18] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map 32 32 6 gl_texture_cube_map_array 32 32 18 11 5 1 5 9 9 14 7 5:
    - Statuses : 1 fail(s)
    - Exec time: [0.20] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_1d 32 1 1 11 23 7 5 0 0 14 1 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_1d_array 32 1 16 11 2 5 5 0 7 14 1 7:
    - Statuses : 1 fail(s)
    - Exec time: [0.13] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_2d_array 32 16 15 11 12 5 5 1 2 14 15 9:
    - Statuses : 1 fail(s)
    - Exec time: [0.23] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_3d 32 16 18 11 5 2 5 9 7 14 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.23] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_cube_map 16 16 6 11 5 1 5 9 2 5 7 3:
    - Statuses : 1 fail(s)
    - Exec time: [0.15] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_cube_map_array 32 32 18 gl_texture_cube_map_array 16 16 18 11 5 2 5 9 7 5 7 11:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_copy_image@arb_copy_image-targets gl_texture_rectangle 32 32 1 gl_texture_rectangle 32 16 1 11 12 0 5 7 0 14 9 1:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 1024 d=s=z32f_s8:
    - Statuses : 1 fail(s)
    - Exec time: [0.48] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 1024 s=d=z32f_s8:
    - Statuses : 1 fail(s)
    - Exec time: [0.49] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 146 d=z32f:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 146 d=z32f_s=z24_s8:
    - Statuses : 1 fail(s)
    - Exec time: [0.09] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 273 d=z32f_s=z24_s8:
    - Statuses : 1 fail(s)
    - Exec time: [0.09] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 273 s=z24_s8_d=z32f:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 292 s=z24_s8_d=z32f:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 585 d=z32f_s=z24_s8:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_depth_buffer_float@depthstencil-render-miplevels 585 s=z24_s8_d=z32f:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_depth_buffer_float@fbo-clear-formats stencil:
    - Statuses : 1 fail(s)
    - Exec time: [0.44] s

  * spec@arb_depth_buffer_float@texwrap formats:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_depth_texture@depth-tex-modes:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 1024 d=z24:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 146 d=z24:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 273 d=z24:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 292 d=z16:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 292 d=z24:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_depth_texture@depthstencil-render-miplevels 585 d=z16:
    - Statuses : 1 fail(s)
    - Exec time: [0.09] s

  * spec@arb_depth_texture@texdepth:
    - Statuses : 1 fail(s)
    - Exec time: [0.11] s

  * spec@arb_depth_texture@texwrap formats offset:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_direct_state_access@gettextureimage-targets:
    - Statuses : 1 fail(s)
    - Exec time: [0.16] s

  * spec@arb_direct_state_access@textures-storage:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_draw_elements_base_vertex@arb_draw_elements_base_vertex-drawelements:
    - Statuses : 1 fail(s)
    - Exec time: [0.20] s

  * spec@arb_draw_elements_base_vertex@arb_draw_elements_base_vertex-drawelements-instanced:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_draw_elements_base_vertex@arb_draw_elements_base_vertex-drawelements-user_varrays:
    - Statuses : 1 fail(s)
    - Exec time: [0.22] s

  * spec@arb_fragment_program@fp-long-alu:
    - Statuses : 1 fail(s)
    - Exec time: [0.14] s

  * spec@arb_framebuffer_object@fbo-blit-stretch:
    - Statuses : 1 fail(s)
    - Exec time: [0.24] s

  * spec@arb_framebuffer_object@fbo-drawbuffers-none glblendfunci:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_framebuffer_object@fbo-drawbuffers-none glblitframebuffer:
    - Statuses : 1 fail(s)
    - Exec time: [0.10] s

  * spec@arb_framebuffer_object@fbo-drawbuffers-none use_frag_out:
    - Statuses : 1 fail(s)
    - Exec time: [0.12] s

  * spec@arb_framebuffer_object@fbo-generatemipmap-3d:
    - Statuses : 1 fail(s)
    - Exec time: [0.22] s

  * spec@arb_framebuffer_object@fbo-mipmap-copypix:
    - Statuses : 1 fail(s)
    - Exec time: [0.45] s

  * spec@arb_framebuffer_srgb@framebuffer-srgb:
    - Statuses : 1 fail(s)
    - Exec time: [0.08] s

  * spec@arb_get_texture_sub_image@arb_get_texture_sub_image-get:
    - Statuses : 1 fail(s)
    - Exec time: [0.70] s

  * spec@arb_gpu_shader5@execution@ubo_array_indexing@vs-array-nonconst:
    - Statuses : 1 fail(s)
    - Exec time: [0.17] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-float-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.67] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-float-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.52] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-float-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.71] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-float-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.58] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-float-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.69] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-int-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.57] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-int-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.61] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-int-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.62] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-int-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-int-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.74] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-uint-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.57] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-uint-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.80] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-uint-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.71] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-unorm-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.38] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-unorm-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-unorm-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-unorm-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-r-0-unorm-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.71] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-float-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.76] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-float-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-float-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-float-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.53] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-float-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-int-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.63] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-int-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-int-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-int-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-int-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-uint-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.50] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-uint-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.67] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-uint-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.77] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-uint-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.63] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-unorm-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.66] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-unorm-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-unorm-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.67] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-unorm-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.56] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-0-unorm-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.66] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-float-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.72] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-float-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.74] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-float-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-float-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-float-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.60] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-int-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.69] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-int-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-int-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.55] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-int-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-uint-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.74] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-uint-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.76] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-uint-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.57] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-uint-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.79] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-uint-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-unorm-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.66] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-unorm-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.76] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-unorm-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.56] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-unorm-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.65] s

  * spec@arb_gpu_shader5@texturegather@vs-rg-1-unorm-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-float-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.73] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-float-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.70] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-float-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.62] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-float-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.62] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-int-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.66] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-int-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.78] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-int-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-uint-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.61] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-uint-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.75] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-uint-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-uint-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.69] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-uint-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.74] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-unorm-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-unorm-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-unorm-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.64] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-unorm-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-0-unorm-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-float-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.59] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-float-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.72] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-float-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.79] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-int-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.66] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-int-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.50] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-uint-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.78] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-uint-2darray:
    - Statuses : 1 fail(s)
    - Exec time: [1.75] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-uint-2drect:
    - Statuses : 1 fail(s)
    - Exec time: [1.69] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-uint-cube:
    - Statuses : 1 fail(s)
    - Exec time: [1.67] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-uint-cubearray:
    - Statuses : 1 fail(s)
    - Exec time: [1.68] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-unorm-2d:
    - Statuses : 1 fail(s)
    - Exec time: [1.62] s

  * spec@arb_gpu_shader5@texturegather@vs-rgb-1-unorm-2darray:
    - Statuses : 1 fail(s)

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_15742/index.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-14  0:52   ` Matt Roper
@ 2019-12-16 14:31     ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-16 14:31 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: intel-gfx

On Fri, 2019-12-13 at 16:52 -0800, Matt Roper wrote:
> On Fri, Dec 13, 2019 at 03:02:28PM +0200, Stanislav Lisovskiy wrote:
> > Added proper DBuf slice mapping to correspondent
> > pipes, depending on pipe configuration as stated
> > in BSpec.
> > 
> > v2:
> >     - Remove unneeded braces
> >     - Stop using macro for DBuf assignments as
> >       it seems to reduce readability.
> > 
> > v3: Start using enabled slices mask in dev_priv
> > 
> > v4: Renamed "enabled_slices" used in dev_priv
> >     to "enabled_dbuf_slices_mask"(Matt Roper)
> > 
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 226
> > ++++++++++++++++++++++++++++++--
> >  1 file changed, 216 insertions(+), 10 deletions(-)

Hi Matt, 

thanks for good comments, as usual. 
Most of the issues I've addressed in a recent series,
for some which I didn't I will reply inline here.

> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c
> > index 111bcafd6e4c..a13052b2c2ef 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct
> > intel_atomic_state *state)
> >  	return true;
> >  }
> >  
> > +/*
> > + * Calculate initial DBuf slice offset, based on slice size
> > + * and mask(i.e if slice size is 1024 and second slice is enabled
> > + * offset would be 1024)
> > + */
> > +static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
> > +					   u32 slice_size, u32
> > ddb_size)
> > +{
> 
> It might be worth just passing the mask + dev_priv to this function
> and
> let it get slice_size / ddb_size on its own to keep the logic simpler
> at
> the callsite.

The thing is that this is called only at single place and also
at call site I still do need slice_size for other calculations.
So I would still leave it there, as leaving only dev_priv here 
as parameter won't simply things at callsite as it will have to
get those parameters anyway.

> 
> > +	u32 offset = 0;
> > +
> > +	if (!dbuf_slice_mask)
> > +		return 0;
> > +
> > +	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
> > +
> > +	WARN_ON(offset >= ddb_size);
> > +	return offset;
> > +}
> > +
> >  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
> >  			      const struct intel_crtc_state
> > *crtc_state,
> >  			      const u64 total_data_rate,
> >  			      const int num_active)
> 
> I probably should have mentioned it on the previous patch, but most
> of
> these parameters are no longer needed now.

> 
> >  {
> > -	struct drm_atomic_state *state = crtc_state->uapi.state;
> > -	struct intel_atomic_state *intel_state =
> > to_intel_atomic_state(state);
> >  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> >  
> >  	WARN_ON(ddb_size == 0);
> > @@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  	if (INTEL_GEN(dev_priv) < 11)
> >  		return ddb_size - 4; /* 4 blocks for bypass path
> > allocation */
> >  
> > -	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > -	ddb_size /= 2;
> > -
> >  	return ddb_size;
> >  }
> >  
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state);
> > +
> >  static void
> >  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private
> > *dev_priv,
> >  				   const struct intel_crtc_state
> > *crtc_state,
> > @@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
> >  	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
> >  	u16 ddb_size;
> > +	u32 ddb_range_size;
> >  	u32 i;
> > +	u32 dbuf_slice_mask;
> > +	u32 active_pipes;
> > +	u32 offset;
> > +	u32 slice_size;
> > +	u32 total_slice_mask;
> > +	u32 start, end;
> >  
> >  	if (WARN_ON(!state) || !crtc_state->hw.active) {
> >  		alloc->start = 0;
> > @@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > -	if (intel_state->active_pipe_changes)
> > +	if (intel_state->active_pipe_changes) {
> >  		*num_active = hweight8(intel_state->active_pipes);
> > -	else
> > +		active_pipes = intel_state->active_pipes;
> > +	} else {
> >  		*num_active = hweight8(dev_priv->active_pipes);
> > +		active_pipes = dev_priv->active_pipes;
> > +	}
> 
> Might be slightly more intuitive to move the num_active assignment
> outside the 'if' as
> 
>         *num_active = hweight8(active_pipes);
> 
> Up to you; doesn't really matter.
> 
> >  
> >  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state,
> > total_data_rate,
> >  				      *num_active);
> >  
> > +	slice_size = ddb_size / INTEL_INFO(dev_priv)-
> > >num_supported_dbuf_slices;
> > +
> >  	/*
> >  	 * If the state doesn't change the active CRTC's or there is no
> >  	 * modeset request, then there's no need to recalculate;
> > @@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * Get allowed DBuf slices for correspondent pipe and platform.
> > +	 */
> > +	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
> > +						    active_pipes,
> > crtc_state);
> > +
> > +	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
> > +		      dbuf_slice_mask,
> > +		      for_pipe, active_pipes);
> > +
> > +	/*
> > +	 * Figure out at which DBuf slice we start, i.e if we start at
> > Dbuf S2
> > +	 * and slice size is 1024, the offset would be 1024
> > +	 */
> > +	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
> > +						 slice_size, ddb_size);
> > +
> > +	/*
> > +	 * Figure out total size of allowed DBuf slices, which is
> > basically
> > +	 * a number of allowed slices for that pipe multiplied by slice
> > size.
> > +	 * Inside of this
> > +	 * range ddb entries are still allocated in proportion to
> > display width.
> > +	 */
> > +	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
> > +
> >  	/*
> >  	 * Watermark/ddb requirement highly depends upon width of the
> >  	 * framebuffer, So instead of allocating DDB equally among
> > pipes
> >  	 * distribute DDB based on resolution/width of the display.
> >  	 */
> > +	total_slice_mask = dbuf_slice_mask;
> >  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state,
> > i) {
> >  		const struct drm_display_mode *adjusted_mode =
> >  			&crtc_state->hw.adjusted_mode;
> >  		enum pipe pipe = crtc->pipe;
> >  		int hdisplay, vdisplay;
> > +		u32 pipe_dbuf_slice_mask =
> > +					i915_possible_dbuf_slices(dev_p
> > riv,
> > +								  pipe,
> > +								  activ
> > e_pipes,
> > +								  crtc_
> > state);
> > +
> > +		if (!crtc_state->hw.active)
> > +			continue;
> 
> You might want to do this check before we go through the bother of
> executing i915_possible_dbuf_slices.
> 
> > +
> > +		/*
> > +		 * According to BSpec pipe can share one dbuf slice
> > with another
> > +		 * pipes or pipe can use multiple dbufs, in both cases
> > we
> > +		 * account for other pipes only if they have exactly
> > same mask.
> > +		 * However we need to account how many slices we should
> > enable
> > +		 * in total.
> > +		 */
> > +		total_slice_mask |= pipe_dbuf_slice_mask;
> >  
> > -		if (!crtc_state->hw.enable)
> > +		/*
> > +		 * Do not account pipes using other slice sets
> > +		 * luckily as of current BSpec slice sets do not
> > partially
> > +		 * intersect(pipes share either same one slice or same
> > slice set
> > +		 * i.e no partial intersection), so it is enough to
> > check for
> > +		 * equality for now.
> > +		 */
> > +		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
> >  			continue;
> >  
> >  		drm_mode_get_hv_timing(adjusted_mode, &hdisplay,
> > &vdisplay);
> > @@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  			pipe_width = hdisplay;
> >  	}
> >  
> > -	alloc->start = ddb_size * width_before_pipe / total_width;
> > -	alloc->end = ddb_size * (width_before_pipe + pipe_width) /
> > total_width;
> > +	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
> > +
> > +	start = ddb_range_size * width_before_pipe / total_width;
> > +	end = ddb_range_size * (width_before_pipe + pipe_width) /
> > total_width;
> 
> I found it a bit confusing that "total_slice_mask" is a mask of all
> active CRTCs, whereas total_width is only the width of the subset of
> active CRTCs that share our slice mask (i.e., different meanings of
> "total").  I think the logic here is correct, but some variable
> renaming
> might make it more obvious what's going on?
> 
> 
> > +
> > +	alloc->start = offset + start;
> > +	alloc->end = offset + end;
> > +
> > +	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
> > +		      alloc->start, alloc->end);
> > +	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
> > +		      intel_state->enabled_dbuf_slices_mask,
> > +		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
> >  }
> >  
> >  static int skl_compute_wm_params(const struct intel_crtc_state
> > *crtc_state,
> > @@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct
> > intel_crtc_state *crtc_state,
> >  	return mul_fixed16(downscale_w, downscale_h);
> >  }
> >  
> > +struct dbuf_slice_conf_entry {
> > +	u32 active_pipes;
> > +	u32 dbuf_mask[I915_MAX_PIPES];
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 12716
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
> 
> I believe it's legal to leave ending array elements out of
> definitions,
> in which case they'll just be 0.  So you can drop the fourth element
> of
> all these dbuf_mask arrays since that's more intuitive given these
> platforms only actually have three pipes.
> 
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 49255
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> 
>                                              ^^^^^^^^^^^
> I think this one is supposed to be S1 for pipe C.
> 
> 
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> > +};
> > +
> > +static u32 i915_find_pipe_conf(int pipe,
> > +			       u32 active_pipes,
> > +			       const struct dbuf_slice_conf_entry
> > *dbuf_slices,
> > +			       int size)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < size; i++) {
> > +		if (dbuf_slices[i].active_pipes == active_pipes)
> > +			return dbuf_slices[i].dbuf_mask[pipe];
> > +	}
> > +	return 0;
> > +}
> > +
> > +/*
> > + * This function finds an entry with same enabled pipe
> > configuration and
> > + * returns correspondent DBuf slice mask as stated in BSpec for
> > particular
> > + * platform.
> > + */
> > +static u32 icl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   icl_allowed_dbufs,
> > +				   ARRAY_SIZE(icl_allowed_dbufs));
> 
> Should we be handling the <88.8% pipe ratio stuff here?  I.e., an
> extra
> condition that if # pipes == 1 and the pipe ratio is less than 88.8%,
> return both S1 and S2?  Or will that come in a future patch (in which
> case a TODO/FIXME comment might be appropriate)?

I have added a comment in the code. Problem is that the whole
pipe_ratio thing turned out to be completely wrong(see BSpec bugs). 
So I completely excluded that stuff until that constraint is
fully clarified. 

> 
> 
> > +}
> > +
> > +static u32 tgl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   tgl_allowed_dbufs,
> > +				   ARRAY_SIZE(tgl_allowed_dbufs));
> > +}
> 
> Seems like these two functions (as currently written) are so simple
> that
> we can just invoke i915_find_pipe_conf directly in
> i915_possible_dbuf_slices.  Might also be worth considering using an
> empty table entry as a terminator rather than requiring than an
> explicit
> length be passed.
> 
> > +
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> 
> This can be static I think?
> 
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	if (IS_GEN(dev_priv, 11))
> > +		return icl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> > +	else if (IS_GEN(dev_priv, 12))
> > +		return tgl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> > +	/*
> > +	 * For anything else just return one slice yet.
> > +	 * Should be extended for other platforms.
> > +	 */
> > +	return DBUF_S1_BIT;
> > +}
> 
> None of the three functions above seem to actually use crtc_state, so
> I
> think we can drop that parameter.

I would still leave it, as once we get that BSpec "pipe_ratio" or
something else clarified most likely we'll still need crtc_state..


Stan
> 
> 
> > +
> >  static u64
> >  skl_plane_relative_data_rate(const struct intel_crtc_state
> > *crtc_state,
> >  			     const struct intel_plane_state
> > *plane_state,
> > -- 
> > 2.17.1
> > 
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-13 19:01   ` Matt Roper
@ 2019-12-16 15:07     ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-16 15:07 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: intel-gfx

On Fri, 2019-12-13 at 11:01 -0800, Matt Roper wrote:
> On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy wrote:
> > Start manipulating DBuf slices as a mask,
> > but not as a total number, as current approach
> > doesn't give us full control on all combinations
> > of slices, which we might need(like enabling S2
> > only can't enabled by setting enabled_slices=1).
> > 
> > Removed wrong code from intel_get_ddb_size as
> > it doesn't match to BSpec. For now still just
> > use DBuf slice until proper algorithm is implemented.
> > 
> > Other minor code refactoring to get prepared
> > for major DBuf assignment changes landed:
> > - As now enabled slices contain a mask
> >   we still need some value which should
> >   reflect how much DBuf slices are supported
> >   by the platform, now device info contains
> >   num_supported_dbuf_slices.
> > - Removed unneeded assertion as we are now
> >   manipulating slices in a more proper way.
> > 
> > v2: Start using enabled_slices in dev_priv
> > 
> > v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
> >     as this now sits in dev_priv independently.
> > 
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
> >  .../drm/i915/display/intel_display_power.c    | 100 ++++++++----
> > ------
> >  .../drm/i915/display/intel_display_power.h    |   5 +
> >  .../drm/i915/display/intel_display_types.h    |   2 +-
> >  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
> >  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
> >  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
> >  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
> >  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
> >  9 files changed, 84 insertions(+), 106 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index 0e09d0c23b1d..42a0ea540d4f 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct
> > intel_crtc *crtc,
> >  
> >  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
> >  
> > -	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> > +	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
> >  
> >  	if (INTEL_GEN(dev_priv) >= 11 &&
> > -	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
> > -		DRM_ERROR("mismatch in DBUF Slices (expected %u, got
> > %u)\n",
> > -			  dev_priv->enabled_dbuf_slices_num,
> > +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
> > +		DRM_ERROR("mismatch in DBUF Slices (expected %x, got
> > %x)\n",


Thanks for good comments, just as I wrote in previous patch, most of
the issues I've addressed in a recent series, for some which I didn't,
I will reply inline here with explanation.

> 
> Minor nitpick:  I'd write these with "0x%x" to make it more obvious
> to
> the person reading the message that the value is hex and thus a
> bitmask
> rather than a count.
> 
> > +			  dev_priv->enabled_dbuf_slices_mask,
> >  			  hw_enabled_slices);
> >  
> >  	/* planes */
> > @@ -14549,22 +14549,23 @@ static void
> > intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
> >  static void icl_dbuf_slice_pre_update(struct intel_atomic_state
> > *state)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > +	u8 slices_union = hw_enabled_slices | required_slices;
> >  
> >  	/* If 2nd DBuf slice required, enable it here */
> > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices >
> > hw_enabled_slices)
> > -		icl_dbuf_slices_update(dev_priv, required_slices);
> > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > hw_enabled_slices)
> 
> Should this be hw_enabled_slices != slices_union so that we only
> process
> it when we're adding new slices and not in cases where we're only
> going
> to be taking slices away?
> 
> > +		icl_dbuf_slices_update(dev_priv, slices_union);
> >  }
> >  
> >  static void icl_dbuf_slice_post_update(struct intel_atomic_state
> > *state)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> >  
> >  	/* If 2nd DBuf slice is no more required disable it */
> > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices <
> > hw_enabled_slices)
> > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > hw_enabled_slices)
> >  		icl_dbuf_slices_update(dev_priv, required_slices);
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c
> > b/drivers/gpu/drm/i915/display/intel_display_power.c
> > index b8983422a882..ba384a5315f8 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> > @@ -1031,15 +1031,6 @@ static bool
> > gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
> >  		(I915_READ(DC_STATE_EN) &
> > DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
> >  }
> >  
> > -static void gen9_assert_dbuf_enabled(struct drm_i915_private
> > *dev_priv)
> > -{
> > -	u32 tmp = I915_READ(DBUF_CTL);
> > -
> > -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> > -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> > -	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
> > -}
> > -
> >  static void gen9_disable_dc_states(struct drm_i915_private
> > *dev_priv)
> >  {
> >  	struct intel_cdclk_state cdclk_state = {};
> > @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct
> > drm_i915_private *dev_priv)
> >  	/* Can't read out voltage_level so can't use
> > intel_cdclk_changed() */
> >  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw,
> > &cdclk_state));
> >  
> > -	gen9_assert_dbuf_enabled(dev_priv);
> > -
> 
> I'm undecided on whether dropping the assertion completely is a good
> idea or not.  If I understand correctly, it was never meant to check
> that our own handling of the dbuf is correct (and it was added back
> when
> we only ever had a single dbuf slice on gen9), but rather than the
> DMC
> did the right thing when enabling/disabling the dbuf around DC state
> transitions.  As far as I know, the DMC has been pretty solid
> recently,
> but extra paranoia around firmware we don't directly control still
> seems
> like a good idea to me.

With this added we seem to get soem sporadical dmesg-warns on suspend
resume tests for ICL as this assertion now is not fully correct as we
now might not enable both DBuf slices as it was previsously hardcoded
in icl_dbuf_enable, now we only enable dbuf slices based on the actual
need. 
Also I think we already have similar check in verify_wm_state where is
also compares sw state and the actual hardware state.
> 
> 
> >  	if (IS_GEN9_LP(dev_priv))
> >  		bxt_verify_ddi_phy_power_wells(dev_priv);
> >  
> > @@ -4254,72 +4243,71 @@ static void gen9_dbuf_disable(struct
> > drm_i915_private *dev_priv)
> >  	intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
> >  }
> >  
> > -static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> > +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> 
> I don't see any new usage of this function outside this file.  I
> think
> we can keep this static?
> 
> >  {
> > -	if (INTEL_GEN(dev_priv) < 11)
> > -		return 1;
> > -	return 2;
> > +	return INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> > +}
> > +
> > +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv)
> 
> It looks like this never gets used outside this file either, so it
> could
> probably be static.  Or it's simple enough that we could just drop it
> completely and inline the icl_dbuf_slices_update() directly at the
> callsites.
> 
> > +{
> > +	const u8 hw_enabled_slices = dev_priv-
> > >enabled_dbuf_slices_mask;
> > +
> > +	icl_dbuf_slices_update(dev_priv, hw_enabled_slices);
> >  }
> >  
> >  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
> >  			    u8 req_slices)
> >  {
> > -	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	bool ret;
> > +	int i;
> > +	int max_slices = intel_dbuf_max_slices(dev_priv);
> >  
> > -	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> > +	if (hweight8(req_slices) > intel_dbuf_max_slices(dev_priv)) {
> >  		DRM_ERROR("Invalid number of dbuf slices requested\n");
> >  		return;
> >  	}
> >  
> > -	if (req_slices == hw_enabled_slices || req_slices == 0)
> > -		return;
> > +	DRM_DEBUG_KMS("Updating dbuf slices to %x\n", req_slices);
> 
> As noted above, I prefer "0x%x" to make it more obvious the number is
> a
> bitmask.  Up to you though.
> 
> >  
> > -	if (req_slices > hw_enabled_slices)
> > -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2,
> > true);
> > -	else
> > -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2,
> > false);
> > +	for (i = 0; i < max_slices; i++) {
> > +		int slice_bit = BIT(i);
> > +		bool slice_set = (slice_bit & req_slices) != 0;
> 
> Technically you could drop the "!= 0" part since anything non-zero
> will
> be evaluated as 'true.'  Doesn't really matter though.
> 
> > +
> > +		switch (slice_bit) {
> > +		case DBUF_S1_BIT:
> > +			intel_dbuf_slice_set(dev_priv,
> > +					     DBUF_CTL_S1,
> > +					     slice_set);
> > +			break;
> > +		case DBUF_S2_BIT:
> > +			intel_dbuf_slice_set(dev_priv,
> > +					     DBUF_CTL_S2,
> > +					     slice_set);
> > +			break;
> > +		default:
> > +			MISSING_CASE(slice_bit);
> > +		}
> 
> It might be worth parameterizing DBUF_CTL so that we can simplify
> code
> like this to just
> 
>         intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), slice_set);
> 
> or even just
> 
>         intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), req_slices &
> BIT(i))
> 
> as we do with other types of registers.  That will also future-proof
> a
> bit in case we ever get platforms with more dbuf slices.
> 
> > +	}
> >  
> > -	if (ret)
> > -		dev_priv->enabled_dbuf_slices_num = req_slices;
> > +	dev_priv->enabled_dbuf_slices_mask = req_slices;
> >  }
> >  
> >  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
> >  {
> > -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) |
> > DBUF_POWER_REQUEST);
> > -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) |
> > DBUF_POWER_REQUEST);
> > -	POSTING_READ(DBUF_CTL_S2);
> > -
> > -	udelay(10);
> > -
> > -	if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> > -	    !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> > -		DRM_ERROR("DBuf power enable timeout\n");
> > -	else
> > -		/*
> > -		 * FIXME: for now pretend that we only have 1 slice,
> > see
> > -		 * intel_enabled_dbuf_slices_num().
> > -		 */
> > -		dev_priv->enabled_dbuf_slices_num = 1;
> > +	/*
> > +	 * Just power up 1 slice, we will
> > +	 * figure out later which slices we have and what we need.
> > +	 */
> > +	dev_priv->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > +	icl_program_dbuf_slices(dev_priv);
> >  }
> >  
> >  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
> >  {
> > -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) &
> > ~DBUF_POWER_REQUEST);
> > -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) &
> > ~DBUF_POWER_REQUEST);
> > -	POSTING_READ(DBUF_CTL_S2);
> > -
> > -	udelay(10);
> > -
> > -	if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> > -	    (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> > -		DRM_ERROR("DBuf power disable timeout!\n");
> > -	else
> > -		/*
> > -		 * FIXME: for now pretend that the first slice is
> > always
> > -		 * enabled, see intel_enabled_dbuf_slices_num().
> > -		 */
> > -		dev_priv->enabled_dbuf_slices_num = 1;
> > +	/*
> > +	 * Disable all slices
> > +	 */
> > +	dev_priv->enabled_dbuf_slices_mask = 0;
> > +	icl_program_dbuf_slices(dev_priv);
> >  }
> >  
> >  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h
> > b/drivers/gpu/drm/i915/display/intel_display_power.h
> > index 1da04f3e0fb3..0d9f87607eac 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> > @@ -311,8 +311,13 @@ intel_display_power_put_async(struct
> > drm_i915_private *i915,
> >  	for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
> >  	     intel_display_power_put_async((i915), (domain), (wf)),
> > (wf) = 0)
> >  
> > +#define DBUF_S1_BIT			BIT(0)
> > +#define DBUF_S2_BIT			BIT(1)
> > +
> >  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
> >  			    u8 req_slices);
> > +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv);
> > +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv);
> >  
> >  void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >  			     bool override, unsigned int mask);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 70e65c2d525d..ba2e41a03051 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -518,7 +518,7 @@ struct intel_atomic_state {
> >  	struct skl_ddb_values wm_results;
> >  
> >  	/* Number of enabled DBuf slices */
> > -	u8 enabled_dbuf_slices_num;
> > +	u8 enabled_dbuf_slices_mask;
> >  
> >  	struct i915_sw_fence commit_ready;
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > b/drivers/gpu/drm/i915/i915_drv.h
> > index 7a2d9fa5a9a6..ec4b9e3cef79 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1210,7 +1210,7 @@ struct drm_i915_private {
> >  		bool distrust_bios_wm;
> >  	} wm;
> >  
> > -	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices
> > */
> > +	u8 enabled_dbuf_slices_mask; /* GEN11 has configurable 2 slices
> > */
> >  
> >  	struct dram_info {
> >  		bool valid;
> > diff --git a/drivers/gpu/drm/i915/i915_pci.c
> > b/drivers/gpu/drm/i915/i915_pci.c
> > index 877560b1031e..2068aac5ab6a 100644
> > --- a/drivers/gpu/drm/i915/i915_pci.c
> > +++ b/drivers/gpu/drm/i915/i915_pci.c
> > @@ -614,7 +614,8 @@ static const struct intel_device_info
> > intel_cherryview_info = {
> >  	.has_gt_uc = 1, \
> >  	.display.has_hdcp = 1, \
> >  	.display.has_ipc = 1, \
> > -	.ddb_size = 896
> > +	.ddb_size = 896, \
> > +	.num_supported_dbuf_slices = 1
> >  
> >  #define SKL_PLATFORM \
> >  	GEN9_FEATURES, \
> > @@ -649,6 +650,7 @@ static const struct intel_device_info
> > intel_skylake_gt4_info = {
> >  #define GEN9_LP_FEATURES \
> >  	GEN(9), \
> >  	.is_lp = 1, \
> > +	.num_supported_dbuf_slices = 1, \
> >  	.display.has_hotplug = 1, \
> >  	.engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0),
> > \
> >  	.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
> > @@ -737,6 +739,7 @@ static const struct intel_device_info
> > intel_coffeelake_gt3_info = {
> >  	GEN9_FEATURES, \
> >  	GEN(10), \
> >  	.ddb_size = 1024, \
> > +	.num_supported_dbuf_slices = 1, \
> 
> GEN10_FEATURES inherits everything from GEN9_FEATURES, so I think we
> can
> drop this one.
> 
> 
> >  	.display.has_dsc = 1, \
> >  	.has_coherent_ggtt = false, \
> >  	GLK_COLORS
> > @@ -773,6 +776,7 @@ static const struct intel_device_info
> > intel_cannonlake_info = {
> >  	}, \
> >  	GEN(11), \
> >  	.ddb_size = 2048, \
> > +	.num_supported_dbuf_slices = 2, \
> >  	.has_logical_ring_elsq = 1, \
> >  	.color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_device_info.h
> > b/drivers/gpu/drm/i915/intel_device_info.h
> > index 2725cb7fc169..7d4d122d2182 100644
> > --- a/drivers/gpu/drm/i915/intel_device_info.h
> > +++ b/drivers/gpu/drm/i915/intel_device_info.h
> > @@ -180,6 +180,7 @@ struct intel_device_info {
> >  	} display;
> >  
> >  	u16 ddb_size; /* in blocks */
> > +	u8 num_supported_dbuf_slices; /* number of DBuf slices */
> >  
> >  	/* Register offsets for the various display pipes and
> > transcoders */
> >  	int pipe_offsets[I915_MAX_TRANSCODERS];
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c
> > index c2510978ccdf..111bcafd6e4c 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3616,26 +3616,22 @@ bool ilk_disable_lp_wm(struct
> > drm_i915_private *dev_priv)
> >  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> >  }
> >  
> > -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private
> > *dev_priv)
> > +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private
> > *dev_priv)
> >  {
> > -	u8 enabled_dbuf_slices_num;
> > -
> > -	/* Slice 1 will always be enabled */
> > -	enabled_dbuf_slices_num = 1;
> > +	u8 enabled_slices_mask = 0;
> >  
> >  	/* Gen prior to GEN11 have only one DBuf slice */
> >  	if (INTEL_GEN(dev_priv) < 11)
> > -		return enabled_dbuf_slices_num;
> > +		return DBUF_S1_BIT;
> 
> Do we want to assume this or should we just read it anyway to make
> sure?
> As noted before, we might get into a disagreement with the DMC or
> something and it would be good to know how the hardware is actually
> set.

As I see the current code prefers to assume this for any platforms
< 11, which probably need somekind of different hw state readout.
I would prefer to leave it as is for previous platforms not to make
too many things messy at the same time.

Could be good idea to refactor this in subsequent patches though.

Stan

> 
> > -	/*
> > -	 * FIXME: for now we'll only ever use 1 slice; pretend that we
> > have
> > -	 * only that 1 slice enabled until we have a proper way for on-
> > demand
> > -	 * toggling of the second slice.
> > -	 */
> > -	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> > -		enabled_dbuf_slices_num++;
> > +	/* Check if second DBuf slice is enabled */
> > +	if (I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE)
> > +		enabled_slices_mask |= DBUF_S1_BIT;
> 
> You have the comment about the second slice before your check of the
> first slice...  I think you can just drop the comment in this case.
> 
> >  
> > -	return enabled_dbuf_slices_num;
> > +	if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> > +		enabled_slices_mask |= DBUF_S2_BIT;
> > +
> > +	return enabled_slices_mask;
> >  }
> >  
> >  /*
> > @@ -3843,8 +3839,6 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  {
> >  	struct drm_atomic_state *state = crtc_state->uapi.state;
> >  	struct intel_atomic_state *intel_state =
> > to_intel_atomic_state(state);
> > -	const struct drm_display_mode *adjusted_mode;
> > -	u64 total_data_bw;
> >  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> >  
> >  	WARN_ON(ddb_size == 0);
> > @@ -3852,23 +3846,8 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  	if (INTEL_GEN(dev_priv) < 11)
> >  		return ddb_size - 4; /* 4 blocks for bypass path
> > allocation */
> >  
> > -	adjusted_mode = &crtc_state->hw.adjusted_mode;
> > -	total_data_bw = total_data_rate *
> > drm_mode_vrefresh(adjusted_mode);
> > -
> > -	/*
> > -	 * 12GB/s is maximum BW supported by single DBuf slice.
> > -	 *
> > -	 * FIXME dbuf slice code is broken:
> > -	 * - must wait for planes to stop using the slice before
> > powering it off
> > -	 * - plane straddling both slices is illegal in multi-pipe
> > scenarios
> > -	 * - should validate we stay within the hw bandwidth limits
> > -	 */
> > -	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> > -		intel_state->enabled_dbuf_slices_num = 2;
> > -	} else {
> > -		intel_state->enabled_dbuf_slices_num = 1;
> > -		ddb_size /= 2;
> > -	}
> > +	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > +	ddb_size /= 2;
> >  
> >  	return ddb_size;
> >  }
> > @@ -4065,7 +4044,7 @@ void skl_pipe_ddb_get_hw_state(struct
> > intel_crtc *crtc,
> >  
> >  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
> >  {
> > -	dev_priv->enabled_dbuf_slices_num =
> > intel_enabled_dbuf_slices_num(dev_priv);
> > +	dev_priv->enabled_dbuf_slices_mask =
> > intel_enabled_dbuf_slices_mask(dev_priv);
> >  }
> >  
> >  /*
> > @@ -5204,7 +5183,7 @@ skl_compute_ddb(struct intel_atomic_state
> > *state)
> >  	struct intel_crtc *crtc;
> >  	int ret, i;
> >  
> > -	state->enabled_dbuf_slices_num = dev_priv-
> > >enabled_dbuf_slices_num;
> > +	state->enabled_dbuf_slices_mask = dev_priv-
> > >enabled_dbuf_slices_mask;
> >  
> >  	for_each_oldnew_intel_crtc_in_state(state, crtc,
> > old_crtc_state,
> >  					    new_crtc_state, i) {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.h
> > b/drivers/gpu/drm/i915/intel_pm.h
> > index a476f6c730e9..7a7494d1224f 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.h
> > +++ b/drivers/gpu/drm/i915/intel_pm.h
> > @@ -33,7 +33,7 @@ void g4x_wm_get_hw_state(struct drm_i915_private
> > *dev_priv);
> >  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
> >  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
> >  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> > -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private
> > *dev_priv);
> > +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private
> > *dev_priv);
> >  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
> >  			       struct skl_ddb_entry *ddb_y,
> >  			       struct skl_ddb_entry *ddb_uv);
> > -- 
> > 2.17.1
> > 
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly Stanislav Lisovskiy
  2019-12-13 19:01   ` Matt Roper
@ 2019-12-18 18:00   ` Ville Syrjälä
  2019-12-19  9:13     ` Lisovskiy, Stanislav
  1 sibling, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2019-12-18 18:00 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy wrote:
> Start manipulating DBuf slices as a mask,
> but not as a total number, as current approach
> doesn't give us full control on all combinations
> of slices, which we might need(like enabling S2
> only can't enabled by setting enabled_slices=1).
> 
> Removed wrong code from intel_get_ddb_size as
> it doesn't match to BSpec. For now still just
> use DBuf slice until proper algorithm is implemented.
> 
> Other minor code refactoring to get prepared
> for major DBuf assignment changes landed:
> - As now enabled slices contain a mask
>   we still need some value which should
>   reflect how much DBuf slices are supported
>   by the platform, now device info contains
>   num_supported_dbuf_slices.
> - Removed unneeded assertion as we are now
>   manipulating slices in a more proper way.
> 
> v2: Start using enabled_slices in dev_priv
> 
> v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
>     as this now sits in dev_priv independently.
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
>  .../drm/i915/display/intel_display_power.c    | 100 ++++++++----------
>  .../drm/i915/display/intel_display_power.h    |   5 +
>  .../drm/i915/display/intel_display_types.h    |   2 +-
>  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
>  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
>  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
>  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
>  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
>  9 files changed, 84 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0e09d0c23b1d..42a0ea540d4f 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  
>  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
>  
> -	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> +	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 11 &&
> -	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
> -		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
> -			  dev_priv->enabled_dbuf_slices_num,
> +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
> +		DRM_ERROR("mismatch in DBUF Slices (expected %x, got %x)\n",
> +			  dev_priv->enabled_dbuf_slices_mask,
>  			  hw_enabled_slices);
>  
>  	/* planes */
> @@ -14549,22 +14549,23 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
>  static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> +	u8 required_slices = state->enabled_dbuf_slices_mask;
> +	u8 slices_union = hw_enabled_slices | required_slices;
>  
>  	/* If 2nd DBuf slice required, enable it here */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)
> +		icl_dbuf_slices_update(dev_priv, slices_union);
>  }
>  
>  static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> +	u8 required_slices = state->enabled_dbuf_slices_mask;
>  
>  	/* If 2nd DBuf slice is no more required disable it */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices != hw_enabled_slices)

I would rename the variables to old_slices vs. new_slices or something
like that. Would match the common naming pattern we use extensively all
over.

>  		icl_dbuf_slices_update(dev_priv, required_slices);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index b8983422a882..ba384a5315f8 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -1031,15 +1031,6 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
>  		(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
>  }
>  
> -static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
> -{
> -	u32 tmp = I915_READ(DBUF_CTL);
> -
> -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> -	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
> -}
> -
>  static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_cdclk_state cdclk_state = {};
> @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
>  	/* Can't read out voltage_level so can't use intel_cdclk_changed() */
>  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw, &cdclk_state));
>  
> -	gen9_assert_dbuf_enabled(dev_priv);

Why are you removing these? I think you still left the code in place to
power up the first slice uncoditionally. Also not sure if DMC just
powers that sucker up regardless. I think we should try it and if DMC
isn't insane we should turn all the slices off when we don't need them.

> -
>  	if (IS_GEN9_LP(dev_priv))
>  		bxt_verify_ddi_phy_power_wells(dev_priv);
>  
> @@ -4254,72 +4243,71 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
>  	intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
>  }
>  
> -static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
>  {
> -	if (INTEL_GEN(dev_priv) < 11)
> -		return 1;
> -	return 2;
> +	return INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> +}

I don't see this being used anywhere outside this file in this patch.
So why is it being made non-static? Also it's rather redundant now
and could just be inlined into the single caller we have left.

> +
> +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv)
> +{
> +	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;

This whole function is just a one line wrapper now that does nothing
special. So I would not even add it.

> +
> +	icl_dbuf_slices_update(dev_priv, hw_enabled_slices);
>  }
>  
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices)
>  {
> -	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	bool ret;
> +	int i;
> +	int max_slices = intel_dbuf_max_slices(dev_priv);
>  
> -	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> +	if (hweight8(req_slices) > intel_dbuf_max_slices(dev_priv)) {

You already have max_slices in a variable.

>  		DRM_ERROR("Invalid number of dbuf slices requested\n");

Can't happen unless we messed up in state calculation. We should
drop the check or just WARN and keep going. But that's probably
material for another patch.

>  		return;
>  	}
>  
> -	if (req_slices == hw_enabled_slices || req_slices == 0)
> -		return;
> +	DRM_DEBUG_KMS("Updating dbuf slices to %x\n", req_slices);

Pls use 0x%x so it's obvious it's hex.

>  
> -	if (req_slices > hw_enabled_slices)
> -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
> -	else
> -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
> +	for (i = 0; i < max_slices; i++) {
> +		int slice_bit = BIT(i);
> +		bool slice_set = (slice_bit & req_slices) != 0;
> +
> +		switch (slice_bit) {
> +		case DBUF_S1_BIT:
> +			intel_dbuf_slice_set(dev_priv,
> +					     DBUF_CTL_S1,
> +					     slice_set);
> +			break;
> +		case DBUF_S2_BIT:
> +			intel_dbuf_slice_set(dev_priv,
> +					     DBUF_CTL_S2,
> +					     slice_set);
> +			break;
> +		default:
> +			MISSING_CASE(slice_bit);
> +		}

Still can be just:
	intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), 
			     req_slices & BIT(i));


> +	}
>  
> -	if (ret)
> -		dev_priv->enabled_dbuf_slices_num = req_slices;
> +	dev_priv->enabled_dbuf_slices_mask = req_slices;
>  }
>  
>  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
>  {
> -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST);
> -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST);
> -	POSTING_READ(DBUF_CTL_S2);
> -
> -	udelay(10);
> -
> -	if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> -	    !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> -		DRM_ERROR("DBuf power enable timeout\n");
> -	else
> -		/*
> -		 * FIXME: for now pretend that we only have 1 slice, see
> -		 * intel_enabled_dbuf_slices_num().
> -		 */
> -		dev_priv->enabled_dbuf_slices_num = 1;
> +	/*
> +	 * Just power up 1 slice, we will
> +	 * figure out later which slices we have and what we need.
> +	 */
> +	dev_priv->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> +	icl_program_dbuf_slices(dev_priv);
>  }
>  
>  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
>  {
> -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST);
> -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST);
> -	POSTING_READ(DBUF_CTL_S2);
> -
> -	udelay(10);
> -
> -	if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> -	    (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> -		DRM_ERROR("DBuf power disable timeout!\n");
> -	else
> -		/*
> -		 * FIXME: for now pretend that the first slice is always
> -		 * enabled, see intel_enabled_dbuf_slices_num().
> -		 */
> -		dev_priv->enabled_dbuf_slices_num = 1;
> +	/*
> +	 * Disable all slices
> +	 */
> +	dev_priv->enabled_dbuf_slices_mask = 0;
> +	icl_program_dbuf_slices(dev_priv);
>  }
>  
>  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
> index 1da04f3e0fb3..0d9f87607eac 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> @@ -311,8 +311,13 @@ intel_display_power_put_async(struct drm_i915_private *i915,
>  	for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
>  	     intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
>  
> +#define DBUF_S1_BIT			BIT(0)
> +#define DBUF_S2_BIT			BIT(1)
> +
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices);
> +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv);
> +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv);
>  
>  void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>  			     bool override, unsigned int mask);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 70e65c2d525d..ba2e41a03051 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -518,7 +518,7 @@ struct intel_atomic_state {
>  	struct skl_ddb_values wm_results;
>  
>  	/* Number of enabled DBuf slices */
> -	u8 enabled_dbuf_slices_num;
> +	u8 enabled_dbuf_slices_mask;
>  
>  	struct i915_sw_fence commit_ready;
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7a2d9fa5a9a6..ec4b9e3cef79 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1210,7 +1210,7 @@ struct drm_i915_private {
>  		bool distrust_bios_wm;
>  	} wm;
>  
> -	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */
> +	u8 enabled_dbuf_slices_mask; /* GEN11 has configurable 2 slices */
>  
>  	struct dram_info {
>  		bool valid;
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> index 877560b1031e..2068aac5ab6a 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -614,7 +614,8 @@ static const struct intel_device_info intel_cherryview_info = {
>  	.has_gt_uc = 1, \
>  	.display.has_hdcp = 1, \
>  	.display.has_ipc = 1, \
> -	.ddb_size = 896
> +	.ddb_size = 896, \
> +	.num_supported_dbuf_slices = 1
>  
>  #define SKL_PLATFORM \
>  	GEN9_FEATURES, \
> @@ -649,6 +650,7 @@ static const struct intel_device_info intel_skylake_gt4_info = {
>  #define GEN9_LP_FEATURES \
>  	GEN(9), \
>  	.is_lp = 1, \
> +	.num_supported_dbuf_slices = 1, \
>  	.display.has_hotplug = 1, \
>  	.engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \
>  	.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
> @@ -737,6 +739,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info = {
>  	GEN9_FEATURES, \
>  	GEN(10), \
>  	.ddb_size = 1024, \
> +	.num_supported_dbuf_slices = 1, \
>  	.display.has_dsc = 1, \
>  	.has_coherent_ggtt = false, \
>  	GLK_COLORS
> @@ -773,6 +776,7 @@ static const struct intel_device_info intel_cannonlake_info = {
>  	}, \
>  	GEN(11), \
>  	.ddb_size = 2048, \
> +	.num_supported_dbuf_slices = 2, \
>  	.has_logical_ring_elsq = 1, \
>  	.color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
>  
> diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h
> index 2725cb7fc169..7d4d122d2182 100644
> --- a/drivers/gpu/drm/i915/intel_device_info.h
> +++ b/drivers/gpu/drm/i915/intel_device_info.h
> @@ -180,6 +180,7 @@ struct intel_device_info {
>  	} display;
>  
>  	u16 ddb_size; /* in blocks */
> +	u8 num_supported_dbuf_slices; /* number of DBuf slices */

Redundant comment.

>  
>  	/* Register offsets for the various display pipes and transcoders */
>  	int pipe_offsets[I915_MAX_TRANSCODERS];
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c2510978ccdf..111bcafd6e4c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3616,26 +3616,22 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
>  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
>  }
>  
> -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
> +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv)
>  {
> -	u8 enabled_dbuf_slices_num;
> -
> -	/* Slice 1 will always be enabled */
> -	enabled_dbuf_slices_num = 1;
> +	u8 enabled_slices_mask = 0;
>  
>  	/* Gen prior to GEN11 have only one DBuf slice */
>  	if (INTEL_GEN(dev_priv) < 11)
> -		return enabled_dbuf_slices_num;
> +		return DBUF_S1_BIT;
>  
> -	/*
> -	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
> -	 * only that 1 slice enabled until we have a proper way for on-demand
> -	 * toggling of the second slice.
> -	 */
> -	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> -		enabled_dbuf_slices_num++;
> +	/* Check if second DBuf slice is enabled */
> +	if (I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE)
> +		enabled_slices_mask |= DBUF_S1_BIT;
>  
> -	return enabled_dbuf_slices_num;
> +	if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> +		enabled_slices_mask |= DBUF_S2_BIT;

With parametrized DBUF_CTL this could also just loop over the slices.

> +
> +	return enabled_slices_mask;
>  }
>  
>  /*
> @@ -3843,8 +3839,6 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  {
>  	struct drm_atomic_state *state = crtc_state->uapi.state;
>  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
> -	const struct drm_display_mode *adjusted_mode;
> -	u64 total_data_bw;
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
>  
>  	WARN_ON(ddb_size == 0);
> @@ -3852,23 +3846,8 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	if (INTEL_GEN(dev_priv) < 11)
>  		return ddb_size - 4; /* 4 blocks for bypass path allocation */
>  
> -	adjusted_mode = &crtc_state->hw.adjusted_mode;
> -	total_data_bw = total_data_rate * drm_mode_vrefresh(adjusted_mode);
> -
> -	/*
> -	 * 12GB/s is maximum BW supported by single DBuf slice.
> -	 *
> -	 * FIXME dbuf slice code is broken:
> -	 * - must wait for planes to stop using the slice before powering it off
> -	 * - plane straddling both slices is illegal in multi-pipe scenarios
> -	 * - should validate we stay within the hw bandwidth limits
> -	 */
> -	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> -		intel_state->enabled_dbuf_slices_num = 2;
> -	} else {
> -		intel_state->enabled_dbuf_slices_num = 1;
> -		ddb_size /= 2;
> -	}

Aren't we left with loads of pointless function arguments now?

> +	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> +	ddb_size /= 2;
>  
>  	return ddb_size;
>  }
> @@ -4065,7 +4044,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  
>  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
>  {
> -	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);
> +	dev_priv->enabled_dbuf_slices_mask = intel_enabled_dbuf_slices_mask(dev_priv);
>  }
>  
>  /*
> @@ -5204,7 +5183,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
>  	struct intel_crtc *crtc;
>  	int ret, i;
>  
> -	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
> +	state->enabled_dbuf_slices_mask = dev_priv->enabled_dbuf_slices_mask;
>  
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
> diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
> index a476f6c730e9..7a7494d1224f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.h
> +++ b/drivers/gpu/drm/i915/intel_pm.h
> @@ -33,7 +33,7 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
> +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *dev_priv);
>  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  			       struct skl_ddb_entry *ddb_y,
>  			       struct skl_ddb_entry *ddb_uv);
> -- 
> 2.17.1

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
  2019-12-13 16:59   ` Matt Roper
@ 2019-12-18 18:01   ` Ville Syrjälä
  1 sibling, 0 replies; 23+ messages in thread
From: Ville Syrjälä @ 2019-12-18 18:01 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:25PM +0200, Stanislav Lisovskiy wrote:
> Current consensus that it is redundant as
> we already have skl_ddb_values struct out there,
> also this struct contains only single member
> which makes it unnecessary.
> 
> v2: As dirty_pipes soon going to be nuked away
>     from skl_ddb_values, evacuating enabled_slices
>     to safer in dev_priv.
> 
> v3: Changed "enabled_slices" to be "enabled_dbuf_slices_num"
>     (Matt Roper)
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  | 16 +++----
>  .../drm/i915/display/intel_display_power.c    |  8 ++--
>  .../drm/i915/display/intel_display_types.h    |  3 ++
>  drivers/gpu/drm/i915/i915_drv.h               |  7 +--
>  drivers/gpu/drm/i915/intel_pm.c               | 44 +++++++++----------
>  drivers/gpu/drm/i915/intel_pm.h               |  6 +--
>  6 files changed, 39 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0f37f1d2026d..62e33bca7014 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -13339,14 +13339,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  	struct skl_hw_state {
>  		struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
>  		struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
> -		struct skl_ddb_allocation ddb;
>  		struct skl_pipe_wm wm;
>  	} *hw;
> -	struct skl_ddb_allocation *sw_ddb;
>  	struct skl_pipe_wm *sw_wm;
>  	struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
>  	const enum pipe pipe = crtc->pipe;
>  	int plane, level, max_level = ilk_wm_max_level(dev_priv);
> +	u8 hw_enabled_slices;
>  
>  	if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active)
>  		return;
> @@ -13360,14 +13359,13 @@ static void verify_wm_state(struct intel_crtc *crtc,
>  
>  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
>  
> -	skl_ddb_get_hw_state(dev_priv, &hw->ddb);
> -	sw_ddb = &dev_priv->wm.skl_hw.ddb;
> +	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 11 &&
> -	    hw->ddb.enabled_slices != sw_ddb->enabled_slices)
> +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
>  		DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
> -			  sw_ddb->enabled_slices,
> -			  hw->ddb.enabled_slices);
> +			  dev_priv->enabled_dbuf_slices_num,
> +			  hw_enabled_slices);
>  
>  	/* planes */
>  	for_each_universal_plane(dev_priv, pipe, plane) {
> @@ -14553,8 +14551,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
> -	u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
> -	u8 required_slices = state->wm_results.ddb.enabled_slices;
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
>  	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
>  	u8 dirty_pipes = 0;
>  	int i;
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index 0b3dd2a3b94d..b8983422a882 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -4264,7 +4264,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices)
>  {
> -	const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
> +	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
>  	bool ret;
>  
>  	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> @@ -4281,7 +4281,7 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
>  
>  	if (ret)
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = req_slices;
> +		dev_priv->enabled_dbuf_slices_num = req_slices;
>  }
>  
>  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
> @@ -4300,7 +4300,7 @@ static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
>  		 * FIXME: for now pretend that we only have 1 slice, see
>  		 * intel_enabled_dbuf_slices_num().
>  		 */
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
> +		dev_priv->enabled_dbuf_slices_num = 1;
>  }
>  
>  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
> @@ -4319,7 +4319,7 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
>  		 * FIXME: for now pretend that the first slice is always
>  		 * enabled, see intel_enabled_dbuf_slices_num().
>  		 */
> -		dev_priv->wm.skl_hw.ddb.enabled_slices = 1;
> +		dev_priv->enabled_dbuf_slices_num = 1;
>  }
>  
>  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 83ea04149b77..70e65c2d525d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -517,6 +517,9 @@ struct intel_atomic_state {
>  	/* Gen9+ only */
>  	struct skl_ddb_values wm_results;
>  
> +	/* Number of enabled DBuf slices */
> +	u8 enabled_dbuf_slices_num;

Usual pattern would be "num_enabled_dbuf_slices". It would even match
your comment 100% and thus the comment is entirely redundant.

> +
>  	struct i915_sw_fence commit_ready;
>  
>  	struct llist_node freed;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 0781b6326b8c..7a2d9fa5a9a6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -798,13 +798,8 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
>  	return false;
>  }
>  
> -struct skl_ddb_allocation {
> -	u8 enabled_slices; /* GEN11 has configurable 2 slices */
> -};
> -
>  struct skl_ddb_values {
>  	unsigned dirty_pipes;
> -	struct skl_ddb_allocation ddb;
>  };
>  
>  struct skl_wm_level {
> @@ -1215,6 +1210,8 @@ struct drm_i915_private {
>  		bool distrust_bios_wm;
>  	} wm;
>  
> +	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices */

That comment is going to become stale immediately.

> +
>  	struct dram_info {
>  		bool valid;
>  		bool is_16gb_dimm;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ccbbdf4a6aab..c2510978ccdf 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3616,16 +3616,16 @@ bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
>  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
>  }
>  
> -static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
> +u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
>  {
> -	u8 enabled_slices;
> +	u8 enabled_dbuf_slices_num;
>  
>  	/* Slice 1 will always be enabled */
> -	enabled_slices = 1;
> +	enabled_dbuf_slices_num = 1;
>  
>  	/* Gen prior to GEN11 have only one DBuf slice */
>  	if (INTEL_GEN(dev_priv) < 11)
> -		return enabled_slices;
> +		return enabled_dbuf_slices_num;
>  
>  	/*
>  	 * FIXME: for now we'll only ever use 1 slice; pretend that we have
> @@ -3633,9 +3633,9 @@ static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv)
>  	 * toggling of the second slice.
>  	 */
>  	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> -		enabled_slices++;
> +		enabled_dbuf_slices_num++;
>  
> -	return enabled_slices;
> +	return enabled_dbuf_slices_num;
>  }
>  
>  /*
> @@ -3839,9 +3839,10 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
>  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  			      const struct intel_crtc_state *crtc_state,
>  			      const u64 total_data_rate,
> -			      const int num_active,
> -			      struct skl_ddb_allocation *ddb)
> +			      const int num_active)
>  {
> +	struct drm_atomic_state *state = crtc_state->uapi.state;
> +	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	const struct drm_display_mode *adjusted_mode;
>  	u64 total_data_bw;
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> @@ -3863,9 +3864,9 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	 * - should validate we stay within the hw bandwidth limits
>  	 */
>  	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> -		ddb->enabled_slices = 2;
> +		intel_state->enabled_dbuf_slices_num = 2;
>  	} else {
> -		ddb->enabled_slices = 1;
> +		intel_state->enabled_dbuf_slices_num = 1;
>  		ddb_size /= 2;
>  	}
>  
> @@ -3876,7 +3877,6 @@ static void
>  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  				   const struct intel_crtc_state *crtc_state,
>  				   const u64 total_data_rate,
> -				   struct skl_ddb_allocation *ddb,
>  				   struct skl_ddb_entry *alloc, /* out */
>  				   int *num_active /* out */)
>  {
> @@ -3902,7 +3902,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		*num_active = hweight8(dev_priv->active_pipes);
>  
>  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
> -				      *num_active, ddb);
> +				      *num_active);
>  
>  	/*
>  	 * If the state doesn't change the active CRTC's or there is no
> @@ -4063,10 +4063,9 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  	intel_display_power_put(dev_priv, power_domain, wakeref);
>  }
>  
> -void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> -			  struct skl_ddb_allocation *ddb /* out */)
> +void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
>  {
> -	ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> +	dev_priv->enabled_dbuf_slices_num = intel_enabled_dbuf_slices_num(dev_priv);
>  }
>  
>  /*
> @@ -4243,8 +4242,7 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state,
>  }
>  
>  static int
> -skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
> -		      struct skl_ddb_allocation *ddb /* out */)
> +skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state)
>  {
>  	struct drm_atomic_state *state = crtc_state->uapi.state;
>  	struct drm_crtc *crtc = crtc_state->uapi.crtc;
> @@ -4286,7 +4284,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
>  
>  
>  	skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state, total_data_rate,
> -					   ddb, alloc, &num_active);
> +					   alloc, &num_active);
>  	alloc_size = skl_ddb_entry_size(alloc);
>  	if (alloc_size == 0)
>  		return 0;
> @@ -5200,18 +5198,17 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
>  static int
>  skl_compute_ddb(struct intel_atomic_state *state)
>  {
> -	const struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> -	struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc_state *old_crtc_state;
>  	struct intel_crtc_state *new_crtc_state;
>  	struct intel_crtc *crtc;
>  	int ret, i;
>  
> -	memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
> +	state->enabled_dbuf_slices_num = dev_priv->enabled_dbuf_slices_num;
>  
>  	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
>  					    new_crtc_state, i) {
> -		ret = skl_allocate_pipe_ddb(new_crtc_state, ddb);
> +		ret = skl_allocate_pipe_ddb(new_crtc_state);
>  		if (ret)
>  			return ret;
>  
> @@ -5683,11 +5680,10 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
>  {
>  	struct skl_ddb_values *hw = &dev_priv->wm.skl_hw;
> -	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *crtc_state;
>  
> -	skl_ddb_get_hw_state(dev_priv, ddb);
> +	skl_ddb_get_hw_state(dev_priv);
>  	for_each_intel_crtc(&dev_priv->drm, crtc) {
>  		crtc_state = to_intel_crtc_state(crtc->base.state);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
> index c06c6a846d9a..a476f6c730e9 100644
> --- a/drivers/gpu/drm/i915/intel_pm.h
> +++ b/drivers/gpu/drm/i915/intel_pm.h
> @@ -17,8 +17,8 @@ struct intel_atomic_state;
>  struct intel_crtc;
>  struct intel_crtc_state;
>  struct intel_plane;
> -struct skl_ddb_allocation;
>  struct skl_ddb_entry;
> +struct skl_ddb_values;
>  struct skl_pipe_wm;
>  struct skl_wm_level;
>  
> @@ -33,11 +33,11 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> +u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv);
>  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  			       struct skl_ddb_entry *ddb_y,
>  			       struct skl_ddb_entry *ddb_uv);
> -void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> -			  struct skl_ddb_allocation *ddb /* out */);
> +void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv);
>  void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
>  			      struct skl_pipe_wm *out);
>  void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
> -- 
> 2.17.1

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy
  2019-12-14  0:52   ` Matt Roper
@ 2019-12-18 18:05   ` Ville Syrjälä
  2019-12-19 11:58     ` Lisovskiy, Stanislav
  2019-12-19 12:02     ` Lisovskiy, Stanislav
  1 sibling, 2 replies; 23+ messages in thread
From: Ville Syrjälä @ 2019-12-18 18:05 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:28PM +0200, Stanislav Lisovskiy wrote:
> Added proper DBuf slice mapping to correspondent
> pipes, depending on pipe configuration as stated
> in BSpec.
> 
> v2:
>     - Remove unneeded braces
>     - Stop using macro for DBuf assignments as
>       it seems to reduce readability.
> 
> v3: Start using enabled slices mask in dev_priv
> 
> v4: Renamed "enabled_slices" used in dev_priv
>     to "enabled_dbuf_slices_mask"(Matt Roper)
> 
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 226 ++++++++++++++++++++++++++++++--
>  1 file changed, 216 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 111bcafd6e4c..a13052b2c2ef 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
>  	return true;
>  }
>  
> +/*
> + * Calculate initial DBuf slice offset, based on slice size
> + * and mask(i.e if slice size is 1024 and second slice is enabled
> + * offset would be 1024)
> + */
> +static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
> +					   u32 slice_size, u32 ddb_size)

s/u32/unsigned int/ or something. No point in using sized types when
we're not dealing with some thing that is actually that size.

> +{
> +	u32 offset = 0;
> +
> +	if (!dbuf_slice_mask)
> +		return 0;
> +
> +	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
> +
> +	WARN_ON(offset >= ddb_size);
> +	return offset;
> +}
> +
>  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  			      const struct intel_crtc_state *crtc_state,
>  			      const u64 total_data_rate,
>  			      const int num_active)
>  {
> -	struct drm_atomic_state *state = crtc_state->uapi.state;
> -	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
>  
>  	WARN_ON(ddb_size == 0);
> @@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
>  	if (INTEL_GEN(dev_priv) < 11)
>  		return ddb_size - 4; /* 4 blocks for bypass path allocation */
>  
> -	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> -	ddb_size /= 2;
> -
>  	return ddb_size;
>  }
>  
> +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> +			      int pipe, u32 active_pipes,
> +			      const struct intel_crtc_state *crtc_state);
> +
>  static void
>  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  				   const struct intel_crtc_state *crtc_state,
> @@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
>  	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
>  	u16 ddb_size;
> +	u32 ddb_range_size;
>  	u32 i;
> +	u32 dbuf_slice_mask;
> +	u32 active_pipes;
> +	u32 offset;
> +	u32 slice_size;
> +	u32 total_slice_mask;
> +	u32 start, end;
>  
>  	if (WARN_ON(!state) || !crtc_state->hw.active) {
>  		alloc->start = 0;
> @@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	if (intel_state->active_pipe_changes)
> +	if (intel_state->active_pipe_changes) {
>  		*num_active = hweight8(intel_state->active_pipes);
> -	else
> +		active_pipes = intel_state->active_pipes;
> +	} else {
>  		*num_active = hweight8(dev_priv->active_pipes);
> +		active_pipes = dev_priv->active_pipes;
> +	}
>  
>  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
>  				      *num_active);
>  
> +	slice_size = ddb_size / INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> +
>  	/*
>  	 * If the state doesn't change the active CRTC's or there is no
>  	 * modeset request, then there's no need to recalculate;
> @@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> +	/*
> +	 * Get allowed DBuf slices for correspondent pipe and platform.
> +	 */
> +	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
> +						    active_pipes, crtc_state);
> +
> +	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
> +		      dbuf_slice_mask,
> +		      for_pipe, active_pipes);
> +
> +	/*
> +	 * Figure out at which DBuf slice we start, i.e if we start at Dbuf S2
> +	 * and slice size is 1024, the offset would be 1024
> +	 */
> +	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
> +						 slice_size, ddb_size);
> +
> +	/*
> +	 * Figure out total size of allowed DBuf slices, which is basically
> +	 * a number of allowed slices for that pipe multiplied by slice size.
> +	 * Inside of this
> +	 * range ddb entries are still allocated in proportion to display width.
> +	 */
> +	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
> +
>  	/*
>  	 * Watermark/ddb requirement highly depends upon width of the
>  	 * framebuffer, So instead of allocating DDB equally among pipes
>  	 * distribute DDB based on resolution/width of the display.
>  	 */
> +	total_slice_mask = dbuf_slice_mask;
>  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
>  		const struct drm_display_mode *adjusted_mode =
>  			&crtc_state->hw.adjusted_mode;
>  		enum pipe pipe = crtc->pipe;
>  		int hdisplay, vdisplay;
> +		u32 pipe_dbuf_slice_mask =
> +					i915_possible_dbuf_slices(dev_priv,
> +								  pipe,
> +								  active_pipes,
> +								  crtc_state);
> +
> +		if (!crtc_state->hw.active)
> +			continue;
> +
> +		/*
> +		 * According to BSpec pipe can share one dbuf slice with another
> +		 * pipes or pipe can use multiple dbufs, in both cases we
> +		 * account for other pipes only if they have exactly same mask.
> +		 * However we need to account how many slices we should enable
> +		 * in total.
> +		 */
> +		total_slice_mask |= pipe_dbuf_slice_mask;
>  
> -		if (!crtc_state->hw.enable)
> +		/*
> +		 * Do not account pipes using other slice sets
> +		 * luckily as of current BSpec slice sets do not partially
> +		 * intersect(pipes share either same one slice or same slice set
> +		 * i.e no partial intersection), so it is enough to check for
> +		 * equality for now.
> +		 */
> +		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
>  			continue;
>  
>  		drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
> @@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
>  			pipe_width = hdisplay;
>  	}
>  
> -	alloc->start = ddb_size * width_before_pipe / total_width;
> -	alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width;
> +	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
> +
> +	start = ddb_range_size * width_before_pipe / total_width;
> +	end = ddb_range_size * (width_before_pipe + pipe_width) / total_width;
> +
> +	alloc->start = offset + start;
> +	alloc->end = offset + end;
> +
> +	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
> +		      alloc->start, alloc->end);
> +	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
> +		      intel_state->enabled_dbuf_slices_mask,
> +		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
>  }

That function really is quite the monster. Probably needs to be split up
into sensible chunks... later.

>  
>  static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
> @@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state,
>  	return mul_fixed16(downscale_w, downscale_h);
>  }
>  
> +struct dbuf_slice_conf_entry {
> +	u32 active_pipes;
> +	u32 dbuf_mask[I915_MAX_PIPES];

u8 will do for everything.

> +};
> +
> +/*
> + * Table taken from Bspec 12716
> + * Pipes do have some preferred DBuf slice affinity,
> + * plus there are some hardcoded requirements on how
> + * those should be distributed for multipipe scenarios.
> + * For more DBuf slices algorithm can get even more messy
> + * and less readable, so decided to use a table almost
> + * as is from BSpec itself - that way it is at least easier
> + * to compare, change and check.
> + */
> +static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
> +	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },

Still don't like that DBUF_S1_BIT. I still think it should be an
enum dbuf_slice + explcit BIT(DBUF_S1) where needed.

And please use named initializers instead of sprinkling zeroes.
IMO this should just look something like:

	{ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
	  .dbuf_slices = { [PIPE_A] = BIT(DBUF_S1),
	  		   [PIPE_B] = BIT(DBUF_S2),
			 },
	},

> +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
> +	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
> +};
> +
> +/*
> + * Table taken from Bspec 49255
> + * Pipes do have some preferred DBuf slice affinity,
> + * plus there are some hardcoded requirements on how
> + * those should be distributed for multipipe scenarios.
> + * For more DBuf slices algorithm can get even more messy
> + * and less readable, so decided to use a table almost
> + * as is from BSpec itself - that way it is at least easier
> + * to compare, change and check.
> + */
> +static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
> +	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
> +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
> +	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT } },

I believe pipe C should use S1 here.

> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
> +	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> +};
> +
> +static u32 i915_find_pipe_conf(int pipe,

enum pipe pipe

> +			       u32 active_pipes,
> +			       const struct dbuf_slice_conf_entry *dbuf_slices,
> +			       int size)

Could just add a sentinel to the end of the arrays and avoid this
'size' stuff.

The function name is still very confusing. icl_compute_dbuf_slices()
or something perhaps. Or even without a prefix since it's static
anyway.

> +{
> +	int i;
> +
> +	for (i = 0; i < size; i++) {
> +		if (dbuf_slices[i].active_pipes == active_pipes)
> +			return dbuf_slices[i].dbuf_mask[pipe];
> +	}
> +	return 0;
> +}
> +
> +/*
> + * This function finds an entry with same enabled pipe configuration and
> + * returns correspondent DBuf slice mask as stated in BSpec for particular
> + * platform.
> + */
> +static u32 icl_possible_dbuf_slices(int pipe,
> +				    u32 active_pipes,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	return i915_find_pipe_conf(pipe, active_pipes,
> +				   icl_allowed_dbufs,
> +				   ARRAY_SIZE(icl_allowed_dbufs));
> +}
> +
> +static u32 tgl_possible_dbuf_slices(int pipe,
> +				    u32 active_pipes,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	return i915_find_pipe_conf(pipe, active_pipes,
> +				   tgl_allowed_dbufs,
> +				   ARRAY_SIZE(tgl_allowed_dbufs));
> +}

These wrappers aren't really doing anything for us.

> +
> +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,

dev_priv and pipe are redundant parameters. Both
can be extracted from crtc_state. I would put crtc_state as the first
parameter. Matches common practice more closely.

s/i915/skl/ in the function name.

> +			      int pipe, u32 active_pipes,
> +			      const struct intel_crtc_state *crtc_state)
> +{
> +	if (IS_GEN(dev_priv, 11))
> +		return icl_possible_dbuf_slices(pipe,
> +						active_pipes,
> +						crtc_state);
> +	else if (IS_GEN(dev_priv, 12))
> +		return tgl_possible_dbuf_slices(pipe,
> +						active_pipes,
> +						crtc_state);

The established convention is to go from new platforms
to old platforms, if possible.

> +	/*
> +	 * For anything else just return one slice yet.
> +	 * Should be extended for other platforms.
> +	 */
> +	return DBUF_S1_BIT;
> +}
> +
>  static u64
>  skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
>  			     const struct intel_plane_state *plane_state,
> -- 
> 2.17.1

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place
  2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place Stanislav Lisovskiy
  2019-12-13 17:08   ` Matt Roper
@ 2019-12-18 18:12   ` Ville Syrjälä
  1 sibling, 0 replies; 23+ messages in thread
From: Ville Syrjälä @ 2019-12-18 18:12 UTC (permalink / raw)
  To: Stanislav Lisovskiy; +Cc: intel-gfx

On Fri, Dec 13, 2019 at 03:02:26PM +0200, Stanislav Lisovskiy wrote:
> Current DBuf slices update wasn't done in proper
> plane, especially its "post" part, which should
> disable those only once vblank had passed and
> all other changes are committed.
> 
> v2: Fix to use dev_priv and intel_atomic_state
>     instead of skl_ddb_values
>     (to be nuked in Villes patch)
> 
> v3: Renamed "enabled_slices" to "enabled_dbuf_slices_num"
>     (Matt Roper)
> 
> Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
> Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 38 ++++++++++++++------
>  1 file changed, 28 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 62e33bca7014..0e09d0c23b1d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -14546,13 +14546,33 @@ static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
>  				       state);
>  }
>  
> +static void icl_dbuf_slice_pre_update(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
> +
> +	/* If 2nd DBuf slice required, enable it here */
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> +		icl_dbuf_slices_update(dev_priv, required_slices);
> +}
> +
> +static void icl_dbuf_slice_post_update(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> +	u8 required_slices = state->enabled_dbuf_slices_num;
> +
> +	/* If 2nd DBuf slice is no more required disable it */
> +	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> +		icl_dbuf_slices_update(dev_priv, required_slices);
> +}
> +
>  static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
>  	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
> -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> -	u8 required_slices = state->enabled_dbuf_slices_num;
>  	struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
>  	u8 dirty_pipes = 0;
>  	int i;
> @@ -14565,10 +14585,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  			dirty_pipes |= BIT(crtc->pipe);
>  	}
>  
> -	/* If 2nd DBuf slice required, enable it here */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
> -
>  	/*
>  	 * Whenever the number of active pipes changes, we need to make sure we
>  	 * update the pipes in the right order so that their ddb allocations
> @@ -14617,10 +14633,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
>  				intel_wait_for_vblank(dev_priv, pipe);
>  		}
>  	}
> -
> -	/* If 2nd DBuf slice is no more required disable it */
> -	if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
> -		icl_dbuf_slices_update(dev_priv, required_slices);
>  }
>  
>  static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
> @@ -14750,6 +14762,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  	if (state->modeset)
>  		intel_encoders_update_prepare(state);
>  
> +	/* Enable all new slices, we might need */
> +	icl_dbuf_slice_pre_update(state);
> +
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
>  	dev_priv->display.commit_modeset_enables(state);
>  
> @@ -14825,6 +14840,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  	if (state->modeset && intel_can_enable_sagv(state))
>  		intel_enable_sagv(dev_priv);
>  
> +	/* Disable all slices, we don't need */
> +	icl_dbuf_slice_post_update(state);

I would put that just before or after the .optimize_watermarks() loop.
That's kinda the equivalent spot where we do other FIFO related things
on older platforms. And crucially it's before we do the extra underrun
checks and state verification. Not sure why the state verification isn't
blowing up for you with this actually?

Otherwise looks good
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>


> +
>  	drm_atomic_helper_commit_hw_done(&state->base);
>  
>  	if (state->modeset) {
> -- 
> 2.17.1

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-18 18:00   ` Ville Syrjälä
@ 2019-12-19  9:13     ` Lisovskiy, Stanislav
  2019-12-19  9:48       ` Ville Syrjälä
  0 siblings, 1 reply; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-19  9:13 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, 2019-12-18 at 20:00 +0200, Ville Syrjälä wrote:
> On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy wrote:
> > Start manipulating DBuf slices as a mask,
> > but not as a total number, as current approach
> > doesn't give us full control on all combinations
> > of slices, which we might need(like enabling S2
> > only can't enabled by setting enabled_slices=1).
> > 
> > Removed wrong code from intel_get_ddb_size as
> > it doesn't match to BSpec. For now still just
> > use DBuf slice until proper algorithm is implemented.
> > 
> > Other minor code refactoring to get prepared
> > for major DBuf assignment changes landed:
> > - As now enabled slices contain a mask
> >   we still need some value which should
> >   reflect how much DBuf slices are supported
> >   by the platform, now device info contains
> >   num_supported_dbuf_slices.
> > - Removed unneeded assertion as we are now
> >   manipulating slices in a more proper way.
> > 
> > v2: Start using enabled_slices in dev_priv
> > 
> > v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
> >     as this now sits in dev_priv independently.
> > 
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
> >  .../drm/i915/display/intel_display_power.c    | 100 ++++++++----
> > ------
> >  .../drm/i915/display/intel_display_power.h    |   5 +
> >  .../drm/i915/display/intel_display_types.h    |   2 +-
> >  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
> >  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
> >  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
> >  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
> >  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
> >  9 files changed, 84 insertions(+), 106 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index 0e09d0c23b1d..42a0ea540d4f 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct
> > intel_crtc *crtc,

Hi Ville,

Thank you for comments, please see replies for some of those inline.

> >  
> >  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
> >  
> > -	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> > +	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
> >  
> >  	if (INTEL_GEN(dev_priv) >= 11 &&
> > -	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
> > -		DRM_ERROR("mismatch in DBUF Slices (expected %u, got
> > %u)\n",
> > -			  dev_priv->enabled_dbuf_slices_num,
> > +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
> > +		DRM_ERROR("mismatch in DBUF Slices (expected %x, got
> > %x)\n",
> > +			  dev_priv->enabled_dbuf_slices_mask,
> >  			  hw_enabled_slices);
> >  
> >  	/* planes */
> > @@ -14549,22 +14549,23 @@ static void
> > intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
> >  static void icl_dbuf_slice_pre_update(struct intel_atomic_state
> > *state)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > +	u8 slices_union = hw_enabled_slices | required_slices;
> >  
> >  	/* If 2nd DBuf slice required, enable it here */
> > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices >
> > hw_enabled_slices)
> > -		icl_dbuf_slices_update(dev_priv, required_slices);
> > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > hw_enabled_slices)
> > +		icl_dbuf_slices_update(dev_priv, slices_union);
> >  }
> >  
> >  static void icl_dbuf_slice_post_update(struct intel_atomic_state
> > *state)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> >  
> >  	/* If 2nd DBuf slice is no more required disable it */
> > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices <
> > hw_enabled_slices)
> > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > hw_enabled_slices)
> 
> I would rename the variables to old_slices vs. new_slices or
> something
> like that. Would match the common naming pattern we use extensively
> all
> over.

Yep, we just used to have it that way, so I just didn't want to
change variable names.

> 
> >  		icl_dbuf_slices_update(dev_priv, required_slices);
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c
> > b/drivers/gpu/drm/i915/display/intel_display_power.c
> > index b8983422a882..ba384a5315f8 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> > @@ -1031,15 +1031,6 @@ static bool
> > gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
> >  		(I915_READ(DC_STATE_EN) &
> > DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
> >  }
> >  
> > -static void gen9_assert_dbuf_enabled(struct drm_i915_private
> > *dev_priv)
> > -{
> > -	u32 tmp = I915_READ(DBUF_CTL);
> > -
> > -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> > -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> > -	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
> > -}
> > -
> >  static void gen9_disable_dc_states(struct drm_i915_private
> > *dev_priv)
> >  {
> >  	struct intel_cdclk_state cdclk_state = {};
> > @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct
> > drm_i915_private *dev_priv)
> >  	/* Can't read out voltage_level so can't use
> > intel_cdclk_changed() */
> >  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw,
> > &cdclk_state));
> >  
> > -	gen9_assert_dbuf_enabled(dev_priv);
> 
> Why are you removing these? I think you still left the code in place
> to
> power up the first slice uncoditionally. Also not sure if DMC just
> powers that sucker up regardless. I think we should try it and if DMC
> isn't insane we should turn all the slices off when we don't need
> them.

I just didn't get why we do this check here, as we actually have that
check in verify_wm_state. Also this hardcoded check seems to always
assume that we should have both slices enabled which might be wrong - 
we could have now different configurations, prior to this call,
as this is called for example before suspend which would be 
intel_power_domains_suspend->icl_display_core_uninit-
>gen9_disable_dc_states->gen9_assert_dbuf_enabled.

But prior to suspend we can now have S1 or S2 in any combination
enabled or disabled based on pipes config.

verify_wm_state does it at least in a smarter way, i.e it checks 
the actual calculated sw state against hw state and then WARNs about
the mismatch.

> 
> > -
> >  	if (IS_GEN9_LP(dev_priv))
> >  		bxt_verify_ddi_phy_power_wells(dev_priv);
> >  
> > @@ -4254,72 +4243,71 @@ static void gen9_dbuf_disable(struct
> > drm_i915_private *dev_priv)
> >  	intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
> >  }
> >  
> > -static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> > +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
> >  {
> > -	if (INTEL_GEN(dev_priv) < 11)
> > -		return 1;
> > -	return 2;
> > +	return INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
> > +}
> 
> I don't see this being used anywhere outside this file in this patch.
> So why is it being made non-static? Also it's rather redundant now
> and could just be inlined into the single caller we have left.
> 
> > +
> > +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv)
> > +{
> > +	const u8 hw_enabled_slices = dev_priv-
> > >enabled_dbuf_slices_mask;
> 
> This whole function is just a one line wrapper now that does nothing
> special. So I would not even add it.
> 
> > +
> > +	icl_dbuf_slices_update(dev_priv, hw_enabled_slices);
> >  }
> >  
> >  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
> >  			    u8 req_slices)
> >  {
> > -	const u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > -	bool ret;
> > +	int i;
> > +	int max_slices = intel_dbuf_max_slices(dev_priv);
> >  
> > -	if (req_slices > intel_dbuf_max_slices(dev_priv)) {
> > +	if (hweight8(req_slices) > intel_dbuf_max_slices(dev_priv)) {
> 
> You already have max_slices in a variable.
> 
> >  		DRM_ERROR("Invalid number of dbuf slices requested\n");
> 
> Can't happen unless we messed up in state calculation. We should
> drop the check or just WARN and keep going. But that's probably
> material for another patch.
> 
> >  		return;
> >  	}
> >  
> > -	if (req_slices == hw_enabled_slices || req_slices == 0)
> > -		return;
> > +	DRM_DEBUG_KMS("Updating dbuf slices to %x\n", req_slices);
> 
> Pls use 0x%x so it's obvious it's hex.
> 
> >  
> > -	if (req_slices > hw_enabled_slices)
> > -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2,
> > true);
> > -	else
> > -		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2,
> > false);
> > +	for (i = 0; i < max_slices; i++) {
> > +		int slice_bit = BIT(i);
> > +		bool slice_set = (slice_bit & req_slices) != 0;
> > +
> > +		switch (slice_bit) {
> > +		case DBUF_S1_BIT:
> > +			intel_dbuf_slice_set(dev_priv,
> > +					     DBUF_CTL_S1,
> > +					     slice_set);
> > +			break;
> > +		case DBUF_S2_BIT:
> > +			intel_dbuf_slice_set(dev_priv,
> > +					     DBUF_CTL_S2,
> > +					     slice_set);
> > +			break;
> > +		default:
> > +			MISSING_CASE(slice_bit);
> > +		}
> 
> Still can be just:
> 	intel_dbuf_slice_set(dev_priv, DBUF_CTL(i), 
> 			     req_slices & BIT(i));

I actually have this already in latest patch revision:

https://patchwork.freedesktop.org/patch/345308/?series=70059&rev=10

Stan

> 
> 
> > +	}
> >  
> > -	if (ret)
> > -		dev_priv->enabled_dbuf_slices_num = req_slices;
> > +	dev_priv->enabled_dbuf_slices_mask = req_slices;
> >  }
> >  
> >  static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
> >  {
> > -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) |
> > DBUF_POWER_REQUEST);
> > -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) |
> > DBUF_POWER_REQUEST);
> > -	POSTING_READ(DBUF_CTL_S2);
> > -
> > -	udelay(10);
> > -
> > -	if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> > -	    !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> > -		DRM_ERROR("DBuf power enable timeout\n");
> > -	else
> > -		/*
> > -		 * FIXME: for now pretend that we only have 1 slice,
> > see
> > -		 * intel_enabled_dbuf_slices_num().
> > -		 */
> > -		dev_priv->enabled_dbuf_slices_num = 1;
> > +	/*
> > +	 * Just power up 1 slice, we will
> > +	 * figure out later which slices we have and what we need.
> > +	 */
> > +	dev_priv->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > +	icl_program_dbuf_slices(dev_priv);
> >  }
> >  
> >  static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
> >  {
> > -	I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) &
> > ~DBUF_POWER_REQUEST);
> > -	I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) &
> > ~DBUF_POWER_REQUEST);
> > -	POSTING_READ(DBUF_CTL_S2);
> > -
> > -	udelay(10);
> > -
> > -	if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) ||
> > -	    (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE))
> > -		DRM_ERROR("DBuf power disable timeout!\n");
> > -	else
> > -		/*
> > -		 * FIXME: for now pretend that the first slice is
> > always
> > -		 * enabled, see intel_enabled_dbuf_slices_num().
> > -		 */
> > -		dev_priv->enabled_dbuf_slices_num = 1;
> > +	/*
> > +	 * Disable all slices
> > +	 */
> > +	dev_priv->enabled_dbuf_slices_mask = 0;
> > +	icl_program_dbuf_slices(dev_priv);
> >  }
> >  
> >  static void icl_mbus_init(struct drm_i915_private *dev_priv)
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h
> > b/drivers/gpu/drm/i915/display/intel_display_power.h
> > index 1da04f3e0fb3..0d9f87607eac 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_power.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_power.h
> > @@ -311,8 +311,13 @@ intel_display_power_put_async(struct
> > drm_i915_private *i915,
> >  	for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
> >  	     intel_display_power_put_async((i915), (domain), (wf)),
> > (wf) = 0)
> >  
> > +#define DBUF_S1_BIT			BIT(0)
> > +#define DBUF_S2_BIT			BIT(1)
> > +
> >  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
> >  			    u8 req_slices);
> > +void icl_program_dbuf_slices(struct drm_i915_private *dev_priv);
> > +int intel_dbuf_max_slices(struct drm_i915_private *dev_priv);
> >  
> >  void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >  			     bool override, unsigned int mask);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 70e65c2d525d..ba2e41a03051 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -518,7 +518,7 @@ struct intel_atomic_state {
> >  	struct skl_ddb_values wm_results;
> >  
> >  	/* Number of enabled DBuf slices */
> > -	u8 enabled_dbuf_slices_num;
> > +	u8 enabled_dbuf_slices_mask;
> >  
> >  	struct i915_sw_fence commit_ready;
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > b/drivers/gpu/drm/i915/i915_drv.h
> > index 7a2d9fa5a9a6..ec4b9e3cef79 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1210,7 +1210,7 @@ struct drm_i915_private {
> >  		bool distrust_bios_wm;
> >  	} wm;
> >  
> > -	u8 enabled_dbuf_slices_num; /* GEN11 has configurable 2 slices
> > */
> > +	u8 enabled_dbuf_slices_mask; /* GEN11 has configurable 2 slices
> > */
> >  
> >  	struct dram_info {
> >  		bool valid;
> > diff --git a/drivers/gpu/drm/i915/i915_pci.c
> > b/drivers/gpu/drm/i915/i915_pci.c
> > index 877560b1031e..2068aac5ab6a 100644
> > --- a/drivers/gpu/drm/i915/i915_pci.c
> > +++ b/drivers/gpu/drm/i915/i915_pci.c
> > @@ -614,7 +614,8 @@ static const struct intel_device_info
> > intel_cherryview_info = {
> >  	.has_gt_uc = 1, \
> >  	.display.has_hdcp = 1, \
> >  	.display.has_ipc = 1, \
> > -	.ddb_size = 896
> > +	.ddb_size = 896, \
> > +	.num_supported_dbuf_slices = 1
> >  
> >  #define SKL_PLATFORM \
> >  	GEN9_FEATURES, \
> > @@ -649,6 +650,7 @@ static const struct intel_device_info
> > intel_skylake_gt4_info = {
> >  #define GEN9_LP_FEATURES \
> >  	GEN(9), \
> >  	.is_lp = 1, \
> > +	.num_supported_dbuf_slices = 1, \
> >  	.display.has_hotplug = 1, \
> >  	.engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0),
> > \
> >  	.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \
> > @@ -737,6 +739,7 @@ static const struct intel_device_info
> > intel_coffeelake_gt3_info = {
> >  	GEN9_FEATURES, \
> >  	GEN(10), \
> >  	.ddb_size = 1024, \
> > +	.num_supported_dbuf_slices = 1, \
> >  	.display.has_dsc = 1, \
> >  	.has_coherent_ggtt = false, \
> >  	GLK_COLORS
> > @@ -773,6 +776,7 @@ static const struct intel_device_info
> > intel_cannonlake_info = {
> >  	}, \
> >  	GEN(11), \
> >  	.ddb_size = 2048, \
> > +	.num_supported_dbuf_slices = 2, \
> >  	.has_logical_ring_elsq = 1, \
> >  	.color = { .degamma_lut_size = 33, .gamma_lut_size = 262145 }
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_device_info.h
> > b/drivers/gpu/drm/i915/intel_device_info.h
> > index 2725cb7fc169..7d4d122d2182 100644
> > --- a/drivers/gpu/drm/i915/intel_device_info.h
> > +++ b/drivers/gpu/drm/i915/intel_device_info.h
> > @@ -180,6 +180,7 @@ struct intel_device_info {
> >  	} display;
> >  
> >  	u16 ddb_size; /* in blocks */
> > +	u8 num_supported_dbuf_slices; /* number of DBuf slices */
> 
> Redundant comment.
> 
> >  
> >  	/* Register offsets for the various display pipes and
> > transcoders */
> >  	int pipe_offsets[I915_MAX_TRANSCODERS];
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c
> > index c2510978ccdf..111bcafd6e4c 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3616,26 +3616,22 @@ bool ilk_disable_lp_wm(struct
> > drm_i915_private *dev_priv)
> >  	return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
> >  }
> >  
> > -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private
> > *dev_priv)
> > +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private
> > *dev_priv)
> >  {
> > -	u8 enabled_dbuf_slices_num;
> > -
> > -	/* Slice 1 will always be enabled */
> > -	enabled_dbuf_slices_num = 1;
> > +	u8 enabled_slices_mask = 0;
> >  
> >  	/* Gen prior to GEN11 have only one DBuf slice */
> >  	if (INTEL_GEN(dev_priv) < 11)
> > -		return enabled_dbuf_slices_num;
> > +		return DBUF_S1_BIT;
> >  
> > -	/*
> > -	 * FIXME: for now we'll only ever use 1 slice; pretend that we
> > have
> > -	 * only that 1 slice enabled until we have a proper way for on-
> > demand
> > -	 * toggling of the second slice.
> > -	 */
> > -	if (0 && I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> > -		enabled_dbuf_slices_num++;
> > +	/* Check if second DBuf slice is enabled */
> > +	if (I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE)
> > +		enabled_slices_mask |= DBUF_S1_BIT;
> >  
> > -	return enabled_dbuf_slices_num;
> > +	if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)
> > +		enabled_slices_mask |= DBUF_S2_BIT;
> 
> With parametrized DBUF_CTL this could also just loop over the slices.
> 
> > +
> > +	return enabled_slices_mask;
> >  }
> >  
> >  /*
> > @@ -3843,8 +3839,6 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  {
> >  	struct drm_atomic_state *state = crtc_state->uapi.state;
> >  	struct intel_atomic_state *intel_state =
> > to_intel_atomic_state(state);
> > -	const struct drm_display_mode *adjusted_mode;
> > -	u64 total_data_bw;
> >  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> >  
> >  	WARN_ON(ddb_size == 0);
> > @@ -3852,23 +3846,8 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  	if (INTEL_GEN(dev_priv) < 11)
> >  		return ddb_size - 4; /* 4 blocks for bypass path
> > allocation */
> >  
> > -	adjusted_mode = &crtc_state->hw.adjusted_mode;
> > -	total_data_bw = total_data_rate *
> > drm_mode_vrefresh(adjusted_mode);
> > -
> > -	/*
> > -	 * 12GB/s is maximum BW supported by single DBuf slice.
> > -	 *
> > -	 * FIXME dbuf slice code is broken:
> > -	 * - must wait for planes to stop using the slice before
> > powering it off
> > -	 * - plane straddling both slices is illegal in multi-pipe
> > scenarios
> > -	 * - should validate we stay within the hw bandwidth limits
> > -	 */
> > -	if (0 && (num_active > 1 || total_data_bw >= GBps(12))) {
> > -		intel_state->enabled_dbuf_slices_num = 2;
> > -	} else {
> > -		intel_state->enabled_dbuf_slices_num = 1;
> > -		ddb_size /= 2;
> > -	}
> 
> Aren't we left with loads of pointless function arguments now?
> 
> > +	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > +	ddb_size /= 2;
> >  
> >  	return ddb_size;
> >  }
> > @@ -4065,7 +4044,7 @@ void skl_pipe_ddb_get_hw_state(struct
> > intel_crtc *crtc,
> >  
> >  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv)
> >  {
> > -	dev_priv->enabled_dbuf_slices_num =
> > intel_enabled_dbuf_slices_num(dev_priv);
> > +	dev_priv->enabled_dbuf_slices_mask =
> > intel_enabled_dbuf_slices_mask(dev_priv);
> >  }
> >  
> >  /*
> > @@ -5204,7 +5183,7 @@ skl_compute_ddb(struct intel_atomic_state
> > *state)
> >  	struct intel_crtc *crtc;
> >  	int ret, i;
> >  
> > -	state->enabled_dbuf_slices_num = dev_priv-
> > >enabled_dbuf_slices_num;
> > +	state->enabled_dbuf_slices_mask = dev_priv-
> > >enabled_dbuf_slices_mask;
> >  
> >  	for_each_oldnew_intel_crtc_in_state(state, crtc,
> > old_crtc_state,
> >  					    new_crtc_state, i) {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.h
> > b/drivers/gpu/drm/i915/intel_pm.h
> > index a476f6c730e9..7a7494d1224f 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.h
> > +++ b/drivers/gpu/drm/i915/intel_pm.h
> > @@ -33,7 +33,7 @@ void g4x_wm_get_hw_state(struct drm_i915_private
> > *dev_priv);
> >  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
> >  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
> >  void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
> > -u8 intel_enabled_dbuf_slices_num(struct drm_i915_private
> > *dev_priv);
> > +u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private
> > *dev_priv);
> >  void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
> >  			       struct skl_ddb_entry *ddb_y,
> >  			       struct skl_ddb_entry *ddb_uv);
> > -- 
> > 2.17.1
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-19  9:13     ` Lisovskiy, Stanislav
@ 2019-12-19  9:48       ` Ville Syrjälä
  2019-12-19 11:30         ` Lisovskiy, Stanislav
  0 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2019-12-19  9:48 UTC (permalink / raw)
  To: Lisovskiy, Stanislav; +Cc: intel-gfx

On Thu, Dec 19, 2019 at 09:13:23AM +0000, Lisovskiy, Stanislav wrote:
> On Wed, 2019-12-18 at 20:00 +0200, Ville Syrjälä wrote:
> > On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy wrote:
> > > Start manipulating DBuf slices as a mask,
> > > but not as a total number, as current approach
> > > doesn't give us full control on all combinations
> > > of slices, which we might need(like enabling S2
> > > only can't enabled by setting enabled_slices=1).
> > > 
> > > Removed wrong code from intel_get_ddb_size as
> > > it doesn't match to BSpec. For now still just
> > > use DBuf slice until proper algorithm is implemented.
> > > 
> > > Other minor code refactoring to get prepared
> > > for major DBuf assignment changes landed:
> > > - As now enabled slices contain a mask
> > >   we still need some value which should
> > >   reflect how much DBuf slices are supported
> > >   by the platform, now device info contains
> > >   num_supported_dbuf_slices.
> > > - Removed unneeded assertion as we are now
> > >   manipulating slices in a more proper way.
> > > 
> > > v2: Start using enabled_slices in dev_priv
> > > 
> > > v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
> > >     as this now sits in dev_priv independently.
> > > 
> > > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
> > >  .../drm/i915/display/intel_display_power.c    | 100 ++++++++----
> > > ------
> > >  .../drm/i915/display/intel_display_power.h    |   5 +
> > >  .../drm/i915/display/intel_display_types.h    |   2 +-
> > >  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
> > >  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
> > >  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
> > >  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
> > >  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
> > >  9 files changed, 84 insertions(+), 106 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > > b/drivers/gpu/drm/i915/display/intel_display.c
> > > index 0e09d0c23b1d..42a0ea540d4f 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct
> > > intel_crtc *crtc,
> 
> Hi Ville,
> 
> Thank you for comments, please see replies for some of those inline.
> 
> > >  
> > >  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
> > >  
> > > -	hw_enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> > > +	hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
> > >  
> > >  	if (INTEL_GEN(dev_priv) >= 11 &&
> > > -	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_num)
> > > -		DRM_ERROR("mismatch in DBUF Slices (expected %u, got
> > > %u)\n",
> > > -			  dev_priv->enabled_dbuf_slices_num,
> > > +	    hw_enabled_slices != dev_priv->enabled_dbuf_slices_mask)
> > > +		DRM_ERROR("mismatch in DBUF Slices (expected %x, got
> > > %x)\n",
> > > +			  dev_priv->enabled_dbuf_slices_mask,
> > >  			  hw_enabled_slices);
> > >  
> > >  	/* planes */
> > > @@ -14549,22 +14549,23 @@ static void
> > > intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
> > >  static void icl_dbuf_slice_pre_update(struct intel_atomic_state
> > > *state)
> > >  {
> > >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > > +	u8 slices_union = hw_enabled_slices | required_slices;
> > >  
> > >  	/* If 2nd DBuf slice required, enable it here */
> > > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices >
> > > hw_enabled_slices)
> > > -		icl_dbuf_slices_update(dev_priv, required_slices);
> > > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > > hw_enabled_slices)
> > > +		icl_dbuf_slices_update(dev_priv, slices_union);
> > >  }
> > >  
> > >  static void icl_dbuf_slice_post_update(struct intel_atomic_state
> > > *state)
> > >  {
> > >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > > -	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_num;
> > > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > > +	u8 hw_enabled_slices = dev_priv->enabled_dbuf_slices_mask;
> > > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > >  
> > >  	/* If 2nd DBuf slice is no more required disable it */
> > > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices <
> > > hw_enabled_slices)
> > > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > > hw_enabled_slices)
> > 
> > I would rename the variables to old_slices vs. new_slices or
> > something
> > like that. Would match the common naming pattern we use extensively
> > all
> > over.
> 
> Yep, we just used to have it that way, so I just didn't want to
> change variable names.
> 
> > 
> > >  		icl_dbuf_slices_update(dev_priv, required_slices);
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c
> > > b/drivers/gpu/drm/i915/display/intel_display_power.c
> > > index b8983422a882..ba384a5315f8 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> > > @@ -1031,15 +1031,6 @@ static bool
> > > gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
> > >  		(I915_READ(DC_STATE_EN) &
> > > DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
> > >  }
> > >  
> > > -static void gen9_assert_dbuf_enabled(struct drm_i915_private
> > > *dev_priv)
> > > -{
> > > -	u32 tmp = I915_READ(DBUF_CTL);
> > > -
> > > -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> > > -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> > > -	     "Unexpected DBuf power power state (0x%08x)\n", tmp);
> > > -}
> > > -
> > >  static void gen9_disable_dc_states(struct drm_i915_private
> > > *dev_priv)
> > >  {
> > >  	struct intel_cdclk_state cdclk_state = {};
> > > @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct
> > > drm_i915_private *dev_priv)
> > >  	/* Can't read out voltage_level so can't use
> > > intel_cdclk_changed() */
> > >  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw,
> > > &cdclk_state));
> > >  
> > > -	gen9_assert_dbuf_enabled(dev_priv);
> > 
> > Why are you removing these? I think you still left the code in place
> > to
> > power up the first slice uncoditionally. Also not sure if DMC just
> > powers that sucker up regardless. I think we should try it and if DMC
> > isn't insane we should turn all the slices off when we don't need
> > them.
> 
> I just didn't get why we do this check here, as we actually have that
> check in verify_wm_state. Also this hardcoded check seems to always
> assume that we should have both slices enabled which might be wrong - 
> we could have now different configurations, prior to this call,
> as this is called for example before suspend which would be 
> intel_power_domains_suspend->icl_display_core_uninit-

The check is there because DMC is supposed to restore power to the
slices after DC5/6.

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly
  2019-12-19  9:48       ` Ville Syrjälä
@ 2019-12-19 11:30         ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-19 11:30 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, 2019-12-19 at 11:48 +0200, Ville Syrjälä wrote:
> On Thu, Dec 19, 2019 at 09:13:23AM +0000, Lisovskiy, Stanislav wrote:
> > On Wed, 2019-12-18 at 20:00 +0200, Ville Syrjälä wrote:
> > > On Fri, Dec 13, 2019 at 03:02:27PM +0200, Stanislav Lisovskiy
> > > wrote:
> > > > Start manipulating DBuf slices as a mask,
> > > > but not as a total number, as current approach
> > > > doesn't give us full control on all combinations
> > > > of slices, which we might need(like enabling S2
> > > > only can't enabled by setting enabled_slices=1).
> > > > 
> > > > Removed wrong code from intel_get_ddb_size as
> > > > it doesn't match to BSpec. For now still just
> > > > use DBuf slice until proper algorithm is implemented.
> > > > 
> > > > Other minor code refactoring to get prepared
> > > > for major DBuf assignment changes landed:
> > > > - As now enabled slices contain a mask
> > > >   we still need some value which should
> > > >   reflect how much DBuf slices are supported
> > > >   by the platform, now device info contains
> > > >   num_supported_dbuf_slices.
> > > > - Removed unneeded assertion as we are now
> > > >   manipulating slices in a more proper way.
> > > > 
> > > > v2: Start using enabled_slices in dev_priv
> > > > 
> > > > v3: "enabled_slices" is now "enabled_dbuf_slices_mask",
> > > >     as this now sits in dev_priv independently.
> > > > 
> > > > Signed-off-by: Stanislav Lisovskiy <
> > > > stanislav.lisovskiy@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/display/intel_display.c  |  23 ++--
> > > >  .../drm/i915/display/intel_display_power.c    | 100 ++++++++
> > > > ----
> > > > ------
> > > >  .../drm/i915/display/intel_display_power.h    |   5 +
> > > >  .../drm/i915/display/intel_display_types.h    |   2 +-
> > > >  drivers/gpu/drm/i915/i915_drv.h               |   2 +-
> > > >  drivers/gpu/drm/i915/i915_pci.c               |   6 +-
> > > >  drivers/gpu/drm/i915/intel_device_info.h      |   1 +
> > > >  drivers/gpu/drm/i915/intel_pm.c               |  49 +++------
> > > >  drivers/gpu/drm/i915/intel_pm.h               |   2 +-
> > > >  9 files changed, 84 insertions(+), 106 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > > > b/drivers/gpu/drm/i915/display/intel_display.c
> > > > index 0e09d0c23b1d..42a0ea540d4f 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > > @@ -13359,12 +13359,12 @@ static void verify_wm_state(struct
> > > > intel_crtc *crtc,
> > 
> > Hi Ville,
> > 
> > Thank you for comments, please see replies for some of those
> > inline.
> > 

Just going through your comments now - majority seem to be addressed
already in recent series(formatiing, DBUF_CTL automation, redundant
static func). So I will proceed with DBUF asserts and remaining stuff,
being not addressed.

However I would take a courage to leave variable naming same at least
:)
As for example "required_slices" and "hw_enabled_slices" were named
that way even before me. Let's may be first solve all the crucial 
issues here and then I would be happy to change those variable
names(which were named that way by somebody else) to whatever in a
follow up patch.

Stan

> > > >  
> > > >  	skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
> > > >  
> > > > -	hw_enabled_slices =
> > > > intel_enabled_dbuf_slices_num(dev_priv);
> > > > +	hw_enabled_slices =
> > > > intel_enabled_dbuf_slices_mask(dev_priv);
> > > >  
> > > >  	if (INTEL_GEN(dev_priv) >= 11 &&
> > > > -	    hw_enabled_slices != dev_priv-
> > > > >enabled_dbuf_slices_num)
> > > > -		DRM_ERROR("mismatch in DBUF Slices (expected
> > > > %u, got
> > > > %u)\n",
> > > > -			  dev_priv->enabled_dbuf_slices_num,
> > > > +	    hw_enabled_slices != dev_priv-
> > > > >enabled_dbuf_slices_mask)
> > > > +		DRM_ERROR("mismatch in DBUF Slices (expected
> > > > %x, got
> > > > %x)\n",
> > > > +			  dev_priv->enabled_dbuf_slices_mask,
> > > >  			  hw_enabled_slices);
> > > >  
> > > >  	/* planes */
> > > > @@ -14549,22 +14549,23 @@ static void
> > > > intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
> > > >  static void icl_dbuf_slice_pre_update(struct
> > > > intel_atomic_state
> > > > *state)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv = to_i915(state-
> > > > >base.dev);
> > > > -	u8 hw_enabled_slices = dev_priv-
> > > > >enabled_dbuf_slices_num;
> > > > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > > > +	u8 hw_enabled_slices = dev_priv-
> > > > >enabled_dbuf_slices_mask;
> > > > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > > > +	u8 slices_union = hw_enabled_slices | required_slices;
> > > >  
> > > >  	/* If 2nd DBuf slice required, enable it here */
> > > > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices >
> > > > hw_enabled_slices)
> > > > -		icl_dbuf_slices_update(dev_priv,
> > > > required_slices);
> > > > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > > > hw_enabled_slices)
> > > > +		icl_dbuf_slices_update(dev_priv, slices_union);
> > > >  }
> > > >  
> > > >  static void icl_dbuf_slice_post_update(struct
> > > > intel_atomic_state
> > > > *state)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv = to_i915(state-
> > > > >base.dev);
> > > > -	u8 hw_enabled_slices = dev_priv-
> > > > >enabled_dbuf_slices_num;
> > > > -	u8 required_slices = state->enabled_dbuf_slices_num;
> > > > +	u8 hw_enabled_slices = dev_priv-
> > > > >enabled_dbuf_slices_mask;
> > > > +	u8 required_slices = state->enabled_dbuf_slices_mask;
> > > >  
> > > >  	/* If 2nd DBuf slice is no more required disable it */
> > > > -	if (INTEL_GEN(dev_priv) >= 11 && required_slices <
> > > > hw_enabled_slices)
> > > > +	if (INTEL_GEN(dev_priv) >= 11 && required_slices !=
> > > > hw_enabled_slices)
> > > 
> > > I would rename the variables to old_slices vs. new_slices or
> > > something
> > > like that. Would match the common naming pattern we use
> > > extensively
> > > all
> > > over.
> > 
> > Yep, we just used to have it that way, so I just didn't want to
> > change variable names.
> > 
> > > 
> > > >  		icl_dbuf_slices_update(dev_priv,
> > > > required_slices);
> > > >  }
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c
> > > > b/drivers/gpu/drm/i915/display/intel_display_power.c
> > > > index b8983422a882..ba384a5315f8 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> > > > @@ -1031,15 +1031,6 @@ static bool
> > > > gen9_dc_off_power_well_enabled(struct drm_i915_private
> > > > *dev_priv,
> > > >  		(I915_READ(DC_STATE_EN) &
> > > > DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
> > > >  }
> > > >  
> > > > -static void gen9_assert_dbuf_enabled(struct drm_i915_private
> > > > *dev_priv)
> > > > -{
> > > > -	u32 tmp = I915_READ(DBUF_CTL);
> > > > -
> > > > -	WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
> > > > -	     (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
> > > > -	     "Unexpected DBuf power power state (0x%08x)\n",
> > > > tmp);
> > > > -}
> > > > -
> > > >  static void gen9_disable_dc_states(struct drm_i915_private
> > > > *dev_priv)
> > > >  {
> > > >  	struct intel_cdclk_state cdclk_state = {};
> > > > @@ -1055,8 +1046,6 @@ static void gen9_disable_dc_states(struct
> > > > drm_i915_private *dev_priv)
> > > >  	/* Can't read out voltage_level so can't use
> > > > intel_cdclk_changed() */
> > > >  	WARN_ON(intel_cdclk_needs_modeset(&dev_priv->cdclk.hw,
> > > > &cdclk_state));
> > > >  
> > > > -	gen9_assert_dbuf_enabled(dev_priv);
> > > 
> > > Why are you removing these? I think you still left the code in
> > > place
> > > to
> > > power up the first slice uncoditionally. Also not sure if DMC
> > > just
> > > powers that sucker up regardless. I think we should try it and if
> > > DMC
> > > isn't insane we should turn all the slices off when we don't need
> > > them.
> > 
> > I just didn't get why we do this check here, as we actually have
> > that
> > check in verify_wm_state. Also this hardcoded check seems to always
> > assume that we should have both slices enabled which might be wrong
> > - 
> > we could have now different configurations, prior to this call,
> > as this is called for example before suspend which would be 
> > intel_power_domains_suspend->icl_display_core_uninit-
> 
> The check is there because DMC is supposed to restore power to the
> slices after DC5/6.
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-18 18:05   ` Ville Syrjälä
@ 2019-12-19 11:58     ` Lisovskiy, Stanislav
  2019-12-19 12:02     ` Lisovskiy, Stanislav
  1 sibling, 0 replies; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-19 11:58 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, 2019-12-18 at 20:05 +0200, Ville Syrjälä wrote:
> On Fri, Dec 13, 2019 at 03:02:28PM +0200, Stanislav Lisovskiy wrote:
> > Added proper DBuf slice mapping to correspondent
> > pipes, depending on pipe configuration as stated
> > in BSpec.
> > 
> > v2:
> >     - Remove unneeded braces
> >     - Stop using macro for DBuf assignments as
> >       it seems to reduce readability.
> > 
> > v3: Start using enabled slices mask in dev_priv
> > 
> > v4: Renamed "enabled_slices" used in dev_priv
> >     to "enabled_dbuf_slices_mask"(Matt Roper)
> > 
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 226
> > ++++++++++++++++++++++++++++++--
> >  1 file changed, 216 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c
> > index 111bcafd6e4c..a13052b2c2ef 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct
> > intel_atomic_state *state)
> >  	return true;
> >  }
> >  
> > +/*
> > + * Calculate initial DBuf slice offset, based on slice size
> > + * and mask(i.e if slice size is 1024 and second slice is enabled
> > + * offset would be 1024)
> > + */
> > +static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
> > +					   u32 slice_size, u32
> > ddb_size)
> 
> s/u32/unsigned int/ or something. No point in using sized types when
> we're not dealing with some thing that is actually that size.
> 
> > +{
> > +	u32 offset = 0;
> > +
> > +	if (!dbuf_slice_mask)
> > +		return 0;
> > +
> > +	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
> > +
> > +	WARN_ON(offset >= ddb_size);
> > +	return offset;
> > +}
> > +
> >  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
> >  			      const struct intel_crtc_state
> > *crtc_state,
> >  			      const u64 total_data_rate,
> >  			      const int num_active)
> >  {
> > -	struct drm_atomic_state *state = crtc_state->uapi.state;
> > -	struct intel_atomic_state *intel_state =
> > to_intel_atomic_state(state);
> >  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> >  
> >  	WARN_ON(ddb_size == 0);
> > @@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  	if (INTEL_GEN(dev_priv) < 11)
> >  		return ddb_size - 4; /* 4 blocks for bypass path
> > allocation */
> >  
> > -	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > -	ddb_size /= 2;
> > -
> >  	return ddb_size;
> >  }
> >  
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state);
> > +
> >  static void
> >  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private
> > *dev_priv,
> >  				   const struct intel_crtc_state
> > *crtc_state,
> > @@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
> >  	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
> >  	u16 ddb_size;
> > +	u32 ddb_range_size;
> >  	u32 i;
> > +	u32 dbuf_slice_mask;
> > +	u32 active_pipes;
> > +	u32 offset;
> > +	u32 slice_size;
> > +	u32 total_slice_mask;
> > +	u32 start, end;
> >  
> >  	if (WARN_ON(!state) || !crtc_state->hw.active) {
> >  		alloc->start = 0;
> > @@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > -	if (intel_state->active_pipe_changes)
> > +	if (intel_state->active_pipe_changes) {
> >  		*num_active = hweight8(intel_state->active_pipes);
> > -	else
> > +		active_pipes = intel_state->active_pipes;
> > +	} else {
> >  		*num_active = hweight8(dev_priv->active_pipes);
> > +		active_pipes = dev_priv->active_pipes;
> > +	}
> >  
> >  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state,
> > total_data_rate,
> >  				      *num_active);
> >  
> > +	slice_size = ddb_size / INTEL_INFO(dev_priv)-
> > >num_supported_dbuf_slices;
> > +
> >  	/*
> >  	 * If the state doesn't change the active CRTC's or there is no
> >  	 * modeset request, then there's no need to recalculate;
> > @@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * Get allowed DBuf slices for correspondent pipe and platform.
> > +	 */
> > +	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
> > +						    active_pipes,
> > crtc_state);
> > +
> > +	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
> > +		      dbuf_slice_mask,
> > +		      for_pipe, active_pipes);
> > +
> > +	/*
> > +	 * Figure out at which DBuf slice we start, i.e if we start at
> > Dbuf S2
> > +	 * and slice size is 1024, the offset would be 1024
> > +	 */
> > +	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
> > +						 slice_size, ddb_size);
> > +
> > +	/*
> > +	 * Figure out total size of allowed DBuf slices, which is
> > basically
> > +	 * a number of allowed slices for that pipe multiplied by slice
> > size.
> > +	 * Inside of this
> > +	 * range ddb entries are still allocated in proportion to
> > display width.
> > +	 */
> > +	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
> > +
> >  	/*
> >  	 * Watermark/ddb requirement highly depends upon width of the
> >  	 * framebuffer, So instead of allocating DDB equally among
> > pipes
> >  	 * distribute DDB based on resolution/width of the display.
> >  	 */
> > +	total_slice_mask = dbuf_slice_mask;
> >  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state,
> > i) {
> >  		const struct drm_display_mode *adjusted_mode =
> >  			&crtc_state->hw.adjusted_mode;
> >  		enum pipe pipe = crtc->pipe;
> >  		int hdisplay, vdisplay;
> > +		u32 pipe_dbuf_slice_mask =
> > +					i915_possible_dbuf_slices(dev_p
> > riv,
> > +								  pipe,
> > +								  activ
> > e_pipes,
> > +								  crtc_
> > state);
> > +
> > +		if (!crtc_state->hw.active)
> > +			continue;
> > +
> > +		/*
> > +		 * According to BSpec pipe can share one dbuf slice
> > with another
> > +		 * pipes or pipe can use multiple dbufs, in both cases
> > we
> > +		 * account for other pipes only if they have exactly
> > same mask.
> > +		 * However we need to account how many slices we should
> > enable
> > +		 * in total.
> > +		 */
> > +		total_slice_mask |= pipe_dbuf_slice_mask;
> >  
> > -		if (!crtc_state->hw.enable)
> > +		/*
> > +		 * Do not account pipes using other slice sets
> > +		 * luckily as of current BSpec slice sets do not
> > partially
> > +		 * intersect(pipes share either same one slice or same
> > slice set
> > +		 * i.e no partial intersection), so it is enough to
> > check for
> > +		 * equality for now.
> > +		 */
> > +		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
> >  			continue;
> >  
> >  		drm_mode_get_hv_timing(adjusted_mode, &hdisplay,
> > &vdisplay);
> > @@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  			pipe_width = hdisplay;
> >  	}
> >  
> > -	alloc->start = ddb_size * width_before_pipe / total_width;
> > -	alloc->end = ddb_size * (width_before_pipe + pipe_width) /
> > total_width;
> > +	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
> > +
> > +	start = ddb_range_size * width_before_pipe / total_width;
> > +	end = ddb_range_size * (width_before_pipe + pipe_width) /
> > total_width;
> > +
> > +	alloc->start = offset + start;
> > +	alloc->end = offset + end;
> > +
> > +	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
> > +		      alloc->start, alloc->end);
> > +	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
> > +		      intel_state->enabled_dbuf_slices_mask,
> > +		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
> >  }
> 
> That function really is quite the monster. Probably needs to be split
> up
> into sensible chunks... later.
> 
> >  
> >  static int skl_compute_wm_params(const struct intel_crtc_state
> > *crtc_state,
> > @@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct
> > intel_crtc_state *crtc_state,
> >  	return mul_fixed16(downscale_w, downscale_h);
> >  }
> >  
> > +struct dbuf_slice_conf_entry {
> > +	u32 active_pipes;
> > +	u32 dbuf_mask[I915_MAX_PIPES];
> 
> u8 will do for everything.
> 
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 12716
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
> 
> Still don't like that DBUF_S1_BIT. I still think it should be an
> enum dbuf_slice + explcit BIT(DBUF_S1) where needed.
> 
> And please use named initializers instead of sprinkling zeroes.
> IMO this should just look something like:
> 
> 	{ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
> 	  .dbuf_slices = { [PIPE_A] = BIT(DBUF_S1),
> 	  		   [PIPE_B] = BIT(DBUF_S2),
> 			 },
> 	},
> 
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 49255
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> 
> I believe pipe C should use S1 here.

Thanks for spotting. Actually my generator says it as well, just didn't
use it for checking. BTW can you review that one as well - I think
it might be useful to keep in igt/tools, to avoid exactly typos like
this. 

> 
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> > +};
> > +
> > +static u32 i915_find_pipe_conf(int pipe,
> 
> enum pipe pipe
> 
> > +			       u32 active_pipes,
> > +			       const struct dbuf_slice_conf_entry
> > *dbuf_slices,
> > +			       int size)
> 
> Could just add a sentinel to the end of the arrays and avoid this
> 'size' stuff.
> 
> The function name is still very confusing. icl_compute_dbuf_slices()
> or something perhaps. Or even without a prefix since it's static
> anyway.
> 
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < size; i++) {
> > +		if (dbuf_slices[i].active_pipes == active_pipes)
> > +			return dbuf_slices[i].dbuf_mask[pipe];
> > +	}
> > +	return 0;
> > +}
> > +
> > +/*
> > + * This function finds an entry with same enabled pipe
> > configuration and
> > + * returns correspondent DBuf slice mask as stated in BSpec for
> > particular
> > + * platform.
> > + */
> > +static u32 icl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   icl_allowed_dbufs,
> > +				   ARRAY_SIZE(icl_allowed_dbufs));
> > +}
> > +
> > +static u32 tgl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   tgl_allowed_dbufs,
> > +				   ARRAY_SIZE(tgl_allowed_dbufs));
> > +}
> 
> These wrappers aren't really doing anything for us.
> 
> > +
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> 
> dev_priv and pipe are redundant parameters. Both
> can be extracted from crtc_state. I would put crtc_state as the first
> parameter. Matches common practice more closely.
> 
> s/i915/skl/ in the function name.
> 
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	if (IS_GEN(dev_priv, 11))
> > +		return icl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> > +	else if (IS_GEN(dev_priv, 12))
> > +		return tgl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> 
> The established convention is to go from new platforms
> to old platforms, if possible.
> 
> > +	/*
> > +	 * For anything else just return one slice yet.
> > +	 * Should be extended for other platforms.
> > +	 */
> > +	return DBUF_S1_BIT;
> > +}
> > +
> >  static u64
> >  skl_plane_relative_data_rate(const struct intel_crtc_state
> > *crtc_state,
> >  			     const struct intel_plane_state
> > *plane_state,
> > -- 
> > 2.17.1
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-18 18:05   ` Ville Syrjälä
  2019-12-19 11:58     ` Lisovskiy, Stanislav
@ 2019-12-19 12:02     ` Lisovskiy, Stanislav
  1 sibling, 0 replies; 23+ messages in thread
From: Lisovskiy, Stanislav @ 2019-12-19 12:02 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, 2019-12-18 at 20:05 +0200, Ville Syrjälä wrote:
> On Fri, Dec 13, 2019 at 03:02:28PM +0200, Stanislav Lisovskiy wrote:
> > Added proper DBuf slice mapping to correspondent
> > pipes, depending on pipe configuration as stated
> > in BSpec.
> > 
> > v2:
> >     - Remove unneeded braces
> >     - Stop using macro for DBuf assignments as
> >       it seems to reduce readability.
> > 
> > v3: Start using enabled slices mask in dev_priv
> > 
> > v4: Renamed "enabled_slices" used in dev_priv
> >     to "enabled_dbuf_slices_mask"(Matt Roper)
> > 
> > Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 226
> > ++++++++++++++++++++++++++++++--
> >  1 file changed, 216 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c
> > index 111bcafd6e4c..a13052b2c2ef 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3832,13 +3832,30 @@ bool intel_can_enable_sagv(struct
> > intel_atomic_state *state)
> >  	return true;
> >  }
> >  
> > +/*
> > + * Calculate initial DBuf slice offset, based on slice size
> > + * and mask(i.e if slice size is 1024 and second slice is enabled
> > + * offset would be 1024)
> > + */
> > +static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
> > +					   u32 slice_size, u32
> > ddb_size)
> 
> s/u32/unsigned int/ or something. No point in using sized types when
> we're not dealing with some thing that is actually that size.
> 
> > +{
> > +	u32 offset = 0;
> > +
> > +	if (!dbuf_slice_mask)
> > +		return 0;
> > +
> > +	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
> > +
> > +	WARN_ON(offset >= ddb_size);
> > +	return offset;
> > +}
> > +
> >  static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
> >  			      const struct intel_crtc_state
> > *crtc_state,
> >  			      const u64 total_data_rate,
> >  			      const int num_active)
> >  {
> > -	struct drm_atomic_state *state = crtc_state->uapi.state;
> > -	struct intel_atomic_state *intel_state =
> > to_intel_atomic_state(state);
> >  	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
> >  
> >  	WARN_ON(ddb_size == 0);
> > @@ -3846,12 +3863,13 @@ static u16 intel_get_ddb_size(struct
> > drm_i915_private *dev_priv,
> >  	if (INTEL_GEN(dev_priv) < 11)
> >  		return ddb_size - 4; /* 4 blocks for bypass path
> > allocation */
> >  
> > -	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
> > -	ddb_size /= 2;
> > -
> >  	return ddb_size;
> >  }
> >  
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state);
> > +
> >  static void
> >  skl_ddb_get_pipe_allocation_limits(struct drm_i915_private
> > *dev_priv,
> >  				   const struct intel_crtc_state
> > *crtc_state,
> > @@ -3866,7 +3884,14 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
> >  	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
> >  	u16 ddb_size;
> > +	u32 ddb_range_size;
> >  	u32 i;
> > +	u32 dbuf_slice_mask;
> > +	u32 active_pipes;
> > +	u32 offset;
> > +	u32 slice_size;
> > +	u32 total_slice_mask;
> > +	u32 start, end;
> >  
> >  	if (WARN_ON(!state) || !crtc_state->hw.active) {
> >  		alloc->start = 0;
> > @@ -3875,14 +3900,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > -	if (intel_state->active_pipe_changes)
> > +	if (intel_state->active_pipe_changes) {
> >  		*num_active = hweight8(intel_state->active_pipes);
> > -	else
> > +		active_pipes = intel_state->active_pipes;
> > +	} else {
> >  		*num_active = hweight8(dev_priv->active_pipes);
> > +		active_pipes = dev_priv->active_pipes;
> > +	}
> >  
> >  	ddb_size = intel_get_ddb_size(dev_priv, crtc_state,
> > total_data_rate,
> >  				      *num_active);
> >  
> > +	slice_size = ddb_size / INTEL_INFO(dev_priv)-
> > >num_supported_dbuf_slices;
> > +
> >  	/*
> >  	 * If the state doesn't change the active CRTC's or there is no
> >  	 * modeset request, then there's no need to recalculate;
> > @@ -3900,18 +3930,68 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * Get allowed DBuf slices for correspondent pipe and platform.
> > +	 */
> > +	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
> > +						    active_pipes,
> > crtc_state);
> > +
> > +	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
> > +		      dbuf_slice_mask,
> > +		      for_pipe, active_pipes);
> > +
> > +	/*
> > +	 * Figure out at which DBuf slice we start, i.e if we start at
> > Dbuf S2
> > +	 * and slice size is 1024, the offset would be 1024
> > +	 */
> > +	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
> > +						 slice_size, ddb_size);
> > +
> > +	/*
> > +	 * Figure out total size of allowed DBuf slices, which is
> > basically
> > +	 * a number of allowed slices for that pipe multiplied by slice
> > size.
> > +	 * Inside of this
> > +	 * range ddb entries are still allocated in proportion to
> > display width.
> > +	 */
> > +	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
> > +
> >  	/*
> >  	 * Watermark/ddb requirement highly depends upon width of the
> >  	 * framebuffer, So instead of allocating DDB equally among
> > pipes
> >  	 * distribute DDB based on resolution/width of the display.
> >  	 */
> > +	total_slice_mask = dbuf_slice_mask;
> >  	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state,
> > i) {
> >  		const struct drm_display_mode *adjusted_mode =
> >  			&crtc_state->hw.adjusted_mode;
> >  		enum pipe pipe = crtc->pipe;
> >  		int hdisplay, vdisplay;
> > +		u32 pipe_dbuf_slice_mask =
> > +					i915_possible_dbuf_slices(dev_p
> > riv,
> > +								  pipe,
> > +								  activ
> > e_pipes,
> > +								  crtc_
> > state);
> > +
> > +		if (!crtc_state->hw.active)
> > +			continue;
> > +
> > +		/*
> > +		 * According to BSpec pipe can share one dbuf slice
> > with another
> > +		 * pipes or pipe can use multiple dbufs, in both cases
> > we
> > +		 * account for other pipes only if they have exactly
> > same mask.
> > +		 * However we need to account how many slices we should
> > enable
> > +		 * in total.
> > +		 */
> > +		total_slice_mask |= pipe_dbuf_slice_mask;
> >  
> > -		if (!crtc_state->hw.enable)
> > +		/*
> > +		 * Do not account pipes using other slice sets
> > +		 * luckily as of current BSpec slice sets do not
> > partially
> > +		 * intersect(pipes share either same one slice or same
> > slice set
> > +		 * i.e no partial intersection), so it is enough to
> > check for
> > +		 * equality for now.
> > +		 */
> > +		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
> >  			continue;
> >  
> >  		drm_mode_get_hv_timing(adjusted_mode, &hdisplay,
> > &vdisplay);
> > @@ -3923,8 +4003,19 @@ skl_ddb_get_pipe_allocation_limits(struct
> > drm_i915_private *dev_priv,
> >  			pipe_width = hdisplay;
> >  	}
> >  
> > -	alloc->start = ddb_size * width_before_pipe / total_width;
> > -	alloc->end = ddb_size * (width_before_pipe + pipe_width) /
> > total_width;
> > +	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
> > +
> > +	start = ddb_range_size * width_before_pipe / total_width;
> > +	end = ddb_range_size * (width_before_pipe + pipe_width) /
> > total_width;
> > +
> > +	alloc->start = offset + start;
> > +	alloc->end = offset + end;
> > +
> > +	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
> > +		      alloc->start, alloc->end);
> > +	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
> > +		      intel_state->enabled_dbuf_slices_mask,
> > +		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
> >  }
> 
> That function really is quite the monster. Probably needs to be split
> up
> into sensible chunks... later.
> 
> >  
> >  static int skl_compute_wm_params(const struct intel_crtc_state
> > *crtc_state,
> > @@ -4094,6 +4185,121 @@ skl_plane_downscale_amount(const struct
> > intel_crtc_state *crtc_state,
> >  	return mul_fixed16(downscale_w, downscale_h);
> >  }
> >  
> > +struct dbuf_slice_conf_entry {
> > +	u32 active_pipes;
> > +	u32 dbuf_mask[I915_MAX_PIPES];
> 
> u8 will do for everything.
> 
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 12716
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
> 
> Still don't like that DBUF_S1_BIT. I still think it should be an
> enum dbuf_slice + explcit BIT(DBUF_S1) where needed.
> 
> And please use named initializers instead of sprinkling zeroes.
> IMO this should just look something like:
> 
> 	{ .active_pipes = BIT(PIPE_A) | BIT(PIPE_B),
> 	  .dbuf_slices = { [PIPE_A] = BIT(DBUF_S1),
> 	  		   [PIPE_B] = BIT(DBUF_S2),
> 			 },
> 	},
> 
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
> > +};
> > +
> > +/*
> > + * Table taken from Bspec 49255
> > + * Pipes do have some preferred DBuf slice affinity,
> > + * plus there are some hardcoded requirements on how
> > + * those should be distributed for multipipe scenarios.
> > + * For more DBuf slices algorithm can get even more messy
> > + * and less readable, so decided to use a table almost
> > + * as is from BSpec itself - that way it is at least easier
> > + * to compare, change and check.
> > + */
> > +static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
> > +	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
> > +	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
> > +	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 }
> > },
> > +	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT }
> > },
> > +	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> 
> I believe pipe C should use S1 here.

Ah it was actually already fixed in recent revision. Still we do need
to generate those with a tool I think.. I didn't use it here - and that
was the outcome..

The tools is here(wink): 
https://patchwork.freedesktop.org/series/70493/

Stan

> 
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
> > +	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
> > +		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT }
> > },
> > +};
> > +
> > +static u32 i915_find_pipe_conf(int pipe,
> 
> enum pipe pipe
> 
> > +			       u32 active_pipes,
> > +			       const struct dbuf_slice_conf_entry
> > *dbuf_slices,
> > +			       int size)
> 
> Could just add a sentinel to the end of the arrays and avoid this
> 'size' stuff.
> 
> The function name is still very confusing. icl_compute_dbuf_slices()
> or something perhaps. Or even without a prefix since it's static
> anyway.
> 
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < size; i++) {
> > +		if (dbuf_slices[i].active_pipes == active_pipes)
> > +			return dbuf_slices[i].dbuf_mask[pipe];
> > +	}
> > +	return 0;
> > +}
> > +
> > +/*
> > + * This function finds an entry with same enabled pipe
> > configuration and
> > + * returns correspondent DBuf slice mask as stated in BSpec for
> > particular
> > + * platform.
> > + */
> > +static u32 icl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   icl_allowed_dbufs,
> > +				   ARRAY_SIZE(icl_allowed_dbufs));
> > +}
> > +
> > +static u32 tgl_possible_dbuf_slices(int pipe,
> > +				    u32 active_pipes,
> > +				    const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	return i915_find_pipe_conf(pipe, active_pipes,
> > +				   tgl_allowed_dbufs,
> > +				   ARRAY_SIZE(tgl_allowed_dbufs));
> > +}
> 
> These wrappers aren't really doing anything for us.
> 
> > +
> > +u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
> 
> dev_priv and pipe are redundant parameters. Both
> can be extracted from crtc_state. I would put crtc_state as the first
> parameter. Matches common practice more closely.
> 
> s/i915/skl/ in the function name.
> 
> > +			      int pipe, u32 active_pipes,
> > +			      const struct intel_crtc_state
> > *crtc_state)
> > +{
> > +	if (IS_GEN(dev_priv, 11))
> > +		return icl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> > +	else if (IS_GEN(dev_priv, 12))
> > +		return tgl_possible_dbuf_slices(pipe,
> > +						active_pipes,
> > +						crtc_state);
> 
> The established convention is to go from new platforms
> to old platforms, if possible.
> 
> > +	/*
> > +	 * For anything else just return one slice yet.
> > +	 * Should be extended for other platforms.
> > +	 */
> > +	return DBUF_S1_BIT;
> > +}
> > +
> >  static u64
> >  skl_plane_relative_data_rate(const struct intel_crtc_state
> > *crtc_state,
> >  			     const struct intel_plane_state
> > *plane_state,
> > -- 
> > 2.17.1
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes
  2019-12-13 10:31 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
@ 2019-12-13 10:31 ` Stanislav Lisovskiy
  0 siblings, 0 replies; 23+ messages in thread
From: Stanislav Lisovskiy @ 2019-12-13 10:31 UTC (permalink / raw)
  To: intel-gfx

Added proper DBuf slice mapping to correspondent
pipes, depending on pipe configuration as stated
in BSpec.

v2:
    - Remove unneeded braces
    - Stop using macro for DBuf assignments as
      it seems to reduce readability.

v3: Start using enabled slices mask in dev_priv

v4: Renamed "enabled_slices" used in dev_priv
    to "enabled_dbuf_slices_mask"

Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 226 ++++++++++++++++++++++++++++++--
 1 file changed, 216 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5881752286a1..5de4e5f7ed18 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3815,13 +3815,30 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state)
 	return true;
 }
 
+/*
+ * Calculate initial DBuf slice offset, based on slice size
+ * and mask(i.e if slice size is 1024 and second slice is enabled
+ * offset would be 1024)
+ */
+static u32 icl_get_first_dbuf_slice_offset(u32 dbuf_slice_mask,
+					   u32 slice_size, u32 ddb_size)
+{
+	u32 offset = 0;
+
+	if (!dbuf_slice_mask)
+		return 0;
+
+	offset = (ffs(dbuf_slice_mask) - 1) * slice_size;
+
+	WARN_ON(offset >= ddb_size);
+	return offset;
+}
+
 static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 			      const struct intel_crtc_state *crtc_state,
 			      const u64 total_data_rate,
 			      const int num_active)
 {
-	struct drm_atomic_state *state = crtc_state->uapi.state;
-	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
 
 	WARN_ON(ddb_size == 0);
@@ -3829,12 +3846,13 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv,
 	if (INTEL_GEN(dev_priv) < 11)
 		return ddb_size - 4; /* 4 blocks for bypass path allocation */
 
-	intel_state->enabled_dbuf_slices_mask = DBUF_S1_BIT;
-	ddb_size /= 2;
-
 	return ddb_size;
 }
 
+u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
+			      int pipe, u32 active_pipes,
+			      const struct intel_crtc_state *crtc_state);
+
 static void
 skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 				   const struct intel_crtc_state *crtc_state,
@@ -3849,7 +3867,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 	u32 pipe_width = 0, total_width = 0, width_before_pipe = 0;
 	enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe;
 	u16 ddb_size;
+	u32 ddb_range_size;
 	u32 i;
+	u32 dbuf_slice_mask;
+	u32 active_pipes;
+	u32 offset;
+	u32 slice_size;
+	u32 total_slice_mask;
+	u32 start, end;
 
 	if (WARN_ON(!state) || !crtc_state->hw.active) {
 		alloc->start = 0;
@@ -3858,14 +3883,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	if (intel_state->active_pipe_changes)
+	if (intel_state->active_pipe_changes) {
 		*num_active = hweight8(intel_state->active_pipes);
-	else
+		active_pipes = intel_state->active_pipes;
+	} else {
 		*num_active = hweight8(dev_priv->active_pipes);
+		active_pipes = dev_priv->active_pipes;
+	}
 
 	ddb_size = intel_get_ddb_size(dev_priv, crtc_state, total_data_rate,
 				      *num_active);
 
+	slice_size = ddb_size / INTEL_INFO(dev_priv)->num_supported_dbuf_slices;
+
 	/*
 	 * If the state doesn't change the active CRTC's or there is no
 	 * modeset request, then there's no need to recalculate;
@@ -3883,18 +3913,68 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 		return;
 	}
 
+	/*
+	 * Get allowed DBuf slices for correspondent pipe and platform.
+	 */
+	dbuf_slice_mask = i915_possible_dbuf_slices(dev_priv, for_pipe,
+						    active_pipes, crtc_state);
+
+	DRM_DEBUG_KMS("DBuf slice mask %x pipe %d active pipes %x\n",
+		      dbuf_slice_mask,
+		      for_pipe, active_pipes);
+
+	/*
+	 * Figure out at which DBuf slice we start, i.e if we start at Dbuf S2
+	 * and slice size is 1024, the offset would be 1024
+	 */
+	offset = icl_get_first_dbuf_slice_offset(dbuf_slice_mask,
+						 slice_size, ddb_size);
+
+	/*
+	 * Figure out total size of allowed DBuf slices, which is basically
+	 * a number of allowed slices for that pipe multiplied by slice size.
+	 * Inside of this
+	 * range ddb entries are still allocated in proportion to display width.
+	 */
+	ddb_range_size = hweight8(dbuf_slice_mask) * slice_size;
+
 	/*
 	 * Watermark/ddb requirement highly depends upon width of the
 	 * framebuffer, So instead of allocating DDB equally among pipes
 	 * distribute DDB based on resolution/width of the display.
 	 */
+	total_slice_mask = dbuf_slice_mask;
 	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
 		const struct drm_display_mode *adjusted_mode =
 			&crtc_state->hw.adjusted_mode;
 		enum pipe pipe = crtc->pipe;
 		int hdisplay, vdisplay;
+		u32 pipe_dbuf_slice_mask =
+					i915_possible_dbuf_slices(dev_priv,
+								  pipe,
+								  active_pipes,
+								  crtc_state);
+
+		if (!crtc_state->hw.active)
+			continue;
+
+		/*
+		 * According to BSpec pipe can share one dbuf slice with another
+		 * pipes or pipe can use multiple dbufs, in both cases we
+		 * account for other pipes only if they have exactly same mask.
+		 * However we need to account how many slices we should enable
+		 * in total.
+		 */
+		total_slice_mask |= pipe_dbuf_slice_mask;
 
-		if (!crtc_state->hw.enable)
+		/*
+		 * Do not account pipes using other slice sets
+		 * luckily as of current BSpec slice sets do not partially
+		 * intersect(pipes share either same one slice or same slice set
+		 * i.e no partial intersection), so it is enough to check for
+		 * equality for now.
+		 */
+		if (dbuf_slice_mask != pipe_dbuf_slice_mask)
 			continue;
 
 		drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay);
@@ -3906,8 +3986,19 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv,
 			pipe_width = hdisplay;
 	}
 
-	alloc->start = ddb_size * width_before_pipe / total_width;
-	alloc->end = ddb_size * (width_before_pipe + pipe_width) / total_width;
+	intel_state->enabled_dbuf_slices_mask = total_slice_mask;
+
+	start = ddb_range_size * width_before_pipe / total_width;
+	end = ddb_range_size * (width_before_pipe + pipe_width) / total_width;
+
+	alloc->start = offset + start;
+	alloc->end = offset + end;
+
+	DRM_DEBUG_KMS("Pipe %d ddb %d-%d\n", for_pipe,
+		      alloc->start, alloc->end);
+	DRM_DEBUG_KMS("Enabled ddb slices mask %x num supported %d\n",
+		      intel_state->enabled_dbuf_slices_mask,
+		      INTEL_INFO(dev_priv)->num_supported_dbuf_slices);
 }
 
 static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
@@ -4077,6 +4168,121 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state,
 	return mul_fixed16(downscale_w, downscale_h);
 }
 
+struct dbuf_slice_conf_entry {
+	u32 active_pipes;
+	u32 dbuf_mask[I915_MAX_PIPES];
+};
+
+/*
+ * Table taken from Bspec 12716
+ * Pipes do have some preferred DBuf slice affinity,
+ * plus there are some hardcoded requirements on how
+ * those should be distributed for multipipe scenarios.
+ * For more DBuf slices algorithm can get even more messy
+ * and less readable, so decided to use a table almost
+ * as is from BSpec itself - that way it is at least easier
+ * to compare, change and check.
+ */
+static struct dbuf_slice_conf_entry icl_allowed_dbufs[] = {
+	{ BIT(PIPE_A), { DBUF_S1_BIT, 0, 0, 0 } },
+	{ BIT(PIPE_B), { 0, DBUF_S1_BIT, 0, 0 } },
+	{ BIT(PIPE_C), { 0, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S1_BIT, DBUF_S2_BIT, 0, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } }
+};
+
+/*
+ * Table taken from Bspec 49255
+ * Pipes do have some preferred DBuf slice affinity,
+ * plus there are some hardcoded requirements on how
+ * those should be distributed for multipipe scenarios.
+ * For more DBuf slices algorithm can get even more messy
+ * and less readable, so decided to use a table almost
+ * as is from BSpec itself - that way it is at least easier
+ * to compare, change and check.
+ */
+static struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = {
+	{ BIT(PIPE_A), { DBUF_S1_BIT | DBUF_S2_BIT, 0, 0, 0 } },
+	{ BIT(PIPE_B), { 0, DBUF_S1_BIT | DBUF_S2_BIT, 0, 0 } },
+	{ BIT(PIPE_C), { 0, 0, DBUF_S1_BIT | DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_D), { 0, 0, 0, DBUF_S1_BIT | DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B), { DBUF_S2_BIT, DBUF_S1_BIT, 0, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_C), { DBUF_S1_BIT, 0, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_D), { DBUF_S1_BIT, 0, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_B) | BIT(PIPE_C), { 0, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_B) | BIT(PIPE_D), { 0, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_C) | BIT(PIPE_D), { 0, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, 0 } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, 0, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, 0, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ 0, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
+	{ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D),
+		{ DBUF_S1_BIT, DBUF_S1_BIT, DBUF_S2_BIT, DBUF_S2_BIT } },
+};
+
+static u32 i915_find_pipe_conf(int pipe,
+			       u32 active_pipes,
+			       const struct dbuf_slice_conf_entry *dbuf_slices,
+			       int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (dbuf_slices[i].active_pipes == active_pipes)
+			return dbuf_slices[i].dbuf_mask[pipe];
+	}
+	return 0;
+}
+
+/*
+ * This function finds an entry with same enabled pipe configuration and
+ * returns correspondent DBuf slice mask as stated in BSpec for particular
+ * platform.
+ */
+static u32 icl_possible_dbuf_slices(int pipe,
+				    u32 active_pipes,
+				    const struct intel_crtc_state *crtc_state)
+{
+	return i915_find_pipe_conf(pipe, active_pipes,
+				   icl_allowed_dbufs,
+				   ARRAY_SIZE(icl_allowed_dbufs));
+}
+
+static u32 tgl_possible_dbuf_slices(int pipe,
+				    u32 active_pipes,
+				    const struct intel_crtc_state *crtc_state)
+{
+	return i915_find_pipe_conf(pipe, active_pipes,
+				   tgl_allowed_dbufs,
+				   ARRAY_SIZE(tgl_allowed_dbufs));
+}
+
+u32 i915_possible_dbuf_slices(struct drm_i915_private *dev_priv,
+			      int pipe, u32 active_pipes,
+			      const struct intel_crtc_state *crtc_state)
+{
+	if (IS_GEN(dev_priv, 11))
+		return icl_possible_dbuf_slices(pipe,
+						active_pipes,
+						crtc_state);
+	else if (IS_GEN(dev_priv, 12))
+		return tgl_possible_dbuf_slices(pipe,
+						active_pipes,
+						crtc_state);
+	/*
+	 * For anything else just return one slice yet.
+	 * Should be extended for other platforms.
+	 */
+	return DBUF_S1_BIT;
+}
+
 static u64
 skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
 			     const struct intel_plane_state *plane_state,
-- 
2.17.1

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

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

end of thread, other threads:[~2019-12-19 12:02 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-13 13:02 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 1/4] drm/i915: Remove skl_ddl_allocation struct Stanislav Lisovskiy
2019-12-13 16:59   ` Matt Roper
2019-12-18 18:01   ` Ville Syrjälä
2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 2/4] drm/i915: Move dbuf slice update to proper place Stanislav Lisovskiy
2019-12-13 17:08   ` Matt Roper
2019-12-18 18:12   ` Ville Syrjälä
2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 3/4] drm/i915: Manipulate DBuf slices properly Stanislav Lisovskiy
2019-12-13 19:01   ` Matt Roper
2019-12-16 15:07     ` Lisovskiy, Stanislav
2019-12-18 18:00   ` Ville Syrjälä
2019-12-19  9:13     ` Lisovskiy, Stanislav
2019-12-19  9:48       ` Ville Syrjälä
2019-12-19 11:30         ` Lisovskiy, Stanislav
2019-12-13 13:02 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy
2019-12-14  0:52   ` Matt Roper
2019-12-16 14:31     ` Lisovskiy, Stanislav
2019-12-18 18:05   ` Ville Syrjälä
2019-12-19 11:58     ` Lisovskiy, Stanislav
2019-12-19 12:02     ` Lisovskiy, Stanislav
2019-12-13 13:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success for Enable second DBuf slice for ICL and TGL (rev8) Patchwork
2019-12-14  7:04 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-12-13 10:31 [Intel-gfx] [PATCH v8 0/4] Enable second DBuf slice for ICL and TGL Stanislav Lisovskiy
2019-12-13 10:31 ` [Intel-gfx] [PATCH v8 4/4] drm/i915: Correctly map DBUF slices to pipes Stanislav Lisovskiy

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.