public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links
@ 2023-09-14 19:26 Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 01/25] drm/i915/dp: Factor out helpers to compute the link limits Imre Deak
                   ` (33 more replies)
  0 siblings, 34 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: Luca Coelho

This is v3 of [1] addressing the review comments, adding R-bs
and the following changes based on further testing / offline
discussions:

- Return -ENOSPC to userspace in case of a link BW limit
  failure. (Patch 9, thanks to Karthik B S for the related IGT
  testing)
- Replace fractional bpp fix with a patch from Ville. (Patch 12)
- Disable DSC PPS SDP during output disabling. (Patch 20, Ville)

[1] https://lore.kernel.org/intel-gfx/20230824080517.693621-1-imre.deak@intel.com

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Luca Coelho <luciano.coelho@intel.com>

Imre Deak (24):
  drm/i915/dp: Factor out helpers to compute the link limits
  drm/i915/dp: Track the pipe and link bpp limits separately
  drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
  drm/i915/dp: Update the link bpp limits for DSC mode
  drm/i915/dp: Limit the output link bpp in DSC mode
  drm/i915: Add helper to modeset a set of pipes
  drm/i915: During modeset forcing handle inactive but enabled pipes
  drm/i915: Factor out a helper to check/compute all the CRTC states
  drm/i915: Add helpers for BW management on shared display links
  drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  drm/i915/fdi: Recompute state for affected CRTCs on FDI links
  drm/dp_mst: Add a way to calculate PBN values with FEC overhead
  drm/dp_mst: Add helper to determine if an MST port is downstream of
    another port
  drm/dp_mst: Factor out a helper to check the atomic state of a
    topology manager
  drm/dp_mst: Swap the order of checking root vs. non-root port BW
    limitations
  drm/i915/dp_mst: Fix PBN calculation with FEC overhead
  drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  drm/i915/dp_mst: Program the DSC PPS SDP for each stream
  drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is
    disabled
  drm/i915/dp_mst: Enable DSC decompression if any stream needs this
  drm/i915/dp_mst: Add missing DSC compression disabling
  drm/i915/dp_mst: Allow DSC only for sink ports of the first branch
    device
  drm/i915/dp_mst: Improve BW sharing between MST streams
  drm/i915/dp_mst: Check BW limitations only after all streams are
    computed

Ville Syrjälä (1):
  drm/dp_mst: Fix fractional DSC bpp handling

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |   2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 181 ++++++++---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/g4x_hdmi.c       |   6 +-
 drivers/gpu/drm/i915/display/intel_cdclk.c    |   2 +-
 drivers/gpu/drm/i915/display/intel_crt.c      |   7 +
 drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
 drivers/gpu/drm/i915/display/intel_ddi.c      |  12 +-
 drivers/gpu/drm/i915/display/intel_display.c  | 203 +++++++++----
 drivers/gpu/drm/i915/display/intel_display.h  |   6 +-
 .../drm/i915/display/intel_display_types.h    |  26 +-
 drivers/gpu/drm/i915/display/intel_dp.c       | 196 +++++++++---
 drivers/gpu/drm/i915/display/intel_dp.h       |  17 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 287 +++++++++++++++---
 drivers/gpu/drm/i915/display/intel_dp_mst.h   |   3 +
 drivers/gpu/drm/i915/display/intel_fdi.c      | 140 +++++++--
 drivers/gpu/drm/i915/display/intel_fdi.h      |   5 +
 drivers/gpu/drm/i915/display/intel_link_bw.c  | 244 +++++++++++++++
 drivers/gpu/drm/i915/display/intel_link_bw.h  |  39 +++
 drivers/gpu/drm/i915/display/intel_lvds.c     |  10 +-
 drivers/gpu/drm/i915/display/intel_sdvo.c     |  10 +-
 drivers/gpu/drm/i915/display/skl_watermark.c  |   2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |   3 +-
 .../gpu/drm/tests/drm_dp_mst_helper_test.c    |  19 +-
 include/drm/display/drm_dp_mst_helper.h       |   9 +-
 26 files changed, 1203 insertions(+), 230 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h

-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 01/25] drm/i915/dp: Factor out helpers to compute the link limits
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 02/25] drm/i915/dp: Track the pipe and link bpp limits separately Imre Deak
                   ` (32 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Factor out helpers that DP / DP_MST encoders can use to compute the link
rate/lane count and bpp limits. A follow-up patch will call these to
recalculate the limits if DSC compression is required.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 61 +++++++++++++--------
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 52 ++++++++++--------
 2 files changed, 68 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 55ba6eeaa810d..78984d5126bbe 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2188,29 +2188,25 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static int
-intel_dp_compute_link_config(struct intel_encoder *encoder,
-			     struct intel_crtc_state *pipe_config,
-			     struct drm_connector_state *conn_state,
-			     bool respect_downstream_limits)
+static void
+intel_dp_compute_config_limits(struct intel_dp *intel_dp,
+			       struct intel_crtc_state *crtc_state,
+			       bool respect_downstream_limits,
+			       struct link_config_limits *limits)
 {
-	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	const struct drm_display_mode *adjusted_mode =
-		&pipe_config->hw.adjusted_mode;
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct link_config_limits limits;
-	bool joiner_needs_dsc = false;
-	int ret;
+		&crtc_state->hw.adjusted_mode;
 
-	limits.min_rate = intel_dp_common_rate(intel_dp, 0);
-	limits.max_rate = intel_dp_max_link_rate(intel_dp);
+	limits->min_rate = intel_dp_common_rate(intel_dp, 0);
+	limits->max_rate = intel_dp_max_link_rate(intel_dp);
 
-	limits.min_lane_count = 1;
-	limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
+	limits->min_lane_count = 1;
+	limits->max_lane_count = intel_dp_max_lane_count(intel_dp);
 
-	limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
-	limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config, respect_downstream_limits);
+	limits->min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+	limits->max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
+					   respect_downstream_limits);
 
 	if (intel_dp->use_max_params) {
 		/*
@@ -2221,16 +2217,35 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 		 * configuration, and typically on older panels these
 		 * values correspond to the native resolution of the panel.
 		 */
-		limits.min_lane_count = limits.max_lane_count;
-		limits.min_rate = limits.max_rate;
+		limits->min_lane_count = limits->max_lane_count;
+		limits->min_rate = limits->max_rate;
 	}
 
-	intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
+	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
 	drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
 		    "max rate %d max bpp %d pixel clock %iKHz\n",
-		    limits.max_lane_count, limits.max_rate,
-		    limits.max_bpp, adjusted_mode->crtc_clock);
+		    limits->max_lane_count, limits->max_rate,
+		    limits->max_bpp, adjusted_mode->crtc_clock);
+}
+
+static int
+intel_dp_compute_link_config(struct intel_encoder *encoder,
+			     struct intel_crtc_state *pipe_config,
+			     struct drm_connector_state *conn_state,
+			     bool respect_downstream_limits)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	const struct drm_display_mode *adjusted_mode =
+		&pipe_config->hw.adjusted_mode;
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct link_config_limits limits;
+	bool joiner_needs_dsc = false;
+	int ret;
+
+	intel_dp_compute_config_limits(intel_dp, pipe_config,
+				       respect_downstream_limits, &limits);
 
 	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
 				    adjusted_mode->crtc_clock))
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 1c7f0b6afe475..f4fcfc6926881 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -293,6 +293,35 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
 	return 0;
 }
 
+static void
+intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
+				   struct intel_crtc_state *crtc_state,
+				   struct link_config_limits *limits)
+{
+	/*
+	 * for MST we always configure max link bw - the spec doesn't
+	 * seem to suggest we should do otherwise.
+	 */
+	limits->min_rate = limits->max_rate =
+		intel_dp_max_link_rate(intel_dp);
+
+	limits->min_lane_count = limits->max_lane_count =
+		intel_dp_max_lane_count(intel_dp);
+
+	limits->min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+	/*
+	 * FIXME: If all the streams can't fit into the link with
+	 * their current pipe_bpp we should reduce pipe_bpp across
+	 * the board until things start to fit. Until then we
+	 * limit to <= 8bpc since that's what was hardcoded for all
+	 * MST streams previously. This hack should be removed once
+	 * we have the proper retry logic in place.
+	 */
+	limits->max_bpp = min(crtc_state->pipe_bpp, 24);
+
+	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
+}
+
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 				       struct intel_crtc_state *pipe_config,
 				       struct drm_connector_state *conn_state)
@@ -312,28 +341,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->has_pch_encoder = false;
 
-	/*
-	 * for MST we always configure max link bw - the spec doesn't
-	 * seem to suggest we should do otherwise.
-	 */
-	limits.min_rate =
-	limits.max_rate = intel_dp_max_link_rate(intel_dp);
-
-	limits.min_lane_count =
-	limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
-
-	limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
-	/*
-	 * FIXME: If all the streams can't fit into the link with
-	 * their current pipe_bpp we should reduce pipe_bpp across
-	 * the board until things start to fit. Until then we
-	 * limit to <= 8bpc since that's what was hardcoded for all
-	 * MST streams previously. This hack should be removed once
-	 * we have the proper retry logic in place.
-	 */
-	limits.max_bpp = min(pipe_config->pipe_bpp, 24);
-
-	intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
+	intel_dp_mst_compute_config_limits(intel_dp, pipe_config, &limits);
 
 	ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
 					       conn_state, &limits);
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 02/25] drm/i915/dp: Track the pipe and link bpp limits separately
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 01/25] drm/i915/dp: Factor out helpers to compute the link limits Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 03/25] drm/i915/dp: Skip computing a non-DSC link config if DSC is needed Imre Deak
                   ` (31 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: Luca Coelho

A follow-up patch will need to limit the output link bpp both in the
non-DSC and DSC configuration, so track the pipe and link bpp limits
separately in the link_config_limits struct.

Use .4 fixed point format for link bpp matching the 1/16 bpp granularity
in DSC mode and for now keep this limit matching the pipe bpp limit.

v2: (Jani)
- Add to_bpp_int(), to_bpp_x16() helpers instead of opencoding them.
- Rename link_config_limits::link.min/max_bpp to min/max_bpp_x16.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../drm/i915/display/intel_display_types.h    | 10 +++++++
 drivers/gpu/drm/i915/display/intel_dp.c       | 27 +++++++++++--------
 drivers/gpu/drm/i915/display/intel_dp.h       |  9 ++++++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 17 +++++++-----
 4 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 4b807c377166e..bdad675e03fb8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -2110,4 +2110,14 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
 	return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
 }
 
+static inline int to_bpp_int(int bpp_x16)
+{
+	return bpp_x16 >> 4;
+}
+
+static inline int to_bpp_x16(int bpp)
+{
+	return bpp << 4;
+}
+
 #endif /*  __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 78984d5126bbe..5fd32280eab2f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1470,7 +1470,7 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
 	if (intel_dp->compliance.test_data.bpc != 0) {
 		int bpp = 3 * intel_dp->compliance.test_data.bpc;
 
-		limits->min_bpp = limits->max_bpp = bpp;
+		limits->pipe.min_bpp = limits->pipe.max_bpp = bpp;
 		pipe_config->dither_force_disable = bpp == 6 * 3;
 
 		drm_dbg_kms(&i915->drm, "Setting pipe_bpp to %d\n", bpp);
@@ -1532,7 +1532,9 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
 	int bpp, i, lane_count, clock = intel_dp_mode_clock(pipe_config, conn_state);
 	int mode_rate, link_rate, link_avail;
 
-	for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
+	for (bpp = to_bpp_int(limits->link.max_bpp_x16);
+	     bpp >= to_bpp_int(limits->link.min_bpp_x16);
+	     bpp -= 2 * 3) {
 		int link_bpp = intel_dp_output_bpp(pipe_config->output_format, bpp);
 
 		mode_rate = intel_dp_link_required(clock, link_bpp);
@@ -1958,8 +1960,8 @@ bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private *i915,
 	dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), conn_state->max_requested_bpc);
 	dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
 
-	dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->max_bpp);
-	dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->min_bpp);
+	dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
+	dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
 	return pipe_bpp >= dsc_min_pipe_bpp &&
 	       pipe_bpp <= dsc_max_pipe_bpp;
@@ -2019,10 +2021,10 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
 		return -EINVAL;
 
 	dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
-	dsc_max_bpp = min(dsc_max_bpc * 3, limits->max_bpp);
+	dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
 
 	dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
-	dsc_min_bpp = max(dsc_min_bpc * 3, limits->min_bpp);
+	dsc_min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
 
 	/*
 	 * Get the maximum DSC bpc that will be supported by any valid
@@ -2061,7 +2063,7 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
 	if (forced_bpp) {
 		pipe_bpp = forced_bpp;
 	} else {
-		int max_bpc = min(limits->max_bpp / 3, (int)conn_state->max_requested_bpc);
+		int max_bpc = min(limits->pipe.max_bpp / 3, (int)conn_state->max_requested_bpc);
 
 		/* For eDP use max bpp that can be supported with DSC. */
 		pipe_bpp = intel_dp_dsc_compute_max_bpp(intel_dp, max_bpc);
@@ -2204,9 +2206,9 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
 	limits->min_lane_count = 1;
 	limits->max_lane_count = intel_dp_max_lane_count(intel_dp);
 
-	limits->min_bpp = intel_dp_min_bpp(crtc_state->output_format);
-	limits->max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
-					   respect_downstream_limits);
+	limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+	limits->pipe.max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
+						     respect_downstream_limits);
 
 	if (intel_dp->use_max_params) {
 		/*
@@ -2223,10 +2225,13 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
 
 	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
+	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
+	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+
 	drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
 		    "max rate %d max bpp %d pixel clock %iKHz\n",
 		    limits->max_lane_count, limits->max_rate,
-		    limits->max_bpp, adjusted_mode->crtc_clock);
+		    to_bpp_int(limits->link.max_bpp_x16), adjusted_mode->crtc_clock);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index b34ddc9c352a4..98c60ab6e182e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -26,7 +26,14 @@ struct intel_encoder;
 struct link_config_limits {
 	int min_rate, max_rate;
 	int min_lane_count, max_lane_count;
-	int min_bpp, max_bpp;
+	struct {
+		/* Uncompressed DSC input or link output bpp in 1 bpp units */
+		int min_bpp, max_bpp;
+	} pipe;
+	struct {
+		/* Compressed or uncompressed link output bpp in 1/16 bpp units */
+		int min_bpp_x16, max_bpp_x16;
+	} link;
 };
 
 void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f4fcfc6926881..69342bce6953d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -157,8 +157,10 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
 	int slots = -EINVAL;
 	int link_bpp;
 
-	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp,
-						     limits->min_bpp, limits,
+	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
+						     to_bpp_int(limits->link.max_bpp_x16),
+						     to_bpp_int(limits->link.min_bpp_x16),
+						     limits,
 						     conn_state, 2 * 3, false);
 
 	if (slots < 0)
@@ -203,8 +205,8 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
 	else
 		dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
 
-	max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp);
-	min_bpp = limits->min_bpp;
+	max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
+	min_bpp = limits->pipe.min_bpp;
 
 	num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
 						       dsc_bpc);
@@ -308,7 +310,7 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
 	limits->min_lane_count = limits->max_lane_count =
 		intel_dp_max_lane_count(intel_dp);
 
-	limits->min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+	limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format);
 	/*
 	 * FIXME: If all the streams can't fit into the link with
 	 * their current pipe_bpp we should reduce pipe_bpp across
@@ -317,9 +319,12 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
 	 * MST streams previously. This hack should be removed once
 	 * we have the proper retry logic in place.
 	 */
-	limits->max_bpp = min(crtc_state->pipe_bpp, 24);
+	limits->pipe.max_bpp = min(crtc_state->pipe_bpp, 24);
 
 	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
+
+	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
+	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
 }
 
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 03/25] drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 01/25] drm/i915/dp: Factor out helpers to compute the link limits Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 02/25] drm/i915/dp: Track the pipe and link bpp limits separately Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode Imre Deak
                   ` (30 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Computing the non-DSC mode link config is redundant once it's determined
that DSC will be needed, so skip computing it. In a follow-up patch this
simplifies setting the link limits which are dependent on the DSC vs.
non-DSC mode.

While at it sanitize the debug print about the MST DSC fallback path,
making it similar to the SST DSC one.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 22 ++++++++++++------
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 25 +++++++++++++++------
 2 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 5fd32280eab2f..bdaaad34463fb 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2247,7 +2247,8 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct link_config_limits limits;
 	bool joiner_needs_dsc = false;
-	int ret;
+	bool dsc_needed;
+	int ret = 0;
 
 	intel_dp_compute_config_limits(intel_dp, pipe_config,
 				       respect_downstream_limits, &limits);
@@ -2263,13 +2264,20 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	 */
 	joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
 
-	/*
-	 * Optimize for slow and wide for everything, because there are some
-	 * eDP 1.3 and 1.4 panels don't work well with fast and narrow.
-	 */
-	ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, conn_state, &limits);
+	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en;
 
-	if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) {
+	if (!dsc_needed) {
+		/*
+		 * Optimize for slow and wide for everything, because there are some
+		 * eDP 1.3 and 1.4 panels don't work well with fast and narrow.
+		 */
+		ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
+							conn_state, &limits);
+		if (ret)
+			dsc_needed = true;
+	}
+
+	if (dsc_needed) {
 		drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
 			    str_yes_no(ret), str_yes_no(joiner_needs_dsc),
 			    str_yes_no(intel_dp->force_dsc_en));
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 69342bce6953d..2a0f2caf5b8d7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -337,7 +337,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	const struct drm_display_mode *adjusted_mode =
 		&pipe_config->hw.adjusted_mode;
 	struct link_config_limits limits;
-	int ret;
+	bool dsc_needed;
+	int ret = 0;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
@@ -348,15 +349,25 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 
 	intel_dp_mst_compute_config_limits(intel_dp, pipe_config, &limits);
 
-	ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
-					       conn_state, &limits);
+	dsc_needed = intel_dp->force_dsc_en;
 
-	if (ret == -EDEADLK)
-		return ret;
+	if (!dsc_needed) {
+		ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
+						       conn_state, &limits);
+
+		if (ret == -EDEADLK)
+			return ret;
+
+		if (ret)
+			dsc_needed = true;
+	}
 
 	/* enable compression if the mode doesn't fit available BW */
-	drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
-	if (ret || intel_dp->force_dsc_en) {
+	if (dsc_needed) {
+		drm_dbg_kms(&dev_priv->drm, "Try DSC (fallback=%s, force=%s)\n",
+			    str_yes_no(ret),
+			    str_yes_no(intel_dp->force_dsc_en));
+
 		/*
 		 * FIXME: As bpc is hardcoded to 8, as mentioned above,
 		 * WARN and ignore the debug flag force_dsc_bpc for now.
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (2 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 03/25] drm/i915/dp: Skip computing a non-DSC link config if DSC is needed Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-19 14:48   ` Ville Syrjälä
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in " Imre Deak
                   ` (29 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

In non-DSC mode the link bpp can be set in 2*3 bpp steps in the pipe bpp
range, while in DSC mode it can be set in 1/16 bpp steps to any value
up to the maximum pipe bpp. Update the limits accordingly in both modes
to prepare for a follow-up patch which may need to reduce the max link
bpp value and starts to check the link bpp limits in DSC mode as well.

While at it add more detail to the link limit debug print and print it
also for DSC mode.

v2:
- Add to_bpp_frac_dec() instead of open coding it. (Jani)
v3: (Ville)
- Add BPP_X16_FMT / BPP_X16_ARG.
- Add TODO: comment about initializing the DSC link bpp limits earlier.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  8 ++
 drivers/gpu/drm/i915/display/intel_dp.c       | 93 +++++++++++++++----
 drivers/gpu/drm/i915/display/intel_dp.h       |  6 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 23 +++--
 4 files changed, 108 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index bdad675e03fb8..50fe8ff354137 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -2115,6 +2115,14 @@ static inline int to_bpp_int(int bpp_x16)
 	return bpp_x16 >> 4;
 }
 
+static inline int to_bpp_frac(int bpp_x16)
+{
+	return bpp_x16 & 0xf;
+}
+
+#define BPP_X16_FMT		"%d.%04d"
+#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
+
 static inline int to_bpp_x16(int bpp)
 {
 	return bpp << 4;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index bdaaad34463fb..2a45eefc83ebf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2190,16 +2190,72 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static void
+/**
+ * intel_dp_compute_config_link_bpp_limits - compute output link bpp limits
+ * @intel_dp: intel DP
+ * @crtc_state: crtc state
+ * @dsc: DSC compression mode
+ * @limits: link configuration limits
+ *
+ * Calculates the output link min, max bpp values in @limits based on the
+ * pipe bpp range, @crtc_state and @dsc mode.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
+					const struct intel_crtc_state *crtc_state,
+					bool dsc,
+					struct link_config_limits *limits)
+{
+	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+	const struct drm_display_mode *adjusted_mode =
+		&crtc_state->hw.adjusted_mode;
+	const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+	int max_link_bpp_x16;
+
+	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+
+	if (!dsc) {
+		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
+
+		if (max_link_bpp_x16 < to_bpp_x16(limits->pipe.min_bpp))
+			return false;
+
+		limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
+	} else {
+		/*
+		 * TODO: set the DSC link limits already here, atm these are
+		 * initialized only later in intel_edp_dsc_compute_pipe_bpp() /
+		 * intel_dp_dsc_compute_pipe_bpp()
+		 */
+		limits->link.min_bpp_x16 = 0;
+	}
+
+	limits->link.max_bpp_x16 = max_link_bpp_x16;
+
+	drm_dbg_kms(&i915->drm,
+		    "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",
+		    encoder->base.base.id, encoder->base.name,
+		    crtc->base.base.id, crtc->base.name,
+		    adjusted_mode->crtc_clock,
+		    dsc ? "on" : "off",
+		    limits->max_lane_count,
+		    limits->max_rate,
+		    limits->pipe.max_bpp,
+		    BPP_X16_ARGS(limits->link.max_bpp_x16));
+
+	return true;
+}
+
+static bool
 intel_dp_compute_config_limits(struct intel_dp *intel_dp,
 			       struct intel_crtc_state *crtc_state,
 			       bool respect_downstream_limits,
+			       bool dsc,
 			       struct link_config_limits *limits)
 {
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-	const struct drm_display_mode *adjusted_mode =
-		&crtc_state->hw.adjusted_mode;
-
 	limits->min_rate = intel_dp_common_rate(intel_dp, 0);
 	limits->max_rate = intel_dp_max_link_rate(intel_dp);
 
@@ -2225,13 +2281,10 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
 
 	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
-	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
-	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
-
-	drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
-		    "max rate %d max bpp %d pixel clock %iKHz\n",
-		    limits->max_lane_count, limits->max_rate,
-		    to_bpp_int(limits->link.max_bpp_x16), adjusted_mode->crtc_clock);
+	return intel_dp_compute_config_link_bpp_limits(intel_dp,
+						       crtc_state,
+						       dsc,
+						       limits);
 }
 
 static int
@@ -2250,9 +2303,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	bool dsc_needed;
 	int ret = 0;
 
-	intel_dp_compute_config_limits(intel_dp, pipe_config,
-				       respect_downstream_limits, &limits);
-
 	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
 				    adjusted_mode->crtc_clock))
 		pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
@@ -2264,7 +2314,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	 */
 	joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
 
-	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en;
+	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
+		     !intel_dp_compute_config_limits(intel_dp, pipe_config,
+						     respect_downstream_limits,
+						     false,
+						     &limits);
 
 	if (!dsc_needed) {
 		/*
@@ -2281,6 +2335,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 		drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
 			    str_yes_no(ret), str_yes_no(joiner_needs_dsc),
 			    str_yes_no(intel_dp->force_dsc_en));
+
+		if (!intel_dp_compute_config_limits(intel_dp, pipe_config,
+						    respect_downstream_limits,
+						    true,
+						    &limits))
+			return -EINVAL;
+
 		ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
 						  conn_state, &limits, 64, true);
 		if (ret < 0)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 98c60ab6e182e..2cf3681bac64a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -156,4 +156,10 @@ void intel_dp_phy_test(struct intel_encoder *encoder);
 void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
 int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
 
+bool
+intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
+					const struct intel_crtc_state *crtc_state,
+					bool dsc,
+					struct link_config_limits *limits);
+
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2a0f2caf5b8d7..7d84689d69fad 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -295,9 +295,10 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
 	return 0;
 }
 
-static void
+static bool
 intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
 				   struct intel_crtc_state *crtc_state,
+				   bool dsc,
 				   struct link_config_limits *limits)
 {
 	/*
@@ -323,8 +324,10 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
 
 	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
-	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
-	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+	return intel_dp_compute_config_link_bpp_limits(intel_dp,
+						       crtc_state,
+						       dsc,
+						       limits);
 }
 
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
@@ -347,9 +350,11 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->has_pch_encoder = false;
 
-	intel_dp_mst_compute_config_limits(intel_dp, pipe_config, &limits);
-
-	dsc_needed = intel_dp->force_dsc_en;
+	dsc_needed = intel_dp->force_dsc_en ||
+		     !intel_dp_mst_compute_config_limits(intel_dp,
+							 pipe_config,
+							 false,
+							 &limits);
 
 	if (!dsc_needed) {
 		ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
@@ -368,6 +373,12 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 			    str_yes_no(ret),
 			    str_yes_no(intel_dp->force_dsc_en));
 
+		if (!intel_dp_mst_compute_config_limits(intel_dp,
+							pipe_config,
+							true,
+							&limits))
+			return -EINVAL;
+
 		/*
 		 * FIXME: As bpc is hardcoded to 8, as mentioned above,
 		 * WARN and ignore the debug flag force_dsc_bpc for now.
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in DSC mode
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (3 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-19 14:49   ` Ville Syrjälä
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes Imre Deak
                   ` (28 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Limit the output link bpp in DSC mode to the link_config_limits
link.min_bpp_x16 .. max_bpp_x16 range the same way it's done in non-DSC
mode.  Atm this doesn't make a difference, the link bpp range being
0 .. max pipe bpp, but a follow-up patch will need a way to reduce max
link bpp below its current value.

v2:
- Add to_bpp_int_roundup() instead of open coding it. (Jani)

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_types.h | 5 +++++
 drivers/gpu/drm/i915/display/intel_dp.c            | 4 ++++
 drivers/gpu/drm/i915/display/intel_dp_mst.c        | 3 +++
 3 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 50fe8ff354137..966163ccbd7a3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -2123,6 +2123,11 @@ static inline int to_bpp_frac(int bpp_x16)
 #define BPP_X16_FMT		"%d.%04d"
 #define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
 
+static inline int to_bpp_int_roundup(int bpp_x16)
+{
+	return (bpp_x16 + 0xf) >> 4;
+}
+
 static inline int to_bpp_x16(int bpp)
 {
 	return bpp << 4;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2a45eefc83ebf..d5e6813d36c8f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1925,6 +1925,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
 	dsc_src_min_bpp = dsc_src_min_compressed_bpp();
 	dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
 	dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
+	dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
 
 	dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
 	dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(intel_dp, pipe_config, pipe_bpp / 3);
@@ -1934,6 +1935,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
 								adjusted_mode->hdisplay,
 								pipe_config->bigjoiner_pipes);
 	dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
+	dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
 
 	if (DISPLAY_VER(i915) >= 13)
 		return xelpd_dsc_compute_link_config(intel_dp, pipe_config, limits,
@@ -2079,10 +2081,12 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
 	dsc_src_min_bpp = dsc_src_min_compressed_bpp();
 	dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
 	dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
+	dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
 
 	dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
 	dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(intel_dp, pipe_config, pipe_bpp / 3);
 	dsc_max_bpp = dsc_sink_max_bpp ? min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp;
+	dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
 
 	/* Compressed BPP should be less than the Input DSC bpp */
 	dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 7d84689d69fad..d38d0dd23fc39 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -233,6 +233,9 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
 	if (max_bpp > sink_max_bpp)
 		max_bpp = sink_max_bpp;
 
+	min_bpp = max(min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
+	max_bpp = min(max_bpp, to_bpp_int(limits->link.max_bpp_x16));
+
 	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp,
 						     min_bpp, limits,
 						     conn_state, 2 * 3, true);
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (4 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in " Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-15 18:34   ` Ville Syrjälä
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 07/25] drm/i915: During modeset forcing handle inactive but enabled pipes Imre Deak
                   ` (27 subsequent siblings)
  33 siblings, 2 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Add intel_modeset_pipes_in_mask_early() to modeset a provided set of
pipes, used in a follow-up patch.

While at it add _late suffix to intel_modeset_all_pipes() for clarity
and add DocBook descriptions for the two exported functions.

v2:
- Add a flag controlling if active planes are force updated as well.
- Add DockBook descriptions.
v3:
- For clarity use _early/_late suffixes for the exported functions
  instead of the update_active_planes parameter. (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_cdclk.c   |  2 +-
 drivers/gpu/drm/i915/display/intel_display.c | 45 ++++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_display.h |  6 ++-
 drivers/gpu/drm/i915/display/skl_watermark.c |  2 +-
 4 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index ad5251ba6fe13..a2e20b25d6361 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -3139,7 +3139,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
 	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
 					     &new_cdclk_state->actual)) {
 		/* All pipes must be switched off while we change the cdclk. */
-		ret = intel_modeset_all_pipes(state, "CDCLK change");
+		ret = intel_modeset_all_pipes_late(state, "CDCLK change");
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 6bbc9069754c4..27e6ea21e0a91 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5407,8 +5407,9 @@ intel_verify_planes(struct intel_atomic_state *state)
 			     plane_state->uapi.visible);
 }
 
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason)
+static int intel_modeset_pipes_in_mask(struct intel_atomic_state *state,
+				       const char *reason, u8 mask,
+				       bool update_active_planes)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc *crtc;
@@ -5417,7 +5418,7 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 	 * Add all pipes to the state, and force
 	 * a modeset on all the active ones.
 	 */
-	for_each_intel_crtc(&dev_priv->drm, crtc) {
+	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, mask) {
 		struct intel_crtc_state *crtc_state;
 		int ret;
 
@@ -5448,7 +5449,9 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 		if (ret)
 			return ret;
 
-		crtc_state->update_planes |= crtc_state->active_planes;
+		if (update_active_planes)
+			crtc_state->update_planes |= crtc_state->active_planes;
+
 		crtc_state->async_flip_planes = 0;
 		crtc_state->do_async_flip = false;
 	}
@@ -5456,6 +5459,40 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 	return 0;
 }
 
+/**
+ * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ * @mask: mask of pipes to modeset
+ *
+ * Force a full modeset on pipes in @mask due to the description in @reason.
+ * This function can be called only before new plane states are computed.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+				      const char *reason, u8 mask)
+{
+	return intel_modeset_pipes_in_mask(state, reason, mask, false);
+}
+
+/**
+ * intel_modeset_all_pipes_late - force a full modeset on all pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ *
+ * Force a full modeset on all pipes due to the description in @reason.
+ * This function can be called only after new plane states are computed
+ * already.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+				 const char *reason)
+{
+	return intel_modeset_pipes_in_mask(state, reason, -1, true);
+}
+
 /*
  * This implements the workaround described in the "notes" section of the mode
  * set sequence documentation. When going from no pipes or single pipe to
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 49ac8473b988b..64a5be7859331 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -513,8 +513,10 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
 void intel_update_watermarks(struct drm_i915_private *i915);
 
 /* modesetting */
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason);
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+				      const char *reason, u8 pipe_mask);
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+				 const char *reason);
 void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
 					  struct intel_power_domain_mask *old_domains);
 void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 063929a42a42f..a29d9b717deed 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2616,7 +2616,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
 
 		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
 			/* TODO: Implement vblank synchronized MBUS joining changes */
-			ret = intel_modeset_all_pipes(state, "MBUS joining change");
+			ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
 			if (ret)
 				return ret;
 		}
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 07/25] drm/i915: During modeset forcing handle inactive but enabled pipes
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (5 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 07/25] drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late() Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 08/25] drm/i915: Factor out a helper to check/compute all the CRTC states Imre Deak
                   ` (26 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

When forcing a modeset after a BW limit check to recompute the state of
all CRTCs on a link shared by the CRTCs, inactive but otherwise enabled
(aka DPMS off) CRTCs must be also modeset as their BW requirement may
need to be decreased.

Based on the above force-modeset inactive but enabled CRTCs as well as
required. For the current force modeset scenarios (for instance CDCLK
change) this won't make a difference, as during HW programming the
inactive CRTCs are skipped even though they are marked for a modeset.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 27e6ea21e0a91..44abe583a672d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5426,7 +5426,7 @@ static int intel_modeset_pipes_in_mask(struct intel_atomic_state *state,
 		if (IS_ERR(crtc_state))
 			return PTR_ERR(crtc_state);
 
-		if (!crtc_state->hw.active ||
+		if (!crtc_state->hw.enable ||
 		    intel_crtc_needs_modeset(crtc_state))
 			continue;
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 08/25] drm/i915: Factor out a helper to check/compute all the CRTC states
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (6 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 07/25] drm/i915: During modeset forcing handle inactive but enabled pipes Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 09/25] drm/i915: Add helpers for BW management on shared display links Imre Deak
                   ` (25 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Factor out intel_atomic_check_config() to check and compute all the CRTC
states. This will be used by a follow up patch to recompute/check the
state until required by BW limitations between CRTCs.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 78 ++++++++++++--------
 1 file changed, 46 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 44abe583a672d..fe3b6844e063d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6195,6 +6195,51 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
+static int intel_atomic_check_config(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc_state *new_crtc_state;
+	struct intel_crtc *crtc;
+	int ret;
+	int i;
+
+	ret = intel_bigjoiner_add_affected_crtcs(state);
+	if (ret)
+		return ret;
+
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		if (!intel_crtc_needs_modeset(new_crtc_state)) {
+			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
+				copy_bigjoiner_crtc_state_nomodeset(state, crtc);
+			else
+				intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
+			continue;
+		}
+
+		if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
+			drm_WARN_ON(&i915->drm, new_crtc_state->uapi.enable);
+			continue;
+		}
+
+		ret = intel_crtc_prepare_cleared_state(state, crtc);
+		if (ret)
+			break;
+
+		if (!new_crtc_state->hw.enable)
+			continue;
+
+		ret = intel_modeset_pipe_config(state, crtc);
+		if (ret)
+			break;
+
+		ret = intel_atomic_check_bigjoiner(state, crtc);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -6239,41 +6284,10 @@ int intel_atomic_check(struct drm_device *dev,
 			return ret;
 	}
 
-	ret = intel_bigjoiner_add_affected_crtcs(state);
+	ret = intel_atomic_check_config(state);
 	if (ret)
 		goto fail;
 
-	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
-					    new_crtc_state, i) {
-		if (!intel_crtc_needs_modeset(new_crtc_state)) {
-			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
-				copy_bigjoiner_crtc_state_nomodeset(state, crtc);
-			else
-				intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
-			continue;
-		}
-
-		if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
-			drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable);
-			continue;
-		}
-
-		ret = intel_crtc_prepare_cleared_state(state, crtc);
-		if (ret)
-			goto fail;
-
-		if (!new_crtc_state->hw.enable)
-			continue;
-
-		ret = intel_modeset_pipe_config(state, crtc);
-		if (ret)
-			goto fail;
-
-		ret = intel_atomic_check_bigjoiner(state, crtc);
-		if (ret)
-			goto fail;
-	}
-
 	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
 					    new_crtc_state, i) {
 		if (!intel_crtc_needs_modeset(new_crtc_state))
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (7 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 08/25] drm/i915: Factor out a helper to check/compute all the CRTC states Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-15  0:33   ` [Intel-gfx] [PATCH v4 " Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C Imre Deak
                   ` (24 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

At the moment a modeset fails if the config computation of a pipe can't
fit its required BW to the available link BW even though the limitation
may be resolved by reducing the BW requirement of other pipes.

To improve the above this patch adds helper functions checking the
overall BW limits after all CRTC states have been computed. If the check
fails the maximum link bpp for a selected pipe will be reduced and all
the CRTC states will be recomputed until either the overall BW limit
check passes, or further bpp reduction is not possible (because all
pipes/encoders sharing the link BW reached their minimum link bpp).

This change prepares for upcoming patches enabling the above BW
management on FDI and MST links.

v2:
- Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
  intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
v3:
- Add the helper functions in a separate patch. (Ville)
- Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
- Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
  limit failure.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  61 ++++-
 .../drm/i915/display/intel_display_types.h    |   3 +-
 drivers/gpu/drm/i915/display/intel_link_bw.c  | 226 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
 6 files changed, 325 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1b2e02e9d92cb..de4967c141f00 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -268,6 +268,7 @@ i915-y += \
 	display/intel_hotplug.o \
 	display/intel_hotplug_irq.o \
 	display/intel_hti.o \
+	display/intel_link_bw.o \
 	display/intel_load_detect.o \
 	display/intel_lpe_audio.o \
 	display/intel_modeset_lock.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 182c6dd64f47c..1eda6a9f19aa8 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
 	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
 	crtc_state->scaler_state.scaler_id = -1;
 	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+	crtc_state->max_link_bpp_x16 = INT_MAX;
 }
 
 static struct intel_crtc *intel_crtc_alloc(void)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index fe3b6844e063d..29816153fdd59 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -87,6 +87,7 @@
 #include "intel_frontbuffer.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_modeset_setup.h"
@@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
 
 static int
 intel_modeset_pipe_config(struct intel_atomic_state *state,
-			  struct intel_crtc *crtc)
+			  struct intel_crtc *crtc,
+			  const struct intel_link_bw_limits *limits)
 {
 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
 	struct intel_crtc_state *crtc_state =
@@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
+
+	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
+		drm_dbg_kms(&i915->drm,
+			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
+			    crtc->base.base.id, crtc->base.name,
+			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+	}
+
 	base_bpp = crtc_state->pipe_bpp;
 
 	/*
@@ -6195,7 +6206,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
-static int intel_atomic_check_config(struct intel_atomic_state *state)
+int intel_atomic_check_config(struct intel_atomic_state *state,
+			      struct intel_link_bw_limits *limits,
+			      enum pipe *failed_pipe)
 {
 	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct intel_crtc_state *new_crtc_state;
@@ -6203,6 +6216,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 	int ret;
 	int i;
 
+	*failed_pipe = INVALID_PIPE;
+
 	ret = intel_bigjoiner_add_affected_crtcs(state);
 	if (ret)
 		return ret;
@@ -6228,7 +6243,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 		if (!new_crtc_state->hw.enable)
 			continue;
 
-		ret = intel_modeset_pipe_config(state, crtc);
+		ret = intel_modeset_pipe_config(state, crtc, limits);
 		if (ret)
 			break;
 
@@ -6237,9 +6252,47 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 			break;
 	}
 
+	if (ret)
+		*failed_pipe = crtc->pipe;
+
 	return ret;
 }
 
+static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits new_limits;
+	struct intel_link_bw_limits old_limits;
+	int ret;
+
+	intel_link_bw_init_limits(i915, &new_limits);
+	old_limits = new_limits;
+
+	while (true) {
+		enum pipe failed_pipe;
+
+		ret = intel_atomic_check_config(state, &new_limits,
+						&failed_pipe);
+		if (ret) {
+			if (ret == -EINVAL &&
+			    intel_link_bw_reset_pipe_limit_to_min(state,
+								  &old_limits,
+								  &new_limits,
+								  failed_pipe))
+				continue;
+
+			break;
+		}
+
+		old_limits = new_limits;
+
+		ret = intel_link_bw_atomic_check(state, &new_limits);
+		if (ret != -EAGAIN)
+			break;
+	}
+
+	return ret;
+}
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -6284,7 +6337,7 @@ int intel_atomic_check(struct drm_device *dev,
 			return ret;
 	}
 
-	ret = intel_atomic_check_config(state);
+	ret = intel_atomic_check_config_and_link(state);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 966163ccbd7a3..514977ebc17b0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1189,7 +1189,8 @@ struct intel_crtc_state {
 		u32 ctrl, div;
 	} dsi_pll;
 
-	int pipe_bpp;
+	int max_link_bpp_x16;	/* in 1/16 bpp units */
+	int pipe_bpp;		/* in 1 bpp units */
 	struct intel_link_m_n dp_m_n;
 
 	/* m2_n2 for eDP downclock */
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
new file mode 100644
index 0000000000000..22494772b9d59
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+
+#include "intel_atomic.h"
+#include "intel_display_types.h"
+#include "intel_dp_mst.h"
+#include "intel_fdi.h"
+#include "intel_link_bw.h"
+
+/**
+ * intel_link_bw_init_limits - initialize BW limits
+ * @i915: device instance
+ * @limits: link BW limits
+ *
+ * Initialize @limits.
+ */
+void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
+{
+	enum pipe pipe;
+
+	limits->min_bpp_pipes = 0;
+	for_each_pipe(i915, pipe)
+		limits->max_bpp_x16[pipe] = INT_MAX;
+}
+
+/**
+ * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
+ * @crtc_state: the crtc state
+ *
+ * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
+ * call this function during state computation in the simple case where the
+ * link bpp will always match the pipe bpp. This is the case for all non-DP
+ * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
+ * of DSC compression.
+ *
+ * Returns %true in case of success, %false if pipe bpp would need to be
+ * reduced below its valid range.
+ */
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
+{
+	int pipe_bpp = min(crtc_state->pipe_bpp,
+			   to_bpp_int(crtc_state->max_link_bpp_x16));
+
+	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
+
+	if (pipe_bpp < 6 * 3)
+		return false;
+
+	crtc_state->pipe_bpp = pipe_bpp;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
+ * @state: atomic state
+ * @limits: link BW limits
+ * @pipe_mask: mask of pipes to select from
+ * @reason: explanation of why bpp reduction is needed
+ *
+ * Select the pipe from @pipe_mask with the biggest link bpp value and set the
+ * maximum of link bpp in @limits below this value. Modeset the selected pipe,
+ * so that its state will get recomputed.
+ *
+ * This function can be called to resolve a link's BW overallocation by reducing
+ * the link bpp of one pipe on the link and hence reducing the total link BW.
+ *
+ * Returns
+ *   - 0 in case of success
+ *   - %-ENOSPC if no pipe can further reduce its link bpp
+ *   - Other negative error, if modesetting the selected pipe failed
+ */
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	enum pipe max_bpp_pipe = INVALID_PIPE;
+	struct intel_crtc *crtc;
+	int max_bpp = 0;
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
+		struct intel_crtc_state *crtc_state;
+		int pipe_bpp;
+
+		if (limits->min_bpp_pipes & BIT(crtc->pipe))
+			continue;
+
+		crtc_state = intel_atomic_get_crtc_state(&state->base,
+							 crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		if (crtc_state->dsc.compression_enable)
+			pipe_bpp = crtc_state->dsc.compressed_bpp;
+		else
+			pipe_bpp = crtc_state->pipe_bpp;
+
+		if (pipe_bpp > max_bpp) {
+			max_bpp = pipe_bpp;
+			max_bpp_pipe = crtc->pipe;
+		}
+	}
+
+	if (max_bpp_pipe == INVALID_PIPE)
+		return -ENOSPC;
+
+	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
+
+	return intel_modeset_pipes_in_mask_early(state, reason,
+						 BIT(max_bpp_pipe));
+}
+
+/**
+ * intel_link_bw_reset_pipe_limit_to_min - reset BW limit for a pipe to its minimum
+ * @state: atomic state
+ * @old_limits: link BW limits
+ * @new_limits: link BW limits
+ * @pipe: pipe
+ *
+ * Reset the link bpp limit for @pipe in @new_limits to its value in
+ * @old_limits and mark this limit as the minimum. This function must be
+ * called after a pipe's compute config function failed, @old_limits
+ * containing the bpp limit with which compute config previously passed.
+ *
+ * The function will fail if setting a minimum is not possible, either
+ * because the old and new limits match (and so would lead to a pipe compute
+ * config failure) or the limit is already at the minimum.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
+				       const struct intel_link_bw_limits *old_limits,
+				       struct intel_link_bw_limits *new_limits,
+				       enum pipe pipe)
+{
+	if (pipe == INVALID_PIPE)
+		return false;
+
+	if (new_limits->min_bpp_pipes & BIT(pipe))
+		return false;
+
+	if (new_limits->max_bpp_x16[pipe] ==
+	    old_limits->max_bpp_x16[pipe])
+		return false;
+
+	new_limits->max_bpp_x16[pipe] =
+		old_limits->max_bpp_x16[pipe];
+	new_limits->min_bpp_pipes |= BIT(pipe);
+
+	return true;
+}
+
+static int check_all_link_config(struct intel_atomic_state *state,
+				 struct intel_link_bw_limits *limits)
+{
+	/* TODO: Check all shared display link configurations like FDI */
+	return 0;
+}
+
+static bool
+assert_link_limit_change_valid(struct drm_i915_private *i915,
+			       const struct intel_link_bw_limits *old_limits,
+			       const struct intel_link_bw_limits *new_limits)
+{
+	bool bpps_changed = false;
+	enum pipe pipe;
+
+	for_each_pipe(i915, pipe) {
+		/* The bpp limit can only decrease. */
+		if (drm_WARN_ON(&i915->drm,
+				new_limits->max_bpp_x16[pipe] >
+				old_limits->max_bpp_x16[pipe]))
+			return false;
+
+		if (new_limits->max_bpp_x16[pipe] <
+		    old_limits->max_bpp_x16[pipe])
+			bpps_changed = true;
+	}
+
+	/* At least one limit must change. */
+	if (drm_WARN_ON(&i915->drm,
+			!bpps_changed))
+		return false;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
+ * @state: atomic state
+ * @new_limits: link BW limits
+ *
+ * Check the configuration of all shared display links in @state and set new BW
+ * limits in @new_limits if there is a BW limitation.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
+ *     with fallback values with which the configuration of all CRTCs
+ *     in @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits old_limits = *new_limits;
+	int ret;
+
+	ret = check_all_link_config(state, new_limits);
+	if (ret != -EAGAIN)
+		return ret;
+
+	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
+		return -EINVAL;
+
+	return -EAGAIN;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
new file mode 100644
index 0000000000000..e514caff5898e
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_LINK_BW_H__
+#define __INTEL_LINK_BW_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+struct drm_i915_private;
+
+struct intel_atomic_state;
+struct intel_crtc_state;
+
+struct intel_link_bw_limits {
+	u8 min_bpp_pipes;
+	/* in 1/16 bpp units */
+	int max_bpp_x16[I915_MAX_PIPES];
+};
+
+void intel_link_bw_init_limits(struct drm_i915_private *i915,
+			       struct intel_link_bw_limits *limits);
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason);
+bool intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
+					   const struct intel_link_bw_limits *old_limits,
+					   struct intel_link_bw_limits *new_limits,
+					   enum pipe pipe);
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits);
+
+#endif
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (8 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 09/25] drm/i915: Add helpers for BW management on shared display links Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-15 19:31   ` Ville Syrjälä
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links Imre Deak
                   ` (23 subsequent siblings)
  33 siblings, 2 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
link bpp in this case, until pipe B uses only up to 2 FDI lanes.

For this instead of the encoder compute config retry loop - which
reduced link bpp only for the encoder's pipe - reduce the maximum link
bpp for pipe B/C as required after all CRTC states are computed and
recompute the CRTC states with the new bpp limit.

v2:
- Don't assume that a CRTC is already in the atomic state, while
  reducing its link bpp.
- Add DocBook description to intel_fdi_atomic_check_link().
v3:
- Enable BW management for FDI links in a separate patch. (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
 drivers/gpu/drm/i915/display/intel_crt.c     |  7 ++
 drivers/gpu/drm/i915/display/intel_display.c | 14 +---
 drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
 drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
 drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
 drivers/gpu/drm/i915/display/intel_lvds.c    | 10 ++-
 drivers/gpu/drm/i915/display/intel_sdvo.c    | 10 ++-
 9 files changed, 107 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 634b14116d9dd..8b5d26cd3b85e 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -19,6 +19,7 @@
 #include "intel_fifo_underrun.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_sdvo.h"
 #include "vlv_sideband.h"
 
@@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
 
-	if (HAS_PCH_SPLIT(i915))
+	if (HAS_PCH_SPLIT(i915)) {
 		crtc_state->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
+			return -EINVAL;
+	}
 
 	if (IS_G4X(i915))
 		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index f6df6c4fa72ef..7aa89d0fa3d6c 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -49,6 +49,7 @@
 #include "intel_gmbus.h"
 #include "intel_hotplug.h"
 #include "intel_hotplug_irq.h"
+#include "intel_link_bw.h"
 #include "intel_load_detect.h"
 #include "intel_pch_display.h"
 #include "intel_pch_refclk.h"
@@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 
 	pipe_config->has_pch_encoder = true;
+	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+		return -EINVAL;
+
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
 	return 0;
@@ -435,6 +439,9 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 
 	pipe_config->has_pch_encoder = true;
+	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+		return -EINVAL;
+
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
 	/* LPT FDI RX only supports 8bpc. */
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 29816153fdd59..aad16dcceb788 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	struct drm_connector_state *connector_state;
 	int pipe_src_w, pipe_src_h;
 	int base_bpp, ret, i;
-	bool retry = true;
 
 	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
 
@@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
 			    crtc->base.base.id, crtc->base.name,
 			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+		crtc_state->bw_constrained = true;
 	}
 
 	base_bpp = crtc_state->pipe_bpp;
@@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 			crtc_state->output_types |= BIT(encoder->type);
 	}
 
-encoder_retry:
 	/* Ensure the port clock defaults are reset when retrying. */
 	crtc_state->port_clock = 0;
 	crtc_state->pixel_multiplier = 1;
@@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	ret = intel_crtc_compute_config(state, crtc);
 	if (ret == -EDEADLK)
 		return ret;
-	if (ret == -EAGAIN) {
-		if (drm_WARN(&i915->drm, !retry,
-			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
-			     crtc->base.base.id, crtc->base.name))
-			return -EINVAL;
-
-		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
-			    crtc->base.base.id, crtc->base.name);
-		retry = false;
-		goto encoder_retry;
-	}
 	if (ret < 0) {
 		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
 			    crtc->base.base.id, crtc->base.name, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index d5e6813d36c8f..03010accc1c7f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
 	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
 	int max_link_bpp_x16;
 
-	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
+			       to_bpp_x16(limits->pipe.max_bpp));
 
 	if (!dsc) {
 		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 4d7d524c68017..ad01915a4a39b 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -13,6 +13,7 @@
 #include "intel_display_types.h"
 #include "intel_fdi.h"
 #include "intel_fdi_regs.h"
+#include "intel_link_bw.h"
 
 struct intel_fdi_funcs {
 	void (*fdi_link_train)(struct intel_crtc *crtc,
@@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
 }
 
 static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
-			       struct intel_crtc_state *pipe_config)
+			       struct intel_crtc_state *pipe_config,
+			       enum pipe *pipe_to_reduce)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_atomic_state *state = pipe_config->uapi.state;
 	struct intel_crtc *other_crtc;
 	struct intel_crtc_state *other_crtc_state;
 
+	*pipe_to_reduce = pipe;
+
 	drm_dbg_kms(&dev_priv->drm,
 		    "checking fdi config on pipe %c, lanes %i\n",
 		    pipe_name(pipe), pipe_config->fdi_lanes);
@@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
 		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
 			drm_dbg_kms(&dev_priv->drm,
 				    "fdi link B uses too many lanes to enable link C\n");
+
+			*pipe_to_reduce = PIPE_B;
+
 			return -EINVAL;
 		}
 		return 0;
@@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *i915 = to_i915(dev);
 	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
-	int lane, link_bw, fdi_dotclock, ret;
-	bool needs_recompute = false;
+	int lane, link_bw, fdi_dotclock;
 
-retry:
 	/* FDI is a binary signal running at ~2.7GHz, encoding
 	 * each output octet as 10 bits. The actual frequency
 	 * is stored as a divider into a 100MHz clock, and the
@@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
 	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
 			       link_bw, &pipe_config->fdi_m_n, false);
 
-	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
-	if (ret == -EDEADLK)
+	return 0;
+}
+
+static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
+				     struct intel_crtc *crtc,
+				     struct intel_crtc_state *pipe_config,
+				     struct intel_link_bw_limits *limits)
+{
+	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	enum pipe pipe_to_reduce;
+	int ret;
+
+	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
+				  &pipe_to_reduce);
+	if (ret != -EINVAL)
 		return ret;
 
-	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
-		pipe_config->pipe_bpp -= 2*3;
-		drm_dbg_kms(&i915->drm,
-			    "fdi link bw constraint, reducing pipe bpp to %i\n",
-			    pipe_config->pipe_bpp);
-		needs_recompute = true;
-		pipe_config->bw_constrained = true;
-
-		goto retry;
+	ret = intel_link_bw_reduce_bpp(state, limits,
+				       BIT(pipe_to_reduce),
+				       "FDI link BW");
+
+	return ret ? : -EAGAIN;
+}
+
+/**
+ * intel_fdi_atomic_check_link - check all modeset FDI link configuration
+ * @state: intel atomic state
+ * @limits: link BW limits
+ *
+ * Check the link configuration for all modeset FDI outputs. If the
+ * configuration is invalid @limits will be updated if possible to
+ * reduce the total BW, after which the configuration for all CRTCs in
+ * @state must be recomputed with the updated @limits.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @limits got updated
+ *     with fallback values with which the configuration of all CRTCs
+ *     in @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+				struct intel_link_bw_limits *limits)
+{
+	struct intel_crtc *crtc;
+	struct intel_crtc_state *crtc_state;
+	int i;
+
+	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+		int ret;
+
+		if (!crtc_state->has_pch_encoder ||
+		    !intel_crtc_needs_modeset(crtc_state) ||
+		    !crtc_state->hw.enable)
+			continue;
+
+		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
+		if (ret)
+			return ret;
 	}
 
-	if (needs_recompute)
-		return -EAGAIN;
-
-	return ret;
+	return 0;
 }
 
 static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
index 1cdb86172702f..129444c580f27 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.h
+++ b/drivers/gpu/drm/i915/display/intel_fdi.h
@@ -8,14 +8,18 @@
 
 enum pipe;
 struct drm_i915_private;
+struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_encoder;
+struct intel_link_bw_limits;
 
 int intel_fdi_link_freq(struct drm_i915_private *i915,
 			const struct intel_crtc_state *pipe_config);
 int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
 			   struct intel_crtc_state *pipe_config);
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+				struct intel_link_bw_limits *limits);
 void intel_fdi_normal_train(struct intel_crtc *crtc);
 void ilk_fdi_disable(struct intel_crtc *crtc);
 void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 22494772b9d59..aacf22bab3135 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -160,7 +160,12 @@ intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
 static int check_all_link_config(struct intel_atomic_state *state,
 				 struct intel_link_bw_limits *limits)
 {
-	/* TODO: Check all shared display link configurations like FDI */
+	int ret;
+
+	ret = intel_fdi_atomic_check_link(state, limits);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 3ace56979b70e..0366d4cc6b72b 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -48,6 +48,7 @@
 #include "intel_dpll.h"
 #include "intel_fdi.h"
 #include "intel_gmbus.h"
+#include "intel_link_bw.h"
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_panel.h"
@@ -425,6 +426,12 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 	}
 
+	if (HAS_PCH_SPLIT(i915)) {
+		crtc_state->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
+			return -EINVAL;
+	}
+
 	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
 		lvds_bpp = 8*3;
 	else
@@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
-	if (HAS_PCH_SPLIT(i915))
-		crtc_state->has_pch_encoder = true;
-
 	ret = intel_panel_fitting(crtc_state, conn_state);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 135a2527fd1b4..3c912f3bc10ba 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -48,6 +48,7 @@
 #include "intel_gmbus.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_panel.h"
 #include "intel_sdvo.h"
 #include "intel_sdvo_regs.h"
@@ -1351,14 +1352,17 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct drm_display_mode *mode = &pipe_config->hw.mode;
 
+	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
+		pipe_config->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+			return -EINVAL;
+	}
+
 	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
 	pipe_config->pipe_bpp = 8*3;
 	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
-	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
-		pipe_config->has_pch_encoder = true;
-
 	/*
 	 * We need to construct preferred input timings based on our
 	 * output timings.  To do that, we have to set the output
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (9 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-19 15:44   ` Ville Syrjälä
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 12/25] drm/dp_mst: Fix fractional DSC bpp handling Imre Deak
                   ` (22 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Recompute the state of all CRTCs on an FDI link during a modeset that
may be affected by the modeset of other CRTCs on the same link. This
ensures that each CRTC on the link maximizes its BW use (after another
CRTC is disabled).

In practice this means recomputing pipe B's config on IVB if pipe C gets
disabled.

v2:
- Add the change recomputing affected CRTC states in a separate patch.
  (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 ++
 drivers/gpu/drm/i915/display/intel_fdi.c     | 53 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_fdi.h     |  1 +
 3 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index aad16dcceb788..31297a333f50e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6210,6 +6210,10 @@ int intel_atomic_check_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	ret = intel_fdi_add_affected_crtcs(state);
+	if (ret)
+		return ret;
+
 	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
 		if (!intel_crtc_needs_modeset(new_crtc_state)) {
 			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index ad01915a4a39b..d723ae7e10d71 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -120,6 +120,59 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
 	dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
 }
 
+/**
+ * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
+ * @state: intel atomic state
+ *
+ * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
+ * known to affect the available FDI BW for the former CRTC. In practice this
+ * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
+ * CRTC C) and CRTC C is getting disabled.
+ *
+ * Returns 0 in case of success, or a negative error code otherwise.
+ */
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc_state *old_crtc_state;
+	struct intel_crtc_state *new_crtc_state;
+	struct intel_crtc *crtc;
+
+	if (!IS_IVYBRIDGE(i915))
+		return 0;
+
+	crtc = intel_crtc_for_pipe(i915, PIPE_C);
+	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+
+	if (!new_crtc_state)
+		return 0;
+
+	old_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+
+	if (!old_crtc_state->fdi_lanes)
+		return 0;
+
+	if (!intel_crtc_needs_modeset(new_crtc_state))
+		return 0;
+
+	if (new_crtc_state->uapi.enable)
+		return 0;
+
+	crtc = intel_crtc_for_pipe(i915, PIPE_B);
+	new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+
+	if (IS_ERR(new_crtc_state))
+		return PTR_ERR(old_crtc_state);
+
+	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+	if (!old_crtc_state->fdi_lanes)
+		return 0;
+
+	return intel_modeset_pipes_in_mask_early(state,
+						 "FDI link BW decrease on pipe C",
+						 BIT(PIPE_B));
+}
+
 /* units of 100MHz */
 static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
index 129444c580f27..eb02b967bb440 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.h
+++ b/drivers/gpu/drm/i915/display/intel_fdi.h
@@ -14,6 +14,7 @@ struct intel_crtc_state;
 struct intel_encoder;
 struct intel_link_bw_limits;
 
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
 int intel_fdi_link_freq(struct drm_i915_private *i915,
 			const struct intel_crtc_state *pipe_config);
 int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 12/25] drm/dp_mst: Fix fractional DSC bpp handling
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (10 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 13/25] drm/dp_mst: Add a way to calculate PBN values with FEC overhead Imre Deak
                   ` (21 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx
  Cc: David Francis, Manasi Navare, Alex Deucher, Mikita Lipski,
	Harry Wentland

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

The current code does '(bpp << 4) / 16' in the MST PBN
calculation, but that is just the same as 'bpp' so the
DSC codepath achieves absolutely nothing. Fix it up so that
the fractional part of the bpp value is actually used instead
of truncated away. 64*1006 has enough zero lsbs that we can
just shift that down in the dividend and thus still manage
to stick to a 32bit divisor.

And while touching this, let's just make the whole thing more
straightforward by making the passed in bpp value .4 binary
fixed point always, instead of having to pass in different
things based on whether DSC is enabled or not.

v2:
- Fix DSC kunit test cases.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: David Francis <David.Francis@amd.com>
Cc: Mikita Lipski <mikita.lipski@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Fixes: dc48529fb14e ("drm/dp_mst: Add PBN calculation for DSC modes")
Reviewed-by: Lyude Paul <lyude@redhat.com> (v1)
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
[Imre: Fix kunit test cases]
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 20 +++++--------------
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  5 ++---
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |  3 +--
 .../gpu/drm/tests/drm_dp_mst_helper_test.c    |  6 +++---
 include/drm/display/drm_dp_mst_helper.h       |  2 +-
 7 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 88ba8b66de1f7..1df65e3e674f6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6804,7 +6804,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
 								    max_bpc);
 		bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
 		clock = adjusted_mode->clock;
-		dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
+		dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4);
 	}
 
 	dm_new_connector_state->vcpi_slots =
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 57230661132bd..2afd1bc74978d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1636,7 +1636,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	} else {
 		/* check if mode could be supported within full_pbn */
 		bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
-		pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false);
+		pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4);
 
 		if (pbn > aconnector->mst_output_port->full_pbn)
 			return DC_FAIL_BANDWIDTH_VALIDATE;
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e04f87ff755ac..0264f673295a8 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4719,13 +4719,12 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
 
 /**
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
- * @clock: dot clock for the mode
- * @bpp: bpp for the mode.
- * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
+ * @clock: dot clock
+ * @bpp: bpp as .4 binary fixed point
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
+int drm_dp_calc_pbn_mode(int clock, int bpp)
 {
 	/*
 	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
@@ -4736,18 +4735,9 @@ int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
 	 * peak_kbps *= (1006/1000)
 	 * peak_kbps *= (64/54)
 	 * peak_kbps *= 8    convert to bytes
-	 *
-	 * If the bpp is in units of 1/16, further divide by 16. Put this
-	 * factor in the numerator rather than the denominator to avoid
-	 * integer overflow
 	 */
-
-	if (dsc)
-		return DIV_ROUND_UP_ULL(mul_u32_u32(clock * (bpp / 16), 64 * 1006),
-					8 * 54 * 1000 * 1000);
-
-	return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006),
-				8 * 54 * 1000 * 1000);
+	return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4),
+				1000 * 8 * 54 * 1000);
 }
 EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index d38d0dd23fc39..dd04306ba9b32 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -109,8 +109,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
 			continue;
 
 		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-						       dsc ? bpp << 4 : bpp,
-						       dsc);
+						       bpp << 4);
 
 		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
 						      connector->port,
@@ -976,7 +975,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
 		return ret;
 
 	if (mode_rate > max_rate || mode->clock > max_dotclk ||
-	    drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) {
+	    drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
 		*status = MODE_CLOCK_HIGH;
 		return 0;
 	}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index bba01fa0780c9..0e1542a5b9ac1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -967,8 +967,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
 		const int clock = crtc_state->adjusted_mode.clock;
 
 		asyh->or.bpc = connector->display_info.bpc;
-		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3,
-						    false);
+		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3 << 4);
 	}
 
 	mst_state = drm_atomic_get_mst_topology_state(state, &mstm->mgr);
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
index 545beea33e8c7..e3c818dfc0e6d 100644
--- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -42,13 +42,13 @@ static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases
 		.clock = 332880,
 		.bpp = 24,
 		.dsc = true,
-		.expected = 50
+		.expected = 1191
 	},
 	{
 		.clock = 324540,
 		.bpp = 24,
 		.dsc = true,
-		.expected = 49
+		.expected = 1161
 	},
 };
 
@@ -56,7 +56,7 @@ static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
 {
 	const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
 
-	KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
+	KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp << 4),
 			params->expected);
 }
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 4429d3b1745b6..655862b3d2a49 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -842,7 +842,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
 int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
 			     int link_rate, int link_lane_count);
 
-int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc);
+int drm_dp_calc_pbn_mode(int clock, int bpp);
 
 void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap);
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 13/25] drm/dp_mst: Add a way to calculate PBN values with FEC overhead
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (11 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 12/25] drm/dp_mst: Fix fractional DSC bpp handling Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 14/25] drm/dp_mst: Add helper to determine if an MST port is downstream of another port Imre Deak
                   ` (20 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: Alex Deucher, Harry Wentland, dri-devel, Wayne Lin

Add a way for drivers to calculate the MST PBN values with FEC overhead.
This is required by 8b/10b links both for DSC and non-DSC (the latter
needed if there are both DSC and non-DSC streams on the same MST link).

Also add a kunit test case for PBN values calculated with FEC overhead.

v2:
- Rebase on fractional bpp fix in the previous patch.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Wayne Lin <wayne.lin@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Lyude Paul <lyude@redhat.com> (v1)
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 19 ++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  5 +++--
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
 .../gpu/drm/tests/drm_dp_mst_helper_test.c    | 15 ++++++++++++++-
 include/drm/display/drm_dp_mst_helper.h       |  2 +-
 7 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 1df65e3e674f6..fb175ac279318 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6804,7 +6804,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
 								    max_bpc);
 		bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
 		clock = adjusted_mode->clock;
-		dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4);
+		dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4, false);
 	}
 
 	dm_new_connector_state->vcpi_slots =
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 2afd1bc74978d..46829361175dc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1636,7 +1636,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	} else {
 		/* check if mode could be supported within full_pbn */
 		bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
-		pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4);
+		pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4, false);
 
 		if (pbn > aconnector->mst_output_port->full_pbn)
 			return DC_FAIL_BANDWIDTH_VALIDATE;
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 0264f673295a8..db97aa76575c1 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4721,22 +4721,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  * @clock: dot clock
  * @bpp: bpp as .4 binary fixed point
+ * @fec: calculate PBN with FEC overhead
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp)
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool fec)
 {
 	/*
-	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+	 * Overheads:
+	 * - SSC downspread and ref clock variation margin:
+	 *     5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+	 * - FEC symbol insertions:
+	 *     2.4% as per spec, factor is 1.024
+	 *
 	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
 	 * common multiplier to render an integer PBN for all link rate/lane
 	 * counts combinations
 	 * calculate
-	 * peak_kbps *= (1006/1000)
+	 * peak_kbps *= (1006/1000) without FEC, or
+	 * peak_kbps *= (1030/1000) with FEC
 	 * peak_kbps *= (64/54)
-	 * peak_kbps *= 8    convert to bytes
+	 * peak_kbps /= 8    convert to bytes
 	 */
-	return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4),
+	u32 overhead = fec ? 1030 : 1006;
+
+	return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * overhead >> 4),
 				1000 * 8 * 54 * 1000);
 }
 EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index dd04306ba9b32..01291bbb44693 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -109,7 +109,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
 			continue;
 
 		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-						       bpp << 4);
+						       bpp << 4,
+						       false);
 
 		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
 						      connector->port,
@@ -975,7 +976,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
 		return ret;
 
 	if (mode_rate > max_rate || mode->clock > max_dotclk ||
-	    drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
+	    drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4, false) > port->full_pbn) {
 		*status = MODE_CLOCK_HIGH;
 		return 0;
 	}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 0e1542a5b9ac1..e1c8f03e6bb57 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -967,7 +967,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
 		const int clock = crtc_state->adjusted_mode.clock;
 
 		asyh->or.bpc = connector->display_info.bpc;
-		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3 << 4);
+		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3 << 4, false);
 	}
 
 	mst_state = drm_atomic_get_mst_topology_state(state, &mstm->mgr);
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
index e3c818dfc0e6d..b8e3d9b64b3c4 100644
--- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -16,6 +16,7 @@ struct drm_dp_mst_calc_pbn_mode_test {
 	const int clock;
 	const int bpp;
 	const bool dsc;
+	const bool fec;
 	const int expected;
 };
 
@@ -24,39 +25,51 @@ static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases
 		.clock = 154000,
 		.bpp = 30,
 		.dsc = false,
+		.fec = false,
 		.expected = 689
 	},
 	{
 		.clock = 234000,
 		.bpp = 30,
 		.dsc = false,
+		.fec = false,
 		.expected = 1047
 	},
 	{
 		.clock = 297000,
 		.bpp = 24,
 		.dsc = false,
+		.fec = false,
 		.expected = 1063
 	},
 	{
 		.clock = 332880,
 		.bpp = 24,
 		.dsc = true,
+		.fec = false,
 		.expected = 1191
 	},
 	{
 		.clock = 324540,
 		.bpp = 24,
 		.dsc = true,
+		.fec = false,
 		.expected = 1161
 	},
+	{
+		.clock = 324540,
+		.bpp = 24,
+		.dsc = true,
+		.fec = true,
+		.expected = 1189
+	},
 };
 
 static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
 {
 	const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
 
-	KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp << 4),
+	KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp << 4, params->fec),
 			params->expected);
 }
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 655862b3d2a49..5de0c3d28794b 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -842,7 +842,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
 int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
 			     int link_rate, int link_lane_count);
 
-int drm_dp_calc_pbn_mode(int clock, int bpp);
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool fec);
 
 void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap);
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 14/25] drm/dp_mst: Add helper to determine if an MST port is downstream of another port
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (12 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 13/25] drm/dp_mst: Add a way to calculate PBN values with FEC overhead Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 15/25] drm/dp_mst: Factor out a helper to check the atomic state of a topology manager Imre Deak
                   ` (19 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add drm_dp_mst_port_downstream_of_parent() required by the i915
driver in a follow-up patch to resolve a BW overallocation of MST
streams going through a given MST port.

Cc: Lyude Paul <lyude@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 52 +++++++++++++++++++
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index db97aa76575c1..22a901493d24c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5136,6 +5136,58 @@ static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port,
 	return false;
 }
 
+static bool
+drm_dp_mst_port_downstream_of_parent_locked(struct drm_dp_mst_topology_mgr *mgr,
+					    struct drm_dp_mst_port *port,
+					    struct drm_dp_mst_port *parent)
+{
+	if (!mgr->mst_primary)
+		return false;
+
+	port = drm_dp_mst_topology_get_port_validated_locked(mgr->mst_primary,
+							     port);
+	if (!port)
+		return false;
+
+	if (!parent)
+		return true;
+
+	parent = drm_dp_mst_topology_get_port_validated_locked(mgr->mst_primary,
+							       parent);
+	if (!parent)
+		return false;
+
+	if (!parent->mstb)
+		return false;
+
+	return drm_dp_mst_port_downstream_of_branch(port, parent->mstb);
+}
+
+/**
+ * drm_dp_mst_port_downstream_of_parent - check if a port is downstream of a parent port
+ * @mgr: MST topology manager
+ * @port: the port being looked up
+ * @parent: the parent port
+ *
+ * The function returns %true if @port is downstream of @parent. If @parent is
+ * %NULL - denoting the root port - the function returns %true if @port is in
+ * @mgr's topology.
+ */
+bool
+drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr,
+				     struct drm_dp_mst_port *port,
+				     struct drm_dp_mst_port *parent)
+{
+	bool ret;
+
+	mutex_lock(&mgr->lock);
+	ret = drm_dp_mst_port_downstream_of_parent_locked(mgr, port, parent);
+	mutex_unlock(&mgr->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_port_downstream_of_parent);
+
 static int
 drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 				      struct drm_dp_mst_topology_state *state);
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 5de0c3d28794b..aecce52cae167 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -892,6 +892,9 @@ drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 struct drm_dp_mst_atomic_payload *
 drm_atomic_get_mst_payload_state(struct drm_dp_mst_topology_state *state,
 				 struct drm_dp_mst_port *port);
+bool drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr,
+					  struct drm_dp_mst_port *port,
+					  struct drm_dp_mst_port *parent);
 int __must_check
 drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
 			      struct drm_dp_mst_topology_mgr *mgr,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 15/25] drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (13 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 14/25] drm/dp_mst: Add helper to determine if an MST port is downstream of another port Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 16/25] drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations Imre Deak
                   ` (18 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Factor out a helper to check the atomic state for one MST topology
manager, returning the MST port where the BW limit check has failed.
This will be used in a follow-up patch by the i915 driver to improve the
BW sharing between MST streams.

Cc: Lyude Paul <lyude@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 93 +++++++++++++++----
 include/drm/display/drm_dp_mst_helper.h       |  4 +
 2 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 22a901493d24c..3d93bc093c46c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5190,11 +5190,13 @@ EXPORT_SYMBOL(drm_dp_mst_port_downstream_of_parent);
 
 static int
 drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
-				      struct drm_dp_mst_topology_state *state);
+				      struct drm_dp_mst_topology_state *state,
+				      struct drm_dp_mst_port **failing_port);
 
 static int
 drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
-				      struct drm_dp_mst_topology_state *state)
+				      struct drm_dp_mst_topology_state *state,
+				      struct drm_dp_mst_port **failing_port)
 {
 	struct drm_dp_mst_atomic_payload *payload;
 	struct drm_dp_mst_port *port;
@@ -5223,7 +5225,7 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 		drm_dbg_atomic(mstb->mgr->dev, "[MSTB:%p] Checking bandwidth limits\n", mstb);
 
 	list_for_each_entry(port, &mstb->ports, next) {
-		ret = drm_dp_mst_atomic_check_port_bw_limit(port, state);
+		ret = drm_dp_mst_atomic_check_port_bw_limit(port, state, failing_port);
 		if (ret < 0)
 			return ret;
 
@@ -5235,7 +5237,8 @@ drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
 
 static int
 drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
-				      struct drm_dp_mst_topology_state *state)
+				      struct drm_dp_mst_topology_state *state,
+				      struct drm_dp_mst_port **failing_port)
 {
 	struct drm_dp_mst_atomic_payload *payload;
 	int pbn_used = 0;
@@ -5256,13 +5259,15 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 			drm_dbg_atomic(port->mgr->dev,
 				       "[MSTB:%p] [MST PORT:%p] no BW available for the port\n",
 				       port->parent, port);
+			*failing_port = port;
 			return -EINVAL;
 		}
 
 		pbn_used = payload->pbn;
 	} else {
 		pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
-								 state);
+								 state,
+								 failing_port);
 		if (pbn_used <= 0)
 			return pbn_used;
 	}
@@ -5271,6 +5276,7 @@ drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
 		drm_dbg_atomic(port->mgr->dev,
 			       "[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n",
 			       port->parent, port, pbn_used, port->full_pbn);
+		*failing_port = port;
 		return -ENOSPC;
 	}
 
@@ -5448,20 +5454,79 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
 
+/**
+ * drm_dp_mst_atomic_check_mgr - Check the atomic state of an MST topology manager
+ * @state: The global atomic state
+ * @mgr: Manager to check
+ * @mst_state: The MST atomic state for @mgr
+ * @failing_port: Returns the port with a BW limitation
+ *
+ * Checks the given MST manager's topology state for an atomic update to ensure
+ * that it's valid. This includes checking whether there's enough bandwidth to
+ * support the new timeslot allocations in the atomic update.
+ *
+ * Any atomic drivers supporting DP MST must make sure to call this or
+ * the drm_dp_mst_atomic_check() function after checking the rest of their state
+ * in their &drm_mode_config_funcs.atomic_check() callback.
+ *
+ * See also:
+ * drm_dp_mst_atomic_check()
+ * drm_dp_atomic_find_time_slots()
+ * drm_dp_atomic_release_time_slots()
+ *
+ * Returns:
+ *   - 0 if the new state is valid
+ *   - %-ENOSPC, if the new state is invalid, because of BW limitation
+ *         @failing_port is set to:
+ *         - The non-root port where a BW limit check failed
+ *           The returned port pointer is valid until at least
+ *           one payload downstream of it exists.
+ *         - %NULL if the BW limit check failed at the root port
+ *   - %-EINVAL, if the new state is invalid, because the root port has
+ *     too many payloads.
+ */
+int drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
+				struct drm_dp_mst_topology_mgr *mgr,
+				struct drm_dp_mst_topology_state *mst_state,
+				struct drm_dp_mst_port **failing_port)
+{
+	int ret;
+
+	*failing_port = NULL;
+
+	if (!mgr->mst_state)
+		return 0;
+
+	ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
+	if (ret)
+		return ret;
+
+	mutex_lock(&mgr->lock);
+	ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
+						    mst_state,
+						    failing_port);
+	mutex_unlock(&mgr->lock);
+
+	return ret < 0 ? ret : 0;
+}
+EXPORT_SYMBOL(drm_dp_mst_atomic_check_mgr);
+
 /**
  * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
  * atomic update is valid
  * @state: Pointer to the new &struct drm_dp_mst_topology_state
  *
  * Checks the given topology state for an atomic update to ensure that it's
- * valid. This includes checking whether there's enough bandwidth to support
- * the new timeslot allocations in the atomic update.
+ * valid, calling drm_dp_mst_atomic_check_mgr() for all MST manager in the
+ * atomic state. This includes checking whether there's enough bandwidth to
+ * support the new timeslot allocations in the atomic update.
  *
  * Any atomic drivers supporting DP MST must make sure to call this after
  * checking the rest of their state in their
  * &drm_mode_config_funcs.atomic_check() callback.
  *
  * See also:
+ * drm_dp_mst_atomic_check_mgr()
  * drm_dp_atomic_find_time_slots()
  * drm_dp_atomic_release_time_slots()
  *
@@ -5476,21 +5541,11 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
 	int i, ret = 0;
 
 	for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
-		if (!mgr->mst_state)
-			continue;
+		struct drm_dp_mst_port *tmp_port;
 
-		ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
+		ret = drm_dp_mst_atomic_check_mgr(state, mgr, mst_state, &tmp_port);
 		if (ret)
 			break;
-
-		mutex_lock(&mgr->lock);
-		ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
-							    mst_state);
-		mutex_unlock(&mgr->lock);
-		if (ret < 0)
-			break;
-		else
-			ret = 0;
 	}
 
 	return ret;
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index aecce52cae167..0e570b67563b5 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -916,6 +916,10 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
 int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr,
 		struct drm_dp_mst_port *port,
 		struct drm_dp_query_stream_enc_status_ack_reply *status);
+int __must_check drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
+					     struct drm_dp_mst_topology_mgr *mgr,
+					     struct drm_dp_mst_topology_state *mst_state,
+					     struct drm_dp_mst_port **failing_port);
 int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
 int __must_check drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state,
 						   struct drm_dp_mst_topology_mgr *mgr);
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 16/25] drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (14 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 15/25] drm/dp_mst: Factor out a helper to check the atomic state of a topology manager Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead Imre Deak
                   ` (17 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

drm_dp_mst_atomic_check_mgr() should check for BW limitation starting
from sink ports continuing towards the root port, so that drivers can
use the @failing_port returned to resolve a BW overallocation in an
ideal way. For instance from streams A,B,C in a topology A,B going
through @failing_port and C not going through it, a BW overallocation of
A,B due to a limit of the port must be resolved first before considering
the limits of other ports closer to the root port. This way can avoid
reducing the BW of stream C unnecessarily due to a BW limit closer to the
root port.

Based on the above swap the order of the BW check for the root port and
the check for all the ports downstream of it (the latter going through
the topology already in the sink->root port direction).

Cc: Lyude Paul <lyude@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 3d93bc093c46c..f4b70ee3d715c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5479,9 +5479,13 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc);
  *   - %-ENOSPC, if the new state is invalid, because of BW limitation
  *         @failing_port is set to:
  *         - The non-root port where a BW limit check failed
+ *           with all the ports downstream of @failing_port passing
+ *           the BW limit check.
  *           The returned port pointer is valid until at least
  *           one payload downstream of it exists.
  *         - %NULL if the BW limit check failed at the root port
+ *           with all the ports downstream of the root port passing
+ *           the BW limit check.
  *   - %-EINVAL, if the new state is invalid, because the root port has
  *     too many payloads.
  */
@@ -5497,17 +5501,16 @@ int drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
 	if (!mgr->mst_state)
 		return 0;
 
-	ret = drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
-	if (ret)
-		return ret;
-
 	mutex_lock(&mgr->lock);
 	ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
 						    mst_state,
 						    failing_port);
 	mutex_unlock(&mgr->lock);
 
-	return ret < 0 ? ret : 0;
+	if (ret < 0)
+		return ret;
+
+	return drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
 }
 EXPORT_SYMBOL(drm_dp_mst_atomic_check_mgr);
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (15 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 16/25] drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-20  9:09   ` Lisovskiy, Stanislav
  2023-09-20 10:58   ` Ville Syrjälä
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms Imre Deak
                   ` (16 subsequent siblings)
  33 siblings, 2 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

On 8b/10b MST links the PBN value for DSC streams must be calculated
accounting for the FEC overhead. The same applies to 8b/10b non-DSC
streams if there is another DSC stream on the same link. Fix up the PBN
calculation accordingly.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 01291bbb44693..c1fea894d3774 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -110,7 +110,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
 
 		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
 						       bpp << 4,
-						       false);
+						       (dsc || crtc_state->fec_enable) &&
+							!intel_dp_is_uhbr(crtc_state));
 
 		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
 						      connector->port,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (16 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-20  9:11   ` Lisovskiy, Stanislav
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream Imre Deak
                   ` (15 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

If an MST stream is modeset, its state must be checked along all the
other streams on the same MST link, for instance to resolve a BW
overallocation of a non-sink MST port or to make sure that the FEC is
enabled/disabled the same way for all these streams.

To prepare for that this patch adds all the stream CRTCs to the atomic
state and marks them for modeset similarly to tgl+ platforms. (If the
state computation doesn't change the state the CRTC is switched back to
fastset mode.)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index c1fea894d3774..832e8b0e87e84 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
 	struct intel_connector *connector_iter;
 	int ret = 0;
 
-	if (DISPLAY_VER(dev_priv) < 12)
-		return  0;
-
 	if (!intel_connector_needs_modeset(state, &connector->base))
 		return 0;
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (17 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-25  8:00   ` Lisovskiy, Stanislav
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled Imre Deak
                   ` (14 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Atm the DSC PPS SDP is programmed only if the first stream is compressed
and then it's programmed only for the first stream. This left all other
compressed streams blank. Program the SDP for all streams.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c    | 12 +++++++-----
 drivers/gpu/drm/i915/display/intel_dp_mst.c |  2 ++
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 45db6349af94f..962c9c7c211ce 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2505,7 +2505,8 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	/* 6.o Configure and enable FEC if needed */
 	intel_ddi_enable_fec(encoder, crtc_state);
 
-	intel_dsc_dp_pps_write(encoder, crtc_state);
+	if (!is_mst)
+		intel_dsc_dp_pps_write(encoder, crtc_state);
 }
 
 static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
@@ -2643,7 +2644,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	/* 7.l Configure and enable FEC if needed */
 	intel_ddi_enable_fec(encoder, crtc_state);
 
-	intel_dsc_dp_pps_write(encoder, crtc_state);
+	if (!is_mst)
+		intel_dsc_dp_pps_write(encoder, crtc_state);
 }
 
 static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
@@ -2705,10 +2707,10 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
 
 	intel_ddi_enable_fec(encoder, crtc_state);
 
-	if (!is_mst)
+	if (!is_mst) {
 		intel_ddi_enable_transcoder_clock(encoder, crtc_state);
-
-	intel_dsc_dp_pps_write(encoder, crtc_state);
+		intel_dsc_dp_pps_write(encoder, crtc_state);
+	}
 }
 
 static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 832e8b0e87e84..19548242fa0f2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -43,6 +43,7 @@
 #include "intel_dpio_phy.h"
 #include "intel_hdcp.h"
 #include "intel_hotplug.h"
+#include "intel_vdsc.h"
 #include "skl_scaler.h"
 
 static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int bpp,
@@ -775,6 +776,7 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
 	if (DISPLAY_VER(dev_priv) < 12 || !first_mst_stream)
 		intel_ddi_enable_transcoder_clock(encoder, pipe_config);
 
+	intel_dsc_dp_pps_write(&dig_port->base, pipe_config);
 	intel_ddi_set_dp_msa(pipe_config, conn_state);
 }
 
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (18 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-25  7:56   ` Lisovskiy, Stanislav
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 21/25] drm/i915/dp_mst: Enable DSC decompression if any stream needs this Imre Deak
                   ` (13 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Atm the DSC PPS SDP will stay enabled after enabling and disabling DSC.
This leaves an output blank after switching off DSC on it. Make sure the
SDP is disabled for an uncompressed output.

v2:
- Disable the SDP already during output disabling. (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 5 ++++-
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 ++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 03010accc1c7f..e942eb95d688f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4027,7 +4027,10 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder,
 			 VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK;
 	u32 val = intel_de_read(dev_priv, reg) & ~dip_enable;
 
-	/* TODO: Add DSC case (DIP_ENABLE_PPS) */
+	/* TODO: Sanitize DSC enabling wrt. intel_dsc_dp_pps_write(). */
+	if (!enable && HAS_DSC(dev_priv))
+		val &= ~VDIP_ENABLE_PPS;
+
 	/* When PSR is enabled, this routine doesn't disable VSC DIP */
 	if (!crtc_state->has_psr)
 		val &= ~VIDEO_DIP_ENABLE_VSC_HSW;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 19548242fa0f2..a38a0e6da01bf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -662,9 +662,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
 	 * BSpec 4287: disable DIP after the transcoder is disabled and before
 	 * the transcoder clock select is set to none.
 	 */
-	if (last_mst_stream)
-		intel_dp_set_infoframes(&dig_port->base, false,
-					old_crtc_state, NULL);
+	intel_dp_set_infoframes(&dig_port->base, false,
+				old_crtc_state, NULL);
 	/*
 	 * From TGL spec: "If multi-stream slave transcoder: Configure
 	 * Transcoder Clock Select to direct no clock to the transcoder"
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 21/25] drm/i915/dp_mst: Enable DSC decompression if any stream needs this
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (19 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 22/25] drm/i915/dp_mst: Add missing DSC compression disabling Imre Deak
                   ` (12 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Atm DSC decompression is enabled in the sink only if the first stream is
compressed. This left compressed streams blank if the first stream was
uncompressed.

Enable decompression whenever FEC is enabled, which will be true for all
streams if any stream is compressed. Enabling FEC correctly in all
streams will be only fixed by an upcoming patch.

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index e942eb95d688f..ce8eafa4ece06 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2917,7 +2917,13 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	int ret;
 
-	if (!crtc_state->dsc.compression_enable)
+	/*
+	 * In case of MST any stream can be compressed not just the first. If
+	 * any stream is compressed FEC will be enabled in all streams, so toggle
+	 * decompression whenever FEC is enabled.
+	 */
+	if (!crtc_state->dsc.compression_enable &&
+	    !crtc_state->fec_enable)
 		return;
 
 	ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_DSC_ENABLE,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 22/25] drm/i915/dp_mst: Add missing DSC compression disabling
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (20 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 21/25] drm/i915/dp_mst: Enable DSC decompression if any stream needs this Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device Imre Deak
                   ` (11 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Add the missing DSC compression disabling step for MST streams,
similarly to how this is done for SST outputs.

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index a38a0e6da01bf..b2ac29a157fbd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -646,6 +646,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
 
 	intel_ddi_disable_transcoder_func(old_crtc_state);
 
+	intel_dsc_disable(old_crtc_state);
+
 	if (DISPLAY_VER(dev_priv) >= 9)
 		skl_scaler_disable(old_crtc_state);
 	else
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (21 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 22/25] drm/i915/dp_mst: Add missing DSC compression disabling Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-25  7:44   ` Lisovskiy, Stanislav
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams Imre Deak
                   ` (10 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

Atm the driver supports DSC on MST links only by enabling it globally in
the first branch device UFP's physical DPCD (vs. enabling it per-stream
in the virtual DPCD right upstream the DPRX). This means the branch
device will decompress any compressed stream (which it recognizes via
MSA / SDP compression info), but it does this only for streams going to
an SST output port. Accordingly allow DSC only for streams going to an
SST output port of the first branch device.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 26 +++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index b2ac29a157fbd..f24f656d6d02a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -335,6 +335,27 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
 						       limits);
 }
 
+static bool intel_dp_mst_port_supports_dsc(struct intel_dp *intel_dp,
+					   struct intel_crtc_state *crtc_state,
+					   struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct intel_connector *connector =
+		to_intel_connector(conn_state->connector);
+	struct intel_crtc *crtc =
+		to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (connector->port->parent != intel_dp->mst_mgr.mst_primary) {
+		drm_dbg_kms(&i915->drm,
+			    "[CRTC:%d:%s] DSC only allowed on sink ports of the first branch device\n",
+			    crtc->base.base.id, crtc->base.name);
+
+		return false;
+	}
+
+	return true;
+}
+
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 				       struct intel_crtc_state *pipe_config,
 				       struct drm_connector_state *conn_state)
@@ -378,6 +399,11 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 			    str_yes_no(ret),
 			    str_yes_no(intel_dp->force_dsc_en));
 
+		if (!intel_dp_mst_port_supports_dsc(intel_dp,
+						    pipe_config,
+						    conn_state))
+			return -EINVAL;
+
 		if (!intel_dp_mst_compute_config_limits(intel_dp,
 							pipe_config,
 							true,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (22 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-19 10:52   ` [Intel-gfx] [PATCH v5 " Imre Deak
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed Imre Deak
                   ` (9 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

At the moment modesetting a stream CRTC will fail if the stream's BW
along with the current BW of all the other streams on the same MST link
is above the total BW of the MST link. Make the BW sharing more dynamic
by trying to reduce the link bpp of one or more streams on the MST link
in this case.

When selecting a stream to reduce the BW for, take into account which
link segment in the MST topology ran out of BW and which streams go
through this link segment. For instance with A,B,C streams in the same
MST topology A and B may share the BW of a link segment downstream of a
branch device, stream C not downstream of the branch device, hence not
affecting this BW. If this link segment's BW runs out one or both of
stream A/B's BW will be reduced until their total BW is within limits.

While reducing the link bpp for a given stream DSC may need to be
enabled for it, which requires FEC on the whole MST link. Check for this
condition and recompute the state for all streams taking the FEC
overhead into account (on 8b/10b links).

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |   5 +-
 drivers/gpu/drm/i915/display/intel_dp.c      |  13 +-
 drivers/gpu/drm/i915/display/intel_dp.h      |   2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 129 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h  |   3 +
 drivers/gpu/drm/i915/display/intel_link_bw.c |  15 ++-
 drivers/gpu/drm/i915/display/intel_link_bw.h |   1 +
 7 files changed, 159 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 31297a333f50e..e2f5f66c132b7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4629,6 +4629,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe);
 	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
 
 	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
@@ -6408,10 +6409,6 @@ int intel_atomic_check(struct drm_device *dev,
 		goto fail;
 	}
 
-	ret = drm_dp_mst_atomic_check(&state->base);
-	if (ret)
-		goto fail;
-
 	ret = intel_atomic_check_planes(state);
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ce8eafa4ece06..f18cde380e0cb 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1369,8 +1369,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
 	return false;
 }
 
-static bool intel_dp_supports_fec(struct intel_dp *intel_dp,
-				  const struct intel_crtc_state *pipe_config)
+bool intel_dp_supports_fec(struct intel_dp *intel_dp,
+			   const struct intel_crtc_state *pipe_config)
 {
 	return intel_dp_source_supports_fec(intel_dp, pipe_config) &&
 		drm_dp_sink_supports_fec(intel_dp->fec_capable);
@@ -2111,8 +2111,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 		&pipe_config->hw.adjusted_mode;
 	int ret;
 
-	pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
-		intel_dp_supports_fec(intel_dp, pipe_config);
+	pipe_config->fec_enable = pipe_config->fec_enable ||
+		(!intel_dp_is_edp(intel_dp) &&
+		 intel_dp_supports_fec(intel_dp, pipe_config));
 
 	if (!intel_dp_supports_dsc(intel_dp, pipe_config))
 		return -EINVAL;
@@ -2308,6 +2309,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	bool dsc_needed;
 	int ret = 0;
 
+	if (pipe_config->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, pipe_config))
+		return -EINVAL;
+
 	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
 				    adjusted_mode->crtc_clock))
 		pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 2cf3681bac64a..612105a303419 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -135,6 +135,8 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
 	return ~((1 << lane_count) - 1) & 0xf;
 }
 
+bool intel_dp_supports_fec(struct intel_dp *intel_dp,
+			   const struct intel_crtc_state *pipe_config);
 u32 intel_dp_mode_to_fec_clock(u32 mode_clock);
 u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f24f656d6d02a..bcfd5f19d994f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -43,6 +43,7 @@
 #include "intel_dpio_phy.h"
 #include "intel_hdcp.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_vdsc.h"
 #include "skl_scaler.h"
 
@@ -369,6 +370,10 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	bool dsc_needed;
 	int ret = 0;
 
+	if (pipe_config->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, pipe_config))
+		return -EINVAL;
+
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
@@ -488,6 +493,130 @@ intel_dp_mst_transcoder_mask(struct intel_atomic_state *state,
 	return transcoders;
 }
 
+static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
+					   struct drm_dp_mst_topology_mgr *mst_mgr,
+					   struct drm_dp_mst_port *parent_port)
+{
+	const struct intel_digital_connector_state *conn_state;
+	struct intel_connector *connector;
+	u8 mask = 0;
+	int i;
+
+	for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
+		if (!conn_state->base.crtc)
+			continue;
+
+		if (&connector->mst_port->mst_mgr != mst_mgr)
+			continue;
+
+		if (connector->port != parent_port &&
+		    !drm_dp_mst_port_downstream_of_parent(mst_mgr,
+							  connector->port,
+							  parent_port))
+			continue;
+
+		mask |= BIT(to_intel_crtc(conn_state->base.crtc)->pipe);
+	}
+
+	return mask;
+}
+
+static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
+					 struct drm_dp_mst_topology_mgr *mst_mgr,
+					 struct intel_link_bw_limits *limits)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc *crtc;
+	u8 mst_pipe_mask;
+	u8 fec_pipe_mask = 0;
+	int ret;
+
+	mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mst_pipe_mask) {
+		struct intel_crtc_state *crtc_state =
+			intel_atomic_get_new_crtc_state(state, crtc);
+
+		/* Atomic connector check should've added all the MST CRTCs. */
+		if (drm_WARN_ON(&i915->drm, !crtc_state))
+			return -EINVAL;
+
+		if (crtc_state->fec_enable)
+			fec_pipe_mask |= BIT(crtc->pipe);
+	}
+
+	if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask)
+		return 0;
+
+	limits->force_fec_pipes |= mst_pipe_mask;
+
+	ret = intel_modeset_pipes_in_mask_early(state, "MST FEC",
+						mst_pipe_mask);
+
+	return ret ? : -EAGAIN;
+}
+
+static int intel_dp_mst_check_bw(struct intel_atomic_state *state,
+				 struct drm_dp_mst_topology_mgr *mst_mgr,
+				 struct drm_dp_mst_topology_state *mst_state,
+				 struct intel_link_bw_limits *limits)
+{
+	struct drm_dp_mst_port *mst_port;
+	u8 mst_port_pipes;
+	int ret;
+
+	ret = drm_dp_mst_atomic_check_mgr(&state->base, mst_mgr, mst_state, &mst_port);
+	if (ret != -ENOSPC)
+		return ret;
+
+	mst_port_pipes = get_pipes_downstream_of_mst_port(state, mst_mgr, mst_port);
+
+	ret = intel_link_bw_reduce_bpp(state, limits,
+				       mst_port_pipes, "MST link BW");
+
+	return ret ? : -EAGAIN;
+}
+
+/**
+ * intel_dp_mst_atomic_check_link - check all modeset MST link configuration
+ * @state: intel atomic state
+ * @limits: link BW limits
+ *
+ * Check the link configuration for all modeset MST outputs. If the
+ * configuration is invalid @limits will be updated if possible to
+ * reduce the total BW, after which the configuration for all CRTCs in
+ * @state must be recomputed with the updated @limits.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @limits got updated
+ *     with fallback values with which the configuration of all CRTCs in
+ *     @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
+				   struct intel_link_bw_limits *limits)
+{
+	struct drm_dp_mst_topology_mgr *mgr;
+	struct drm_dp_mst_topology_state *mst_state;
+	int ret;
+	int i;
+
+	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
+		ret = intel_dp_mst_check_fec_change(state, mgr, limits);
+		if (ret)
+			return ret;
+
+		ret = intel_dp_mst_check_bw(state, mgr, mst_state,
+					    limits);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int intel_dp_mst_compute_config_late(struct intel_encoder *encoder,
 					    struct intel_crtc_state *crtc_state,
 					    struct drm_connector_state *conn_state)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index f1815bb722672..4e836b9ac6061 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -13,6 +13,7 @@ struct intel_crtc;
 struct intel_crtc_state;
 struct intel_digital_port;
 struct intel_dp;
+struct intel_link_bw_limits;
 
 int intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port);
@@ -22,5 +23,7 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
 int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 					     struct intel_crtc *crtc);
+int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
+				   struct intel_link_bw_limits *limits);
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
index aacf22bab3135..f476422cd10a5 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -22,6 +22,7 @@ void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_
 {
 	enum pipe pipe;
 
+	limits->force_fec_pipes = 0;
 	limits->min_bpp_pipes = 0;
 	for_each_pipe(i915, pipe)
 		limits->max_bpp_x16[pipe] = INT_MAX;
@@ -162,6 +163,10 @@ static int check_all_link_config(struct intel_atomic_state *state,
 {
 	int ret;
 
+	ret = intel_dp_mst_atomic_check_link(state, limits);
+	if (ret)
+		return ret;
+
 	ret = intel_fdi_atomic_check_link(state, limits);
 	if (ret)
 		return ret;
@@ -177,6 +182,12 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
 	bool bpps_changed = false;
 	enum pipe pipe;
 
+	/* FEC can't be forced off after it was forced on. */
+	if (drm_WARN_ON(&i915->drm,
+			(old_limits->force_fec_pipes & new_limits->force_fec_pipes) !=
+			old_limits->force_fec_pipes))
+		return false;
+
 	for_each_pipe(i915, pipe) {
 		/* The bpp limit can only decrease. */
 		if (drm_WARN_ON(&i915->drm,
@@ -191,7 +202,9 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
 
 	/* At least one limit must change. */
 	if (drm_WARN_ON(&i915->drm,
-			!bpps_changed))
+			!bpps_changed &&
+			new_limits->force_fec_pipes ==
+			old_limits->force_fec_pipes))
 		return false;
 
 	return true;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
index e514caff5898e..ca72d80267057 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -16,6 +16,7 @@ struct intel_atomic_state;
 struct intel_crtc_state;
 
 struct intel_link_bw_limits {
+	u8 force_fec_pipes;
 	u8 min_bpp_pipes;
 	/* in 1/16 bpp units */
 	int max_bpp_x16[I915_MAX_PIPES];
-- 
2.37.2


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

* [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (23 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams Imre Deak
@ 2023-09-14 19:26 ` Imre Deak
  2023-09-25  7:54   ` Lisovskiy, Stanislav
  2023-09-14 23:33 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev4) Patchwork
                   ` (8 subsequent siblings)
  33 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-14 19:26 UTC (permalink / raw)
  To: intel-gfx

After the previous patch the BW limits on the whole MST topology will be
checked after computing the state for all the streams in the topology.
Accordingly remove the check during the stream's encoder compute config
step, to prevent failing an atomic commit due to a BW limit, if this can
be resolved only by reducing the BW of other streams on the same MST
link.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index bcfd5f19d994f..64867289174d9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -121,15 +121,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
 		if (slots == -EDEADLK)
 			return slots;
 
-		if (slots >= 0) {
-			ret = drm_dp_mst_atomic_check(state);
-			/*
-			 * If we got slots >= 0 and we can fit those based on check
-			 * then we can exit the loop. Otherwise keep trying.
-			 */
-			if (!ret)
-				break;
-		}
+		if (slots >= 0)
+			break;
 	}
 
 	/* We failed to find a proper bpp/timeslots, return error */
-- 
2.37.2


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

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev4)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (24 preceding siblings ...)
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed Imre Deak
@ 2023-09-14 23:33 ` Patchwork
  2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev5) Patchwork
                   ` (7 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-14 23:33 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev4)
URL   : https://patchwork.freedesktop.org/series/122589/
State : failure

== Summary ==

Error: make failed
  CALL    scripts/checksyscalls.sh
  DESCEND objtool
  INSTALL libsubcmd_headers
  CC [M]  drivers/gpu/drm/i915/display/intel_display.o
drivers/gpu/drm/i915/display/intel_display.c:6198:5: error: no previous prototype for ‘intel_atomic_check_config’ [-Werror=missing-prototypes]
 6198 | int intel_atomic_check_config(struct intel_atomic_state *state,
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[6]: *** [scripts/Makefile.build:243: drivers/gpu/drm/i915/display/intel_display.o] Error 1
make[5]: *** [scripts/Makefile.build:480: drivers/gpu/drm/i915] Error 2
make[4]: *** [scripts/Makefile.build:480: drivers/gpu/drm] Error 2
make[3]: *** [scripts/Makefile.build:480: drivers/gpu] Error 2
make[2]: *** [scripts/Makefile.build:480: drivers] Error 2
make[1]: *** [/home/kbuild2/kernel/Makefile:1913: .] Error 2
make: *** [Makefile:234: __sub-make] Error 2
Build failed, no error log produced



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

* [Intel-gfx] [PATCH v4 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 09/25] drm/i915: Add helpers for BW management on shared display links Imre Deak
@ 2023-09-15  0:33   ` Imre Deak
  2023-09-15 19:11     ` Ville Syrjälä
  2023-09-18 18:25     ` [Intel-gfx] [PATCH v5 " Imre Deak
  0 siblings, 2 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-15  0:33 UTC (permalink / raw)
  To: intel-gfx

At the moment a modeset fails if the config computation of a pipe can't
fit its required BW to the available link BW even though the limitation
may be resolved by reducing the BW requirement of other pipes.

To improve the above this patch adds helper functions checking the
overall BW limits after all CRTC states have been computed. If the check
fails the maximum link bpp for a selected pipe will be reduced and all
the CRTC states will be recomputed until either the overall BW limit
check passes, or further bpp reduction is not possible (because all
pipes/encoders sharing the link BW reached their minimum link bpp).

This change prepares for upcoming patches enabling the above BW
management on FDI and MST links.

v2:
- Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
  intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
v3:
- Add the helper functions in a separate patch. (Ville)
- Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
- Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
  limit failure.
v4:
- Make intel_atomic_check_config() static.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  61 ++++-
 .../drm/i915/display/intel_display_types.h    |   3 +-
 drivers/gpu/drm/i915/display/intel_link_bw.c  | 226 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
 6 files changed, 325 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1b2e02e9d92cb..de4967c141f00 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -268,6 +268,7 @@ i915-y += \
 	display/intel_hotplug.o \
 	display/intel_hotplug_irq.o \
 	display/intel_hti.o \
+	display/intel_link_bw.o \
 	display/intel_load_detect.o \
 	display/intel_lpe_audio.o \
 	display/intel_modeset_lock.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 182c6dd64f47c..1eda6a9f19aa8 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
 	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
 	crtc_state->scaler_state.scaler_id = -1;
 	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+	crtc_state->max_link_bpp_x16 = INT_MAX;
 }
 
 static struct intel_crtc *intel_crtc_alloc(void)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index fe3b6844e063d..0f30723a68cc0 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -87,6 +87,7 @@
 #include "intel_frontbuffer.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_modeset_setup.h"
@@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
 
 static int
 intel_modeset_pipe_config(struct intel_atomic_state *state,
-			  struct intel_crtc *crtc)
+			  struct intel_crtc *crtc,
+			  const struct intel_link_bw_limits *limits)
 {
 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
 	struct intel_crtc_state *crtc_state =
@@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
+
+	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
+		drm_dbg_kms(&i915->drm,
+			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
+			    crtc->base.base.id, crtc->base.name,
+			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+	}
+
 	base_bpp = crtc_state->pipe_bpp;
 
 	/*
@@ -6195,7 +6206,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
-static int intel_atomic_check_config(struct intel_atomic_state *state)
+static int intel_atomic_check_config(struct intel_atomic_state *state,
+				     struct intel_link_bw_limits *limits,
+				     enum pipe *failed_pipe)
 {
 	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct intel_crtc_state *new_crtc_state;
@@ -6203,6 +6216,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 	int ret;
 	int i;
 
+	*failed_pipe = INVALID_PIPE;
+
 	ret = intel_bigjoiner_add_affected_crtcs(state);
 	if (ret)
 		return ret;
@@ -6228,7 +6243,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 		if (!new_crtc_state->hw.enable)
 			continue;
 
-		ret = intel_modeset_pipe_config(state, crtc);
+		ret = intel_modeset_pipe_config(state, crtc, limits);
 		if (ret)
 			break;
 
@@ -6237,9 +6252,47 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 			break;
 	}
 
+	if (ret)
+		*failed_pipe = crtc->pipe;
+
 	return ret;
 }
 
+static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits new_limits;
+	struct intel_link_bw_limits old_limits;
+	int ret;
+
+	intel_link_bw_init_limits(i915, &new_limits);
+	old_limits = new_limits;
+
+	while (true) {
+		enum pipe failed_pipe;
+
+		ret = intel_atomic_check_config(state, &new_limits,
+						&failed_pipe);
+		if (ret) {
+			if (ret == -EINVAL &&
+			    intel_link_bw_reset_pipe_limit_to_min(state,
+								  &old_limits,
+								  &new_limits,
+								  failed_pipe))
+				continue;
+
+			break;
+		}
+
+		old_limits = new_limits;
+
+		ret = intel_link_bw_atomic_check(state, &new_limits);
+		if (ret != -EAGAIN)
+			break;
+	}
+
+	return ret;
+}
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -6284,7 +6337,7 @@ int intel_atomic_check(struct drm_device *dev,
 			return ret;
 	}
 
-	ret = intel_atomic_check_config(state);
+	ret = intel_atomic_check_config_and_link(state);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 966163ccbd7a3..514977ebc17b0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1189,7 +1189,8 @@ struct intel_crtc_state {
 		u32 ctrl, div;
 	} dsi_pll;
 
-	int pipe_bpp;
+	int max_link_bpp_x16;	/* in 1/16 bpp units */
+	int pipe_bpp;		/* in 1 bpp units */
 	struct intel_link_m_n dp_m_n;
 
 	/* m2_n2 for eDP downclock */
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
new file mode 100644
index 0000000000000..22494772b9d59
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+
+#include "intel_atomic.h"
+#include "intel_display_types.h"
+#include "intel_dp_mst.h"
+#include "intel_fdi.h"
+#include "intel_link_bw.h"
+
+/**
+ * intel_link_bw_init_limits - initialize BW limits
+ * @i915: device instance
+ * @limits: link BW limits
+ *
+ * Initialize @limits.
+ */
+void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
+{
+	enum pipe pipe;
+
+	limits->min_bpp_pipes = 0;
+	for_each_pipe(i915, pipe)
+		limits->max_bpp_x16[pipe] = INT_MAX;
+}
+
+/**
+ * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
+ * @crtc_state: the crtc state
+ *
+ * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
+ * call this function during state computation in the simple case where the
+ * link bpp will always match the pipe bpp. This is the case for all non-DP
+ * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
+ * of DSC compression.
+ *
+ * Returns %true in case of success, %false if pipe bpp would need to be
+ * reduced below its valid range.
+ */
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
+{
+	int pipe_bpp = min(crtc_state->pipe_bpp,
+			   to_bpp_int(crtc_state->max_link_bpp_x16));
+
+	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
+
+	if (pipe_bpp < 6 * 3)
+		return false;
+
+	crtc_state->pipe_bpp = pipe_bpp;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
+ * @state: atomic state
+ * @limits: link BW limits
+ * @pipe_mask: mask of pipes to select from
+ * @reason: explanation of why bpp reduction is needed
+ *
+ * Select the pipe from @pipe_mask with the biggest link bpp value and set the
+ * maximum of link bpp in @limits below this value. Modeset the selected pipe,
+ * so that its state will get recomputed.
+ *
+ * This function can be called to resolve a link's BW overallocation by reducing
+ * the link bpp of one pipe on the link and hence reducing the total link BW.
+ *
+ * Returns
+ *   - 0 in case of success
+ *   - %-ENOSPC if no pipe can further reduce its link bpp
+ *   - Other negative error, if modesetting the selected pipe failed
+ */
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	enum pipe max_bpp_pipe = INVALID_PIPE;
+	struct intel_crtc *crtc;
+	int max_bpp = 0;
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
+		struct intel_crtc_state *crtc_state;
+		int pipe_bpp;
+
+		if (limits->min_bpp_pipes & BIT(crtc->pipe))
+			continue;
+
+		crtc_state = intel_atomic_get_crtc_state(&state->base,
+							 crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		if (crtc_state->dsc.compression_enable)
+			pipe_bpp = crtc_state->dsc.compressed_bpp;
+		else
+			pipe_bpp = crtc_state->pipe_bpp;
+
+		if (pipe_bpp > max_bpp) {
+			max_bpp = pipe_bpp;
+			max_bpp_pipe = crtc->pipe;
+		}
+	}
+
+	if (max_bpp_pipe == INVALID_PIPE)
+		return -ENOSPC;
+
+	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
+
+	return intel_modeset_pipes_in_mask_early(state, reason,
+						 BIT(max_bpp_pipe));
+}
+
+/**
+ * intel_link_bw_reset_pipe_limit_to_min - reset BW limit for a pipe to its minimum
+ * @state: atomic state
+ * @old_limits: link BW limits
+ * @new_limits: link BW limits
+ * @pipe: pipe
+ *
+ * Reset the link bpp limit for @pipe in @new_limits to its value in
+ * @old_limits and mark this limit as the minimum. This function must be
+ * called after a pipe's compute config function failed, @old_limits
+ * containing the bpp limit with which compute config previously passed.
+ *
+ * The function will fail if setting a minimum is not possible, either
+ * because the old and new limits match (and so would lead to a pipe compute
+ * config failure) or the limit is already at the minimum.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
+				       const struct intel_link_bw_limits *old_limits,
+				       struct intel_link_bw_limits *new_limits,
+				       enum pipe pipe)
+{
+	if (pipe == INVALID_PIPE)
+		return false;
+
+	if (new_limits->min_bpp_pipes & BIT(pipe))
+		return false;
+
+	if (new_limits->max_bpp_x16[pipe] ==
+	    old_limits->max_bpp_x16[pipe])
+		return false;
+
+	new_limits->max_bpp_x16[pipe] =
+		old_limits->max_bpp_x16[pipe];
+	new_limits->min_bpp_pipes |= BIT(pipe);
+
+	return true;
+}
+
+static int check_all_link_config(struct intel_atomic_state *state,
+				 struct intel_link_bw_limits *limits)
+{
+	/* TODO: Check all shared display link configurations like FDI */
+	return 0;
+}
+
+static bool
+assert_link_limit_change_valid(struct drm_i915_private *i915,
+			       const struct intel_link_bw_limits *old_limits,
+			       const struct intel_link_bw_limits *new_limits)
+{
+	bool bpps_changed = false;
+	enum pipe pipe;
+
+	for_each_pipe(i915, pipe) {
+		/* The bpp limit can only decrease. */
+		if (drm_WARN_ON(&i915->drm,
+				new_limits->max_bpp_x16[pipe] >
+				old_limits->max_bpp_x16[pipe]))
+			return false;
+
+		if (new_limits->max_bpp_x16[pipe] <
+		    old_limits->max_bpp_x16[pipe])
+			bpps_changed = true;
+	}
+
+	/* At least one limit must change. */
+	if (drm_WARN_ON(&i915->drm,
+			!bpps_changed))
+		return false;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
+ * @state: atomic state
+ * @new_limits: link BW limits
+ *
+ * Check the configuration of all shared display links in @state and set new BW
+ * limits in @new_limits if there is a BW limitation.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
+ *     with fallback values with which the configuration of all CRTCs
+ *     in @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits old_limits = *new_limits;
+	int ret;
+
+	ret = check_all_link_config(state, new_limits);
+	if (ret != -EAGAIN)
+		return ret;
+
+	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
+		return -EINVAL;
+
+	return -EAGAIN;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
new file mode 100644
index 0000000000000..e514caff5898e
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_LINK_BW_H__
+#define __INTEL_LINK_BW_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+struct drm_i915_private;
+
+struct intel_atomic_state;
+struct intel_crtc_state;
+
+struct intel_link_bw_limits {
+	u8 min_bpp_pipes;
+	/* in 1/16 bpp units */
+	int max_bpp_x16[I915_MAX_PIPES];
+};
+
+void intel_link_bw_init_limits(struct drm_i915_private *i915,
+			       struct intel_link_bw_limits *limits);
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason);
+bool intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
+					   const struct intel_link_bw_limits *old_limits,
+					   struct intel_link_bw_limits *new_limits,
+					   enum pipe pipe);
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits);
+
+#endif
-- 
2.37.2


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev5)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (25 preceding siblings ...)
  2023-09-14 23:33 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev4) Patchwork
@ 2023-09-15  4:07 ` Patchwork
  2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (6 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-15  4:07 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev5)
URL   : https://patchwork.freedesktop.org/series/122589/
State : warning

== Summary ==

Error: dim checkpatch failed
1c45ddaa2306 drm/i915/dp: Factor out helpers to compute the link limits
-:122: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#122: FILE: drivers/gpu/drm/i915/display/intel_dp_mst.c:305:
+	limits->min_rate = limits->max_rate =

-:125: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#125: FILE: drivers/gpu/drm/i915/display/intel_dp_mst.c:308:
+	limits->min_lane_count = limits->max_lane_count =

total: 0 errors, 0 warnings, 2 checks, 147 lines checked
5cbf75c5fb66 drm/i915/dp: Track the pipe and link bpp limits separately
-:49: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#49: FILE: drivers/gpu/drm/i915/display/intel_dp.c:1473:
+		limits->pipe.min_bpp = limits->pipe.max_bpp = bpp;

-:106: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#106: FILE: drivers/gpu/drm/i915/display/intel_dp.c:2211:
+	limits->pipe.max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
+						     respect_downstream_limits);

total: 0 errors, 0 warnings, 2 checks, 146 lines checked
2e87799dc7ea drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
667d1ee529b5 drm/i915/dp: Update the link bpp limits for DSC mode
-:42: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#42: FILE: drivers/gpu/drm/i915/display/intel_display_types.h:2124:
+#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)

-:42: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'bpp_x16' - possible side-effects?
#42: FILE: drivers/gpu/drm/i915/display/intel_display_types.h:2124:
+#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)

-:102: WARNING:LONG_LINE: line length of 164 exceeds 100 columns
#102: FILE: drivers/gpu/drm/i915/display/intel_dp.c:2239:
+		    "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",

total: 1 errors, 1 warnings, 1 checks, 201 lines checked
34432c0c443b drm/i915/dp: Limit the output link bpp in DSC mode
e8ed36a51e75 drm/i915: Add helper to modeset a set of pipes
cb5bc3bee5cb drm/i915: During modeset forcing handle inactive but enabled pipes
a17735557882 drm/i915: Factor out a helper to check/compute all the CRTC states
5d31d9dbb9ed drm/i915: Add helpers for BW management on shared display links
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:202: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#202: 
new file mode 100644

-:345: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#345: FILE: drivers/gpu/drm/i915/display/intel_link_bw.c:139:
+intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
+				       const struct intel_link_bw_limits *old_limits,

total: 0 errors, 1 warnings, 1 checks, 399 lines checked
ed7982fe9d39 drm/i915/fdi: Improve FDI BW sharing between pipe B and C
b38be1ad15df drm/i915/fdi: Recompute state for affected CRTCs on FDI links
99d9a52aa5ea drm/dp_mst: Fix fractional DSC bpp handling
41e7f4331308 drm/dp_mst: Add a way to calculate PBN values with FEC overhead
25a200eb8743 drm/dp_mst: Add helper to determine if an MST port is downstream of another port
24bf5adfae59 drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
f3ffe6554889 drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
21f5901a18f8 drm/i915/dp_mst: Fix PBN calculation with FEC overhead
9a1abab8aa76 drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
60fff6a4ea44 drm/i915/dp_mst: Program the DSC PPS SDP for each stream
4890fc83d5c6 drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
32535a81601d drm/i915/dp_mst: Enable DSC decompression if any stream needs this
4867d9c884e6 drm/i915/dp_mst: Add missing DSC compression disabling
b57b36c685a6 drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
d09682322e32 drm/i915/dp_mst: Improve BW sharing between MST streams
54f569c34398 drm/i915/dp_mst: Check BW limitations only after all streams are computed



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Improve BW management on shared display links (rev5)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (26 preceding siblings ...)
  2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev5) Patchwork
@ 2023-09-15  4:07 ` Patchwork
  2023-09-15  4:21 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
                   ` (5 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-15  4:07 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev5)
URL   : https://patchwork.freedesktop.org/series/122589/
State : warning

== Summary ==

Error: dim sparse failed
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915: Improve BW management on shared display links (rev5)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (27 preceding siblings ...)
  2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2023-09-15  4:21 ` Patchwork
  2023-09-15 12:39 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
                   ` (4 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-15  4:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 6336 bytes --]

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev5)
URL   : https://patchwork.freedesktop.org/series/122589/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_13635 -> Patchwork_122589v5
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (40 -> 40)
------------------------------

  Additional (1): fi-kbl-soraka 
  Missing    (1): fi-snb-2520m 

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_parallel@engines@fds:
    - bat-mtlp-6:         [PASS][1] -> [ABORT][2] ([i915#9262])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/bat-mtlp-6/igt@gem_exec_parallel@engines@fds.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/bat-mtlp-6/igt@gem_exec_parallel@engines@fds.html

  * igt@gem_huc_copy@huc-copy:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][3] ([fdo#109271] / [i915#2190])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-kbl-soraka/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@basic:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][4] ([fdo#109271] / [i915#4613]) +3 other tests skip
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-kbl-soraka/igt@gem_lmem_swapping@basic.html

  * igt@i915_selftest@live@gem_contexts:
    - bat-atsm-1:         [PASS][5] -> [INCOMPLETE][6] ([i915#7913])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/bat-atsm-1/igt@i915_selftest@live@gem_contexts.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/bat-atsm-1/igt@i915_selftest@live@gem_contexts.html

  * igt@i915_selftest@live@gt_pm:
    - fi-kbl-soraka:      NOTRUN -> [DMESG-FAIL][7] ([i915#1886] / [i915#7913])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-kbl-soraka/igt@i915_selftest@live@gt_pm.html

  * igt@i915_suspend@basic-s3-without-i915:
    - fi-bsw-nick:        [PASS][8] -> [INCOMPLETE][9] ([i915#4817])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/fi-bsw-nick/igt@i915_suspend@basic-s3-without-i915.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-bsw-nick/igt@i915_suspend@basic-s3-without-i915.html

  * igt@kms_dsc@dsc-basic:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][10] ([fdo#109271]) +9 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-kbl-soraka/igt@kms_dsc@dsc-basic.html

  
#### Possible fixes ####

  * igt@kms_hdmi_inject@inject-audio:
    - fi-kbl-guc:         [FAIL][11] ([IGT#3] / [i915#6121]) -> [PASS][12]
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html

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

  [IGT#3]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/3
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1886]: https://gitlab.freedesktop.org/drm/intel/issues/1886
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4817]: https://gitlab.freedesktop.org/drm/intel/issues/4817
  [i915#6121]: https://gitlab.freedesktop.org/drm/intel/issues/6121
  [i915#7913]: https://gitlab.freedesktop.org/drm/intel/issues/7913
  [i915#7952]: https://gitlab.freedesktop.org/drm/intel/issues/7952
  [i915#9262]: https://gitlab.freedesktop.org/drm/intel/issues/9262


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

  * Linux: CI_DRM_13635 -> Patchwork_122589v5

  CI-20190529: 20190529
  CI_DRM_13635: c6b7f865a77a75af03c3b68baa4cf7eb66c1c6d5 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_7488: 099e058c5dfb7a49942edf03cae88a52a77077a3 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_122589v5: c6b7f865a77a75af03c3b68baa4cf7eb66c1c6d5 @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

b0a3d0b34309 drm/i915/dp_mst: Check BW limitations only after all streams are computed
6f8f53129a5a drm/i915/dp_mst: Improve BW sharing between MST streams
b5a5a7f88084 drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
6cd5e811c7a4 drm/i915/dp_mst: Add missing DSC compression disabling
ee9689328b06 drm/i915/dp_mst: Enable DSC decompression if any stream needs this
c64811bf340a drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
4f9f7b30b991 drm/i915/dp_mst: Program the DSC PPS SDP for each stream
e5c67f3706d4 drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
65967e8437cc drm/i915/dp_mst: Fix PBN calculation with FEC overhead
03059d0858d7 drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
29ca3c422569 drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
35a8b403f58d drm/dp_mst: Add helper to determine if an MST port is downstream of another port
71687e696a15 drm/dp_mst: Add a way to calculate PBN values with FEC overhead
58d1f25e15c9 drm/dp_mst: Fix fractional DSC bpp handling
e109cfb89599 drm/i915/fdi: Recompute state for affected CRTCs on FDI links
314ac7782bf0 drm/i915/fdi: Improve FDI BW sharing between pipe B and C
24c6f63b9a40 drm/i915: Add helpers for BW management on shared display links
1a0464f77ef3 drm/i915: Factor out a helper to check/compute all the CRTC states
05b0b8c7a6c8 drm/i915: During modeset forcing handle inactive but enabled pipes
abced857c3da drm/i915: Add helper to modeset a set of pipes
44766c4ad358 drm/i915/dp: Limit the output link bpp in DSC mode
10af6187546d drm/i915/dp: Update the link bpp limits for DSC mode
a6834e84dc6f drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
bf33bf15dd1a drm/i915/dp: Track the pipe and link bpp limits separately
f396a776eb3a drm/i915/dp: Factor out helpers to compute the link limits

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/index.html

[-- Attachment #2: Type: text/html, Size: 7415 bytes --]

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

* [Intel-gfx] ✗ Fi.CI.IGT: failure for drm/i915: Improve BW management on shared display links (rev5)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (28 preceding siblings ...)
  2023-09-15  4:21 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2023-09-15 12:39 ` Patchwork
  2023-09-19  1:11 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev9) Patchwork
                   ` (3 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-15 12:39 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 57068 bytes --]

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev5)
URL   : https://patchwork.freedesktop.org/series/122589/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_13635_full -> Patchwork_122589v5_full
====================================================

Summary
-------

  **FAILURE**

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

  

Participating hosts (9 -> 9)
------------------------------

  No changes in participating hosts

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@gem_ccs@suspend-resume@tile4-compressed-compfmt0-lmem0-lmem0:
    - shard-dg2:          NOTRUN -> [INCOMPLETE][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-6/igt@gem_ccs@suspend-resume@tile4-compressed-compfmt0-lmem0-lmem0.html

  * igt@gem_exec_flush@basic-wb-pro-default:
    - shard-snb:          [PASS][2] -> [ABORT][3]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-snb5/igt@gem_exec_flush@basic-wb-pro-default.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb2/igt@gem_exec_flush@basic-wb-pro-default.html

  * igt@gem_exec_suspend@basic-s0@smem:
    - shard-dg2:          [PASS][4] -> [INCOMPLETE][5]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg2-3/igt@gem_exec_suspend@basic-s0@smem.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-1/igt@gem_exec_suspend@basic-s0@smem.html

  * igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend:
    - shard-apl:          [PASS][6] -> [INCOMPLETE][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-apl2/igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-apl6/igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend.html

  * igt@sysfs_timeslice_duration@timeout@ccs3:
    - shard-dg2:          NOTRUN -> [ABORT][8]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@sysfs_timeslice_duration@timeout@ccs3.html

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

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

### IGT changes ###

#### Issues hit ####

  * igt@api_intel_bb@blit-reloc-purge-cache:
    - shard-dg2:          NOTRUN -> [SKIP][9] ([i915#8411])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@api_intel_bb@blit-reloc-purge-cache.html

  * igt@device_reset@unbind-cold-reset-rebind:
    - shard-mtlp:         NOTRUN -> [SKIP][10] ([i915#7701])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@device_reset@unbind-cold-reset-rebind.html

  * igt@drm_fdinfo@most-busy-idle-check-all@rcs0:
    - shard-rkl:          [PASS][11] -> [FAIL][12] ([i915#7742])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-4/igt@drm_fdinfo@most-busy-idle-check-all@rcs0.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-7/igt@drm_fdinfo@most-busy-idle-check-all@rcs0.html

  * igt@drm_fdinfo@most-busy-idle-check-all@vecs1:
    - shard-dg2:          NOTRUN -> [SKIP][13] ([i915#8414]) +19 other tests skip
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@drm_fdinfo@most-busy-idle-check-all@vecs1.html

  * igt@drm_fdinfo@virtual-busy-all:
    - shard-mtlp:         NOTRUN -> [SKIP][14] ([i915#8414])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@drm_fdinfo@virtual-busy-all.html

  * igt@gem_ctx_exec@basic-nohangcheck:
    - shard-rkl:          [PASS][15] -> [FAIL][16] ([i915#6268])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-2/igt@gem_ctx_exec@basic-nohangcheck.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-1/igt@gem_ctx_exec@basic-nohangcheck.html

  * igt@gem_ctx_isolation@preservation-s3@bcs0:
    - shard-dg2:          [PASS][17] -> [FAIL][18] ([fdo#103375]) +1 other test fail
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg2-10/igt@gem_ctx_isolation@preservation-s3@bcs0.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_ctx_isolation@preservation-s3@bcs0.html

  * igt@gem_eio@hibernate:
    - shard-dg1:          [PASS][19] -> [ABORT][20] ([i915#7975] / [i915#8213])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-18/igt@gem_eio@hibernate.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-14/igt@gem_eio@hibernate.html

  * igt@gem_eio@in-flight-suspend:
    - shard-mtlp:         NOTRUN -> [ABORT][21] ([i915#7892] / [i915#9262])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gem_eio@in-flight-suspend.html

  * igt@gem_exec_balancer@bonded-dual:
    - shard-dg2:          NOTRUN -> [SKIP][22] ([i915#4771])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_exec_balancer@bonded-dual.html

  * igt@gem_exec_balancer@hang:
    - shard-mtlp:         [PASS][23] -> [ABORT][24] ([i915#8104] / [i915#9262])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-6/igt@gem_exec_balancer@hang.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-8/igt@gem_exec_balancer@hang.html

  * igt@gem_exec_balancer@noheartbeat:
    - shard-dg2:          NOTRUN -> [SKIP][25] ([i915#8555])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_exec_balancer@noheartbeat.html

  * igt@gem_exec_fair@basic-pace:
    - shard-dg2:          NOTRUN -> [SKIP][26] ([i915#3539])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_exec_fair@basic-pace.html

  * igt@gem_exec_fence@submit3:
    - shard-dg2:          NOTRUN -> [SKIP][27] ([i915#4812]) +1 other test skip
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_exec_fence@submit3.html

  * igt@gem_exec_flush@basic-batch-kernel-default-wb:
    - shard-dg2:          NOTRUN -> [SKIP][28] ([i915#3539] / [i915#4852]) +1 other test skip
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_exec_flush@basic-batch-kernel-default-wb.html

  * igt@gem_exec_params@secure-non-master:
    - shard-dg2:          NOTRUN -> [SKIP][29] ([fdo#112283])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_exec_params@secure-non-master.html

  * igt@gem_exec_reloc@basic-cpu-read-noreloc:
    - shard-mtlp:         NOTRUN -> [SKIP][30] ([i915#3281])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gem_exec_reloc@basic-cpu-read-noreloc.html

  * igt@gem_exec_reloc@basic-gtt-cpu-active:
    - shard-dg2:          NOTRUN -> [SKIP][31] ([i915#3281]) +5 other tests skip
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_exec_reloc@basic-gtt-cpu-active.html

  * igt@gem_exec_reloc@basic-write-wc-noreloc:
    - shard-dg1:          NOTRUN -> [SKIP][32] ([i915#3281])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_exec_reloc@basic-write-wc-noreloc.html

  * igt@gem_exec_schedule@noreorder@bcs0:
    - shard-mtlp:         [PASS][33] -> [DMESG-FAIL][34] ([i915#9121]) +1 other test dmesg-fail
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-7/igt@gem_exec_schedule@noreorder@bcs0.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-4/igt@gem_exec_schedule@noreorder@bcs0.html

  * igt@gem_exec_schedule@noreorder@ccs0:
    - shard-mtlp:         [PASS][35] -> [DMESG-WARN][36] ([i915#8962] / [i915#9121])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-7/igt@gem_exec_schedule@noreorder@ccs0.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-4/igt@gem_exec_schedule@noreorder@ccs0.html

  * igt@gem_fenced_exec_thrash@too-many-fences:
    - shard-dg2:          NOTRUN -> [SKIP][37] ([i915#4860])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_fenced_exec_thrash@too-many-fences.html

  * igt@gem_lmem_swapping@heavy-verify-random-ccs:
    - shard-mtlp:         NOTRUN -> [SKIP][38] ([i915#4613])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gem_lmem_swapping@heavy-verify-random-ccs.html

  * igt@gem_lmem_swapping@parallel-random-verify-ccs@lmem0:
    - shard-dg1:          NOTRUN -> [SKIP][39] ([i915#4565])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_lmem_swapping@parallel-random-verify-ccs@lmem0.html

  * igt@gem_madvise@dontneed-before-pwrite:
    - shard-dg2:          NOTRUN -> [SKIP][40] ([i915#3282]) +1 other test skip
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_madvise@dontneed-before-pwrite.html

  * igt@gem_mmap@short-mmap:
    - shard-dg2:          NOTRUN -> [SKIP][41] ([i915#4083]) +1 other test skip
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_mmap@short-mmap.html

  * igt@gem_mmap_gtt@cpuset-big-copy-odd:
    - shard-dg1:          NOTRUN -> [SKIP][42] ([i915#4077]) +4 other tests skip
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_mmap_gtt@cpuset-big-copy-odd.html

  * igt@gem_mmap_gtt@cpuset-big-copy-xy:
    - shard-mtlp:         NOTRUN -> [SKIP][43] ([i915#4077])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gem_mmap_gtt@cpuset-big-copy-xy.html

  * igt@gem_mmap_gtt@zero-extend:
    - shard-dg2:          NOTRUN -> [SKIP][44] ([i915#4077]) +7 other tests skip
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_mmap_gtt@zero-extend.html

  * igt@gem_mmap_wc@read:
    - shard-dg1:          NOTRUN -> [SKIP][45] ([i915#4083])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_mmap_wc@read.html

  * igt@gem_partial_pwrite_pread@reads:
    - shard-mtlp:         NOTRUN -> [SKIP][46] ([i915#3282]) +2 other tests skip
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gem_partial_pwrite_pread@reads.html

  * igt@gem_pxp@regular-baseline-src-copy-readible:
    - shard-dg1:          NOTRUN -> [SKIP][47] ([i915#4270])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_pxp@regular-baseline-src-copy-readible.html

  * igt@gem_pxp@reject-modify-context-protection-off-1:
    - shard-dg2:          NOTRUN -> [SKIP][48] ([i915#4270]) +1 other test skip
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_pxp@reject-modify-context-protection-off-1.html

  * igt@gem_set_tiling_vs_blt@tiled-to-untiled:
    - shard-dg2:          NOTRUN -> [SKIP][49] ([i915#4079])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_set_tiling_vs_blt@tiled-to-untiled.html

  * igt@gem_userptr_blits@coherency-sync:
    - shard-dg2:          NOTRUN -> [SKIP][50] ([i915#3297]) +2 other tests skip
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_userptr_blits@coherency-sync.html

  * igt@gem_userptr_blits@map-fixed-invalidate-busy:
    - shard-dg2:          NOTRUN -> [SKIP][51] ([i915#3297] / [i915#4880])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gem_userptr_blits@map-fixed-invalidate-busy.html

  * igt@gem_userptr_blits@vma-merge:
    - shard-dg2:          NOTRUN -> [FAIL][52] ([i915#3318])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_userptr_blits@vma-merge.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-dg2:          NOTRUN -> [FAIL][53] ([fdo#103375]) +1 other test fail
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen7_exec_parse@basic-offset:
    - shard-dg1:          NOTRUN -> [SKIP][54] ([fdo#109289]) +2 other tests skip
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gen7_exec_parse@basic-offset.html

  * igt@gen7_exec_parse@batch-without-end:
    - shard-dg2:          NOTRUN -> [SKIP][55] ([fdo#109289]) +1 other test skip
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@gen7_exec_parse@batch-without-end.html

  * igt@gen9_exec_parse@basic-rejected:
    - shard-mtlp:         NOTRUN -> [SKIP][56] ([i915#2856])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@gen9_exec_parse@basic-rejected.html

  * igt@gen9_exec_parse@bb-start-param:
    - shard-dg2:          NOTRUN -> [SKIP][57] ([i915#2856]) +1 other test skip
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@gen9_exec_parse@bb-start-param.html

  * igt@i915_pm_rc6_residency@rc6-idle@rcs0:
    - shard-dg1:          [PASS][58] -> [FAIL][59] ([i915#3591]) +1 other test fail
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-14/igt@i915_pm_rc6_residency@rc6-idle@rcs0.html
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-19/igt@i915_pm_rc6_residency@rc6-idle@rcs0.html

  * igt@i915_pm_rpm@dpms-non-lpsp:
    - shard-dg1:          [PASS][60] -> [SKIP][61] ([i915#1397])
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-14/igt@i915_pm_rpm@dpms-non-lpsp.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-19/igt@i915_pm_rpm@dpms-non-lpsp.html

  * igt@i915_pm_rpm@modeset-lpsp:
    - shard-dg2:          NOTRUN -> [SKIP][62] ([i915#1397]) +1 other test skip
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@i915_pm_rpm@modeset-lpsp.html

  * igt@i915_pm_rpm@modeset-non-lpsp-stress:
    - shard-dg2:          [PASS][63] -> [SKIP][64] ([i915#1397]) +2 other tests skip
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg2-5/igt@i915_pm_rpm@modeset-non-lpsp-stress.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-10/igt@i915_pm_rpm@modeset-non-lpsp-stress.html
    - shard-rkl:          [PASS][65] -> [SKIP][66] ([i915#1397])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-2/igt@i915_pm_rpm@modeset-non-lpsp-stress.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-7/igt@i915_pm_rpm@modeset-non-lpsp-stress.html

  * igt@i915_pm_rpm@system-suspend-modeset:
    - shard-mtlp:         [PASS][67] -> [ABORT][68] ([i915#9262])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-7/igt@i915_pm_rpm@system-suspend-modeset.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-3/igt@i915_pm_rpm@system-suspend-modeset.html

  * igt@i915_pm_rps@min-max-config-loaded:
    - shard-dg2:          NOTRUN -> [SKIP][69] ([i915#6621])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@i915_pm_rps@min-max-config-loaded.html

  * igt@i915_query@query-topology-coherent-slice-mask:
    - shard-dg2:          NOTRUN -> [SKIP][70] ([i915#6188])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@i915_query@query-topology-coherent-slice-mask.html

  * igt@i915_query@query-topology-unsupported:
    - shard-dg2:          NOTRUN -> [SKIP][71] ([fdo#109302])
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@i915_query@query-topology-unsupported.html

  * igt@i915_query@test-query-geometry-subslices:
    - shard-dg1:          NOTRUN -> [SKIP][72] ([i915#5723])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@i915_query@test-query-geometry-subslices.html

  * igt@kms_addfb_basic@addfb25-x-tiled-mismatch-legacy:
    - shard-dg2:          NOTRUN -> [SKIP][73] ([i915#4212]) +1 other test skip
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_addfb_basic@addfb25-x-tiled-mismatch-legacy.html

  * igt@kms_async_flips@async-flip-with-page-flip-events@pipe-a-hdmi-a-2-y-rc_ccs:
    - shard-rkl:          NOTRUN -> [SKIP][74] ([i915#8502]) +3 other tests skip
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-4/igt@kms_async_flips@async-flip-with-page-flip-events@pipe-a-hdmi-a-2-y-rc_ccs.html

  * igt@kms_async_flips@async-flip-with-page-flip-events@pipe-c-hdmi-a-1-4-rc_ccs-cc:
    - shard-dg2:          NOTRUN -> [SKIP][75] ([i915#8502] / [i915#8709]) +11 other tests skip
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-10/igt@kms_async_flips@async-flip-with-page-flip-events@pipe-c-hdmi-a-1-4-rc_ccs-cc.html

  * igt@kms_async_flips@crc@pipe-a-hdmi-a-3:
    - shard-dg2:          NOTRUN -> [FAIL][76] ([i915#8247]) +3 other tests fail
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-3/igt@kms_async_flips@crc@pipe-a-hdmi-a-3.html

  * igt@kms_async_flips@crc@pipe-d-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [FAIL][77] ([i915#8247]) +3 other tests fail
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-14/igt@kms_async_flips@crc@pipe-d-hdmi-a-4.html

  * igt@kms_big_fb@4-tiled-64bpp-rotate-180:
    - shard-mtlp:         NOTRUN -> [FAIL][78] ([i915#5138])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_big_fb@4-tiled-64bpp-rotate-180.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-dg1:          NOTRUN -> [SKIP][79] ([i915#4538] / [i915#5286])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@x-tiled-16bpp-rotate-90:
    - shard-mtlp:         NOTRUN -> [SKIP][80] ([fdo#111614])
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_big_fb@x-tiled-16bpp-rotate-90.html

  * igt@kms_big_fb@x-tiled-32bpp-rotate-90:
    - shard-dg1:          NOTRUN -> [SKIP][81] ([i915#3638])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_big_fb@x-tiled-32bpp-rotate-90.html

  * igt@kms_big_fb@x-tiled-64bpp-rotate-90:
    - shard-dg2:          NOTRUN -> [SKIP][82] ([fdo#111614])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_big_fb@x-tiled-64bpp-rotate-90.html

  * igt@kms_big_fb@y-tiled-32bpp-rotate-180:
    - shard-dg2:          NOTRUN -> [SKIP][83] ([i915#5190]) +6 other tests skip
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_big_fb@y-tiled-32bpp-rotate-180.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip:
    - shard-mtlp:         NOTRUN -> [SKIP][84] ([fdo#111615]) +4 other tests skip
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip:
    - shard-dg1:          NOTRUN -> [SKIP][85] ([i915#4538])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-dg2:          NOTRUN -> [SKIP][86] ([i915#4538] / [i915#5190]) +2 other tests skip
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_ccs@pipe-a-bad-pixel-format-y_tiled_gen12_mc_ccs:
    - shard-mtlp:         NOTRUN -> [SKIP][87] ([i915#3886] / [i915#6095])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_ccs@pipe-a-bad-pixel-format-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-a-ccs-on-another-bo-y_tiled_ccs:
    - shard-dg2:          NOTRUN -> [SKIP][88] ([i915#3689] / [i915#5354]) +10 other tests skip
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_ccs@pipe-a-ccs-on-another-bo-y_tiled_ccs.html

  * igt@kms_ccs@pipe-a-missing-ccs-buffer-y_tiled_gen12_mc_ccs:
    - shard-dg2:          NOTRUN -> [SKIP][89] ([i915#3689] / [i915#3886] / [i915#5354]) +8 other tests skip
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_ccs@pipe-a-missing-ccs-buffer-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-ccs-on-another-bo-y_tiled_gen12_mc_ccs:
    - shard-dg1:          NOTRUN -> [SKIP][90] ([i915#3689] / [i915#3886] / [i915#5354] / [i915#6095])
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_ccs@pipe-b-ccs-on-another-bo-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-crc-primary-basic-yf_tiled_ccs:
    - shard-dg1:          NOTRUN -> [SKIP][91] ([i915#3689] / [i915#5354] / [i915#6095]) +1 other test skip
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_ccs@pipe-b-crc-primary-basic-yf_tiled_ccs.html

  * igt@kms_ccs@pipe-b-missing-ccs-buffer-y_tiled_ccs:
    - shard-mtlp:         NOTRUN -> [SKIP][92] ([i915#6095]) +3 other tests skip
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_ccs@pipe-b-missing-ccs-buffer-y_tiled_ccs.html

  * igt@kms_ccs@pipe-d-missing-ccs-buffer-4_tiled_mtl_rc_ccs_cc:
    - shard-dg1:          NOTRUN -> [SKIP][93] ([i915#5354] / [i915#6095]) +3 other tests skip
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_ccs@pipe-d-missing-ccs-buffer-4_tiled_mtl_rc_ccs_cc.html

  * igt@kms_cdclk@plane-scaling@pipe-c-hdmi-a-3:
    - shard-dg2:          NOTRUN -> [SKIP][94] ([i915#4087]) +3 other tests skip
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-7/igt@kms_cdclk@plane-scaling@pipe-c-hdmi-a-3.html

  * igt@kms_chamelium_color@ctm-green-to-red:
    - shard-dg2:          NOTRUN -> [SKIP][95] ([fdo#111827]) +1 other test skip
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_chamelium_color@ctm-green-to-red.html

  * igt@kms_chamelium_edid@hdmi-mode-timings:
    - shard-dg2:          NOTRUN -> [SKIP][96] ([i915#7828]) +3 other tests skip
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_chamelium_edid@hdmi-mode-timings.html

  * igt@kms_chamelium_hpd@hdmi-hpd-storm-disable:
    - shard-mtlp:         NOTRUN -> [SKIP][97] ([i915#7828]) +1 other test skip
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_chamelium_hpd@hdmi-hpd-storm-disable.html

  * igt@kms_color@deep-color:
    - shard-rkl:          NOTRUN -> [SKIP][98] ([i915#3555])
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-6/igt@kms_color@deep-color.html

  * igt@kms_content_protection@atomic:
    - shard-dg2:          NOTRUN -> [SKIP][99] ([i915#7118])
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_content_protection@atomic.html

  * igt@kms_cursor_crc@cursor-random-512x170:
    - shard-mtlp:         NOTRUN -> [SKIP][100] ([i915#3359])
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_cursor_crc@cursor-random-512x170.html

  * igt@kms_cursor_crc@cursor-sliding-32x10:
    - shard-dg2:          NOTRUN -> [SKIP][101] ([i915#3555]) +6 other tests skip
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_cursor_crc@cursor-sliding-32x10.html

  * igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic:
    - shard-mtlp:         NOTRUN -> [SKIP][102] ([i915#3546]) +1 other test skip
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_cursor_legacy@2x-nonblocking-modeset-vs-cursor-atomic.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - shard-dg1:          NOTRUN -> [SKIP][103] ([i915#4103] / [i915#4213])
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  * igt@kms_cursor_legacy@cursor-vs-flip-toggle:
    - shard-mtlp:         [PASS][104] -> [FAIL][105] ([i915#8248])
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-1/igt@kms_cursor_legacy@cursor-vs-flip-toggle.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-2/igt@kms_cursor_legacy@cursor-vs-flip-toggle.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-atomic:
    - shard-dg2:          NOTRUN -> [SKIP][106] ([fdo#109274] / [i915#5354]) +1 other test skip
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_cursor_legacy@cursora-vs-flipb-atomic.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-glk:          [PASS][107] -> [FAIL][108] ([i915#2346]) +1 other test fail
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-glk7/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-glk4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_dirtyfb@dirtyfb-ioctl@fbc-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [SKIP][109] ([i915#9227])
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-14/igt@kms_dirtyfb@dirtyfb-ioctl@fbc-hdmi-a-4.html

  * igt@kms_dirtyfb@dirtyfb-ioctl@psr-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [SKIP][110] ([i915#9226] / [i915#9261]) +1 other test skip
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-14/igt@kms_dirtyfb@dirtyfb-ioctl@psr-hdmi-a-4.html

  * igt@kms_flip@2x-nonexisting-fb-interruptible:
    - shard-dg2:          NOTRUN -> [SKIP][111] ([fdo#109274]) +1 other test skip
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_flip@2x-nonexisting-fb-interruptible.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling@pipe-a-valid-mode:
    - shard-dg2:          NOTRUN -> [SKIP][112] ([i915#2672]) +3 other tests skip
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling@pipe-a-valid-mode.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-wc:
    - shard-dg2:          NOTRUN -> [SKIP][113] ([i915#8708]) +8 other tests skip
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-wc:
    - shard-mtlp:         NOTRUN -> [SKIP][114] ([i915#1825])
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-gtt:
    - shard-dg1:          NOTRUN -> [SKIP][115] ([i915#8708])
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-render:
    - shard-dg2:          NOTRUN -> [SKIP][116] ([i915#5354]) +35 other tests skip
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-tiling-4:
    - shard-dg1:          NOTRUN -> [SKIP][117] ([i915#5439])
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_frontbuffer_tracking@fbcpsr-tiling-4.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt:
    - shard-dg1:          NOTRUN -> [SKIP][118] ([fdo#111825]) +6 other tests skip
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary:
    - shard-dg2:          NOTRUN -> [SKIP][119] ([i915#3458]) +8 other tests skip
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary.html

  * igt@kms_frontbuffer_tracking@psr-suspend:
    - shard-dg1:          NOTRUN -> [SKIP][120] ([i915#3458]) +1 other test skip
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_frontbuffer_tracking@psr-suspend.html

  * igt@kms_hdr@bpc-switch-suspend:
    - shard-dg2:          NOTRUN -> [SKIP][121] ([i915#3555] / [i915#8228]) +1 other test skip
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-1/igt@kms_hdr@bpc-switch-suspend.html

  * igt@kms_pipe_crc_basic@suspend-read-crc@pipe-a-dp-1:
    - shard-apl:          [PASS][122] -> [INCOMPLETE][123] ([i915#1982])
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-apl6/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-a-dp-1.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-apl1/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-a-dp-1.html

  * igt@kms_plane@plane-panning-bottom-right-suspend@pipe-a-planes:
    - shard-mtlp:         NOTRUN -> [ABORT][124] ([i915#9262])
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_plane@plane-panning-bottom-right-suspend@pipe-a-planes.html

  * igt@kms_plane@plane-panning-bottom-right-suspend@pipe-b-planes:
    - shard-mtlp:         NOTRUN -> [DMESG-WARN][125] ([i915#9262])
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_plane@plane-panning-bottom-right-suspend@pipe-b-planes.html

  * igt@kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-25@pipe-c-hdmi-a-2:
    - shard-dg2:          NOTRUN -> [SKIP][126] ([i915#5176]) +7 other tests skip
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-2/igt@kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-25@pipe-c-hdmi-a-2.html

  * igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation@pipe-b-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][127] ([i915#5176]) +5 other tests skip
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-6/igt@kms_plane_scaling@plane-scaler-with-clipping-clamping-rotation@pipe-b-hdmi-a-2.html

  * igt@kms_plane_scaling@plane-upscale-with-rotation-factor-0-25@pipe-b-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [SKIP][128] ([i915#5176]) +23 other tests skip
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-18/igt@kms_plane_scaling@plane-upscale-with-rotation-factor-0-25@pipe-b-hdmi-a-4.html

  * igt@kms_plane_scaling@planes-downscale-factor-0-25-unity-scaling@pipe-b-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][129] ([i915#5235]) +3 other tests skip
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_plane_scaling@planes-downscale-factor-0-25-unity-scaling@pipe-b-edp-1.html

  * igt@kms_plane_scaling@planes-downscale-factor-0-25@pipe-c-hdmi-a-4:
    - shard-dg1:          NOTRUN -> [SKIP][130] ([i915#5235]) +7 other tests skip
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_plane_scaling@planes-downscale-factor-0-25@pipe-c-hdmi-a-4.html

  * igt@kms_plane_scaling@planes-downscale-factor-0-75-upscale-20x20@pipe-a-hdmi-a-1:
    - shard-snb:          NOTRUN -> [SKIP][131] ([fdo#109271]) +17 other tests skip
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb1/igt@kms_plane_scaling@planes-downscale-factor-0-75-upscale-20x20@pipe-a-hdmi-a-1.html

  * igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25@pipe-b-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][132] ([i915#5235]) +3 other tests skip
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-4/igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25@pipe-b-hdmi-a-2.html

  * igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25@pipe-c-hdmi-a-1:
    - shard-dg2:          NOTRUN -> [SKIP][133] ([i915#5235]) +15 other tests skip
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-10/igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-25@pipe-c-hdmi-a-1.html

  * igt@kms_psr2_su@page_flip-nv12:
    - shard-dg2:          NOTRUN -> [SKIP][134] ([i915#658]) +3 other tests skip
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_psr2_su@page_flip-nv12.html

  * igt@kms_psr@dpms:
    - shard-dg2:          NOTRUN -> [SKIP][135] ([i915#1072]) +5 other tests skip
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_psr@dpms.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-dg1:          NOTRUN -> [SKIP][136] ([i915#1072])
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@kms_psr@psr2_sprite_plane_move.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-dg2:          NOTRUN -> [SKIP][137] ([i915#5461] / [i915#658])
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_rotation_crc@primary-rotation-270:
    - shard-dg2:          NOTRUN -> [SKIP][138] ([i915#4235])
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_rotation_crc@primary-rotation-270.html

  * igt@kms_rotation_crc@primary-y-tiled-reflect-x-90:
    - shard-rkl:          [PASS][139] -> [INCOMPLETE][140] ([i915#8875])
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-4/igt@kms_rotation_crc@primary-y-tiled-reflect-x-90.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-4/igt@kms_rotation_crc@primary-y-tiled-reflect-x-90.html

  * igt@kms_selftest@drm_format_helper:
    - shard-dg2:          NOTRUN -> [SKIP][141] ([i915#8661]) +2 other tests skip
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@kms_selftest@drm_format_helper.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-a:
    - shard-apl:          [PASS][142] -> [FAIL][143] ([i915#9196])
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-apl4/igt@kms_universal_plane@cursor-fb-leak-pipe-a.html
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-apl6/igt@kms_universal_plane@cursor-fb-leak-pipe-a.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-b:
    - shard-snb:          [PASS][144] -> [FAIL][145] ([i915#9196])
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-snb2/igt@kms_universal_plane@cursor-fb-leak-pipe-b.html
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb6/igt@kms_universal_plane@cursor-fb-leak-pipe-b.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-c:
    - shard-tglu:         [PASS][146] -> [FAIL][147] ([i915#9196])
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-tglu-2/igt@kms_universal_plane@cursor-fb-leak-pipe-c.html
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-tglu-5/igt@kms_universal_plane@cursor-fb-leak-pipe-c.html

  * igt@kms_vrr@flip-suspend:
    - shard-mtlp:         NOTRUN -> [SKIP][148] ([i915#3555] / [i915#8808])
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@kms_vrr@flip-suspend.html

  * igt@kms_writeback@writeback-check-output:
    - shard-dg2:          NOTRUN -> [SKIP][149] ([i915#2437]) +1 other test skip
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@kms_writeback@writeback-check-output.html

  * igt@perf@gen8-unprivileged-single-ctx-counters:
    - shard-dg2:          NOTRUN -> [SKIP][150] ([i915#2436])
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@perf@gen8-unprivileged-single-ctx-counters.html

  * igt@perf@mi-rpc:
    - shard-dg2:          NOTRUN -> [SKIP][151] ([i915#2434])
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@perf@mi-rpc.html

  * igt@perf@non-zero-reason@0-rcs0:
    - shard-dg2:          NOTRUN -> [FAIL][152] ([i915#7484])
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@perf@non-zero-reason@0-rcs0.html

  * igt@prime_udl:
    - shard-dg2:          NOTRUN -> [SKIP][153] ([fdo#109291])
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@prime_udl.html

  * igt@prime_vgem@basic-write:
    - shard-dg2:          NOTRUN -> [SKIP][154] ([i915#3291] / [i915#3708])
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@prime_vgem@basic-write.html

  * igt@prime_vgem@fence-flip-hang:
    - shard-dg2:          NOTRUN -> [SKIP][155] ([i915#3708])
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-11/igt@prime_vgem@fence-flip-hang.html

  * igt@runner@aborted:
    - shard-snb:          NOTRUN -> [FAIL][156] ([i915#7812] / [i915#8848])
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb7/igt@runner@aborted.html
    - shard-mtlp:         NOTRUN -> [FAIL][157] ([i915#7812])
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-1/igt@runner@aborted.html

  * igt@v3d/v3d_submit_cl@bad-multisync-out-sync:
    - shard-mtlp:         NOTRUN -> [SKIP][158] ([i915#2575]) +2 other tests skip
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-7/igt@v3d/v3d_submit_cl@bad-multisync-out-sync.html

  * igt@v3d/v3d_submit_cl@bad-perfmon:
    - shard-dg1:          NOTRUN -> [SKIP][159] ([i915#2575]) +1 other test skip
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@v3d/v3d_submit_cl@bad-perfmon.html

  * igt@v3d/v3d_submit_cl@simple-flush-cache:
    - shard-dg2:          NOTRUN -> [SKIP][160] ([i915#2575]) +7 other tests skip
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@v3d/v3d_submit_cl@simple-flush-cache.html

  * igt@vc4/vc4_create_bo@create-bo-4096:
    - shard-dg2:          NOTRUN -> [SKIP][161] ([i915#7711]) +5 other tests skip
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-5/igt@vc4/vc4_create_bo@create-bo-4096.html

  * igt@vc4/vc4_label_bo@set-bad-name:
    - shard-dg1:          NOTRUN -> [SKIP][162] ([i915#7711]) +1 other test skip
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@vc4/vc4_label_bo@set-bad-name.html

  
#### Possible fixes ####

  * igt@gem_ccs@suspend-resume@tile4-compressed-compfmt0-smem-lmem0:
    - shard-dg2:          [INCOMPLETE][163] ([i915#7297]) -> [PASS][164]
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg2-1/igt@gem_ccs@suspend-resume@tile4-compressed-compfmt0-smem-lmem0.html
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-6/igt@gem_ccs@suspend-resume@tile4-compressed-compfmt0-smem-lmem0.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-rkl:          [FAIL][165] ([i915#2846]) -> [PASS][166]
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-4/igt@gem_exec_fair@basic-deadline.html
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-7/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-flow@rcs0:
    - shard-rkl:          [FAIL][167] ([i915#2842]) -> [PASS][168] +1 other test pass
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-4/igt@gem_exec_fair@basic-flow@rcs0.html
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-6/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-pace-share@rcs0:
    - shard-glk:          [FAIL][169] ([i915#2842]) -> [PASS][170]
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-glk2/igt@gem_exec_fair@basic-pace-share@rcs0.html
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-glk1/igt@gem_exec_fair@basic-pace-share@rcs0.html

  * igt@gem_exec_schedule@preempt-hang@vcs0:
    - shard-mtlp:         [ABORT][171] ([i915#9262]) -> [PASS][172] +2 other tests pass
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-1/igt@gem_exec_schedule@preempt-hang@vcs0.html
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-2/igt@gem_exec_schedule@preempt-hang@vcs0.html

  * igt@gem_exec_suspend@basic-s4-devices@lmem0:
    - shard-dg1:          [ABORT][173] ([i915#7975] / [i915#8213]) -> [PASS][174]
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-14/igt@gem_exec_suspend@basic-s4-devices@lmem0.html
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-17/igt@gem_exec_suspend@basic-s4-devices@lmem0.html

  * igt@i915_pm_rc6_residency@rc6-idle@vecs0:
    - shard-dg1:          [FAIL][175] ([i915#3591]) -> [PASS][176]
   [175]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-14/igt@i915_pm_rc6_residency@rc6-idle@vecs0.html
   [176]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-19/igt@i915_pm_rc6_residency@rc6-idle@vecs0.html

  * igt@i915_pm_rpm@dpms-lpsp:
    - shard-dg1:          [SKIP][177] ([i915#1397]) -> [PASS][178] +3 other tests pass
   [177]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-15/igt@i915_pm_rpm@dpms-lpsp.html
   [178]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-19/igt@i915_pm_rpm@dpms-lpsp.html

  * igt@i915_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - shard-rkl:          [SKIP][179] ([i915#1397]) -> [PASS][180]
   [179]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-7/igt@i915_pm_rpm@modeset-non-lpsp-stress-no-wait.html
   [180]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-4/igt@i915_pm_rpm@modeset-non-lpsp-stress-no-wait.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip:
    - shard-tglu:         [FAIL][181] ([i915#3743]) -> [PASS][182]
   [181]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-tglu-10/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html
   [182]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-tglu-3/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-apl:          [FAIL][183] ([i915#2346]) -> [PASS][184] +1 other test pass
   [183]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-apl6/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [184]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-apl2/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-tglu:         [FAIL][185] ([i915#4767]) -> [PASS][186]
   [185]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-tglu-2/igt@kms_fbcon_fbt@fbc-suspend.html
   [186]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-tglu-5/igt@kms_fbcon_fbt@fbc-suspend.html

  * {igt@kms_pm_dc@dc9-dpms}:
    - shard-tglu:         [SKIP][187] ([i915#4281]) -> [PASS][188]
   [187]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-tglu-5/igt@kms_pm_dc@dc9-dpms.html
   [188]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-tglu-4/igt@kms_pm_dc@dc9-dpms.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-a:
    - shard-snb:          [FAIL][189] ([i915#9196]) -> [PASS][190]
   [189]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-snb2/igt@kms_universal_plane@cursor-fb-leak-pipe-a.html
   [190]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb6/igt@kms_universal_plane@cursor-fb-leak-pipe-a.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-b:
    - shard-tglu:         [FAIL][191] ([i915#9196]) -> [PASS][192]
   [191]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-tglu-9/igt@kms_universal_plane@cursor-fb-leak-pipe-b.html
   [192]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-tglu-9/igt@kms_universal_plane@cursor-fb-leak-pipe-b.html

  * igt@kms_universal_plane@cursor-fb-leak-pipe-d:
    - shard-mtlp:         [FAIL][193] ([i915#9196]) -> [PASS][194]
   [193]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-5/igt@kms_universal_plane@cursor-fb-leak-pipe-d.html
   [194]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-1/igt@kms_universal_plane@cursor-fb-leak-pipe-d.html

  * igt@prime_mmap_coherency@ioctl-errors:
    - shard-mtlp:         [FAIL][195] ([i915#9334]) -> [PASS][196]
   [195]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-5/igt@prime_mmap_coherency@ioctl-errors.html
   [196]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-1/igt@prime_mmap_coherency@ioctl-errors.html

  
#### Warnings ####

  * igt@gem_exec_schedule@preempt-hang@vecs0:
    - shard-mtlp:         [DMESG-WARN][197] ([i915#9262]) -> [ABORT][198] ([i915#9262])
   [197]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-mtlp-1/igt@gem_exec_schedule@preempt-hang@vecs0.html
   [198]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-mtlp-2/igt@gem_exec_schedule@preempt-hang@vecs0.html

  * igt@i915_suspend@basic-s3-without-i915:
    - shard-snb:          [DMESG-FAIL][199] ([fdo#103375]) -> [DMESG-WARN][200] ([i915#8841])
   [199]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-snb7/igt@i915_suspend@basic-s3-without-i915.html
   [200]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-snb5/igt@i915_suspend@basic-s3-without-i915.html

  * igt@kms_content_protection@type1:
    - shard-dg2:          [SKIP][201] ([i915#7118] / [i915#7162]) -> [SKIP][202] ([i915#7118])
   [201]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg2-11/igt@kms_content_protection@type1.html
   [202]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg2-3/igt@kms_content_protection@type1.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-rkl:          [SKIP][203] ([i915#3955]) -> [SKIP][204] ([fdo#110189] / [i915#3955])
   [203]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-6/igt@kms_fbcon_fbt@psr-suspend.html
   [204]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-1/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_force_connector_basic@force-load-detect:
    - shard-rkl:          [SKIP][205] ([fdo#109285]) -> [SKIP][206] ([fdo#109285] / [i915#4098])
   [205]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-rkl-6/igt@kms_force_connector_basic@force-load-detect.html
   [206]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-rkl-1/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_psr@primary_page_flip:
    - shard-dg1:          [SKIP][207] ([i915#1072] / [i915#4078]) -> [SKIP][208] ([i915#1072])
   [207]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13635/shard-dg1-12/igt@kms_psr@primary_page_flip.html
   [208]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/shard-dg1-15/igt@kms_psr@primary_page_flip.html

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

  [fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109291]: https://bugs.freedesktop.org/show_bug.cgi?id=109291
  [fdo#109302]: https://bugs.freedesktop.org/show_bug.cgi?id=109302
  [fdo#110189]: https://bugs.freedesktop.org/show_bug.cgi?id=110189
  [fdo#111614]: https://bugs.freedesktop.org/show_bug.cgi?id=111614
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [fdo#112283]: https://bugs.freedesktop.org/show_bug.cgi?id=112283
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1397]: https://gitlab.freedesktop.org/drm/intel/issues/1397
  [i915#1825]: https://gitlab.freedesktop.org/drm/intel/issues/1825
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2434]: https://gitlab.freedesktop.org/drm/intel/issues/2434
  [i915#2436]: https://gitlab.freedesktop.org/drm/intel/issues/2436
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2846]: https://gitlab.freedesktop.org/drm/intel/issues/2846
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#3281]: https://gitlab.freedesktop.org/drm/intel/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/intel/issues/3297
  [i915#3318]: https://gitlab.freedesktop.org/drm/intel/issues/3318
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3458]: https://gitlab.freedesktop.org/drm/intel/issues/3458
  [i915#3539]: https://gitlab.freedesktop.org/drm/intel/issues/3539
  [i915#3546]: https://gitlab.freedesktop.org/drm/intel/issues/3546
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3591]: https://gitlab.freedesktop.org/drm/intel/issues/3591
  [i915#3638]: https://gitlab.freedesktop.org/drm/intel/issues/3638
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3743]: https://gitlab.freedesktop.org/drm/intel/issues/3743
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#3955]: https://gitlab.freedesktop.org/drm/intel/issues/3955
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4078]: https://gitlab.freedesktop.org/drm/intel/issues/4078
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4087]: https://gitlab.freedesktop.org/drm/intel/issues/4087
  [i915#4098]: https://gitlab.freedesktop.org/drm/intel/issues/4098
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#4235]: https://gitlab.freedesktop.org/drm/intel/issues/4235
  [i915#4270]: https://gitlab.freedesktop.org/drm/intel/issues/4270
  [i915#4281]: https://gitlab.freedesktop.org/drm/intel/issues/4281
  [i915#4538]: https://gitlab.freedesktop.org/drm/intel/issues/4538
  [i915#4565]: https://gitlab.freedesktop.org/drm/intel/issues/4565
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4767]: https://gitlab.freedesktop.org/drm/intel/issues/4767
  [i915#4771]: https://gitlab.freedesktop.org/drm/intel/issues/4771
  [i915#4812]: https://gitlab.freedesktop.org/drm/intel/issues/4812
  [i915#4852]: https://gitlab.freedesktop.org/drm/intel/issues/4852
  [i915#4860]: https://gitlab.freedesktop.org/drm/intel/issues/4860
  [i915#4880]: https://gitlab.freedesktop.org/drm/intel/issues/4880
  [i915#5138]: https://gitlab.freedesktop.org/drm/intel/issues/5138
  [i915#5176]: https://gitlab.freedesktop.org/drm/intel/issues/5176
  [i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
  [i915#5235]: https://gitlab.freedesktop.org/drm/intel/issues/5235
  [i915#5286]: https://gitlab.freedesktop.org/drm/intel/issues/5286
  [i915#5354]: https://gitlab.freedesktop.org/drm/intel/issues/5354
  [i915#5439]: https://gitlab.freedesktop.org/drm/intel/issues/5439
  [i915#5461]: https://gitlab.freedesktop.org/drm/intel/issues/5461
  [i915#5723]: https://gitlab.freedesktop.org/drm/intel/issues/5723
  [i915#6095]: https://gitlab.freedesktop.org/drm/intel/issues/6095
  [i915#6188]: https://gitlab.freedesktop.org/drm/intel/issues/6188
  [i915#6268]: https://gitlab.freedesktop.org/drm/intel/issues/6268
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#6621]: https://gitlab.freedesktop.org/drm/intel/issues/6621
  [i915#7118]: https://gitlab.freedesktop.org/drm/intel/issues/7118
  [i915#7162]: https://gitlab.freedesktop.org/drm/intel/issues/7162
  [i915#7297]: https://gitlab.freedesktop.org/drm/intel/issues/7297
  [i915#7484]: https://gitlab.freedesktop.org/drm/intel/issues/7484
  [i915#7701]: https://gitlab.freedesktop.org/drm/intel/issues/7701
  [i915#7711]: https://gitlab.freedesktop.org/drm/intel/issues/7711
  [i915#7742]: https://gitlab.freedesktop.org/drm/intel/issues/7742
  [i915#7812]: https://gitlab.freedesktop.org/drm/intel/issues/7812
  [i915#7828]: https://gitlab.freedesktop.org/drm/intel/issues/7828
  [i915#7892]: https://gitlab.freedesktop.org/drm/intel/issues/7892
  [i915#7975]: https://gitlab.freedesktop.org/drm/intel/issues/7975
  [i915#8104]: https://gitlab.freedesktop.org/drm/intel/issues/8104
  [i915#8213]: https://gitlab.freedesktop.org/drm/intel/issues/8213
  [i915#8228]: https://gitlab.freedesktop.org/drm/intel/issues/8228
  [i915#8247]: https://gitlab.freedesktop.org/drm/intel/issues/8247
  [i915#8248]: https://gitlab.freedesktop.org/drm/intel/issues/8248
  [i915#8411]: https://gitlab.freedesktop.org/drm/intel/issues/8411
  [i915#8414]: https://gitlab.freedesktop.org/drm/intel/issues/8414
  [i915#8502]: https://gitlab.freedesktop.org/drm/intel/issues/8502
  [i915#8555]: https://gitlab.freedesktop.org/drm/intel/issues/8555
  [i915#8661]: https://gitlab.freedesktop.org/drm/intel/issues/8661
  [i915#8708]: https://gitlab.freedesktop.org/drm/intel/issues/8708
  [i915#8709]: https://gitlab.freedesktop.org/drm/intel/issues/8709
  [i915#8808]: https://gitlab.freedesktop.org/drm/intel/issues/8808
  [i915#8841]: https://gitlab.freedesktop.org/drm/intel/issues/8841
  [i915#8848]: https://gitlab.freedesktop.org/drm/intel/issues/8848
  [i915#8875]: https://gitlab.freedesktop.org/drm/intel/issues/8875
  [i915#8962]: https://gitlab.freedesktop.org/drm/intel/issues/8962
  [i915#9067]: https://gitlab.freedesktop.org/drm/intel/issues/9067
  [i915#9121]: https://gitlab.freedesktop.org/drm/intel/issues/9121
  [i915#9196]: https://gitlab.freedesktop.org/drm/intel/issues/9196
  [i915#9226]: https://gitlab.freedesktop.org/drm/intel/issues/9226
  [i915#9227]: https://gitlab.freedesktop.org/drm/intel/issues/9227
  [i915#9261]: https://gitlab.freedesktop.org/drm/intel/issues/9261
  [i915#9262]: https://gitlab.freedesktop.org/drm/intel/issues/9262
  [i915#9334]: https://gitlab.freedesktop.org/drm/intel/issues/9334


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

  * Linux: CI_DRM_13635 -> Patchwork_122589v5

  CI-20190529: 20190529
  CI_DRM_13635: c6b7f865a77a75af03c3b68baa4cf7eb66c1c6d5 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_7488: 099e058c5dfb7a49942edf03cae88a52a77077a3 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_122589v5: c6b7f865a77a75af03c3b68baa4cf7eb66c1c6d5 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v5/index.html

[-- Attachment #2: Type: text/html, Size: 67111 bytes --]

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

* Re: [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes Imre Deak
@ 2023-09-15 18:34   ` Ville Syrjälä
  2023-09-15 20:03     ` Imre Deak
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
  1 sibling, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-15 18:34 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:40PM +0300, Imre Deak wrote:
> Add intel_modeset_pipes_in_mask_early() to modeset a provided set of
> pipes, used in a follow-up patch.
> 
> While at it add _late suffix to intel_modeset_all_pipes() for clarity
> and add DocBook descriptions for the two exported functions.
> 
> v2:
> - Add a flag controlling if active planes are force updated as well.
> - Add DockBook descriptions.
> v3:
> - For clarity use _early/_late suffixes for the exported functions
>   instead of the update_active_planes parameter. (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_cdclk.c   |  2 +-
>  drivers/gpu/drm/i915/display/intel_display.c | 45 ++++++++++++++++++--
>  drivers/gpu/drm/i915/display/intel_display.h |  6 ++-
>  drivers/gpu/drm/i915/display/skl_watermark.c |  2 +-
>  4 files changed, 47 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index ad5251ba6fe13..a2e20b25d6361 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -3139,7 +3139,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
>  	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
>  					     &new_cdclk_state->actual)) {
>  		/* All pipes must be switched off while we change the cdclk. */
> -		ret = intel_modeset_all_pipes(state, "CDCLK change");
> +		ret = intel_modeset_all_pipes_late(state, "CDCLK change");
>  		if (ret)
>  			return ret;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 6bbc9069754c4..27e6ea21e0a91 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5407,8 +5407,9 @@ intel_verify_planes(struct intel_atomic_state *state)
>  			     plane_state->uapi.visible);
>  }
>  
> -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> -			    const char *reason)
> +static int intel_modeset_pipes_in_mask(struct intel_atomic_state *state,
> +				       const char *reason, u8 mask,
> +				       bool update_active_planes)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
> @@ -5417,7 +5418,7 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  	 * Add all pipes to the state, and force
>  	 * a modeset on all the active ones.
>  	 */
> -	for_each_intel_crtc(&dev_priv->drm, crtc) {
> +	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, mask) {
>  		struct intel_crtc_state *crtc_state;
>  		int ret;
>  
> @@ -5448,7 +5449,9 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  		if (ret)
>  			return ret;
>  
> -		crtc_state->update_planes |= crtc_state->active_planes;
> +		if (update_active_planes)
> +			crtc_state->update_planes |= crtc_state->active_planes;

This thing still confuses me. We have a bunch of other "late modeset"
stuff in there (async flip handling and clearing of fastset flag at
least). I still think a clean split would be better than a confusing
parameter.

> +
>  		crtc_state->async_flip_planes = 0;
>  		crtc_state->do_async_flip = false;
>  	}
> @@ -5456,6 +5459,40 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  	return 0;
>  }
>  
> +/**
> + * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
> + * @state: intel atomic state
> + * @reason: the reason for the full modeset
> + * @mask: mask of pipes to modeset
> + *
> + * Force a full modeset on pipes in @mask due to the description in @reason.
> + * This function can be called only before new plane states are computed.
> + *
> + * Returns 0 in case of success, negative error code otherwise.
> + */
> +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> +				      const char *reason, u8 mask)
> +{
> +	return intel_modeset_pipes_in_mask(state, reason, mask, false);
> +}
> +
> +/**
> + * intel_modeset_all_pipes_late - force a full modeset on all pipes
> + * @state: intel atomic state
> + * @reason: the reason for the full modeset
> + *
> + * Force a full modeset on all pipes due to the description in @reason.
> + * This function can be called only after new plane states are computed
> + * already.
> + *
> + * Returns 0 in case of success, negative error code otherwise.
> + */
> +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> +				 const char *reason)
> +{
> +	return intel_modeset_pipes_in_mask(state, reason, -1, true);
> +}
> +
>  /*
>   * This implements the workaround described in the "notes" section of the mode
>   * set sequence documentation. When going from no pipes or single pipe to
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 49ac8473b988b..64a5be7859331 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -513,8 +513,10 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
>  void intel_update_watermarks(struct drm_i915_private *i915);
>  
>  /* modesetting */
> -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> -			    const char *reason);
> +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> +				      const char *reason, u8 pipe_mask);
> +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> +				 const char *reason);
>  void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
>  					  struct intel_power_domain_mask *old_domains);
>  void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
> diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
> index 063929a42a42f..a29d9b717deed 100644
> --- a/drivers/gpu/drm/i915/display/skl_watermark.c
> +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
> @@ -2616,7 +2616,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
>  
>  		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
>  			/* TODO: Implement vblank synchronized MBUS joining changes */
> -			ret = intel_modeset_all_pipes(state, "MBUS joining change");
> +			ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
>  			if (ret)
>  				return ret;
>  		}
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v4 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-15  0:33   ` [Intel-gfx] [PATCH v4 " Imre Deak
@ 2023-09-15 19:11     ` Ville Syrjälä
  2023-09-15 21:01       ` Imre Deak
  2023-09-18 18:25     ` [Intel-gfx] [PATCH v5 " Imre Deak
  1 sibling, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-15 19:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Sep 15, 2023 at 03:33:54AM +0300, Imre Deak wrote:
> At the moment a modeset fails if the config computation of a pipe can't
> fit its required BW to the available link BW even though the limitation
> may be resolved by reducing the BW requirement of other pipes.
> 
> To improve the above this patch adds helper functions checking the
> overall BW limits after all CRTC states have been computed. If the check
> fails the maximum link bpp for a selected pipe will be reduced and all
> the CRTC states will be recomputed until either the overall BW limit
> check passes, or further bpp reduction is not possible (because all
> pipes/encoders sharing the link BW reached their minimum link bpp).
> 
> This change prepares for upcoming patches enabling the above BW
> management on FDI and MST links.
> 
> v2:
> - Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
>   intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
> v3:
> - Add the helper functions in a separate patch. (Ville)
> - Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
> - Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
>   limit failure.
> v4:
> - Make intel_atomic_check_config() static.
> 
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |  61 ++++-
>  .../drm/i915/display/intel_display_types.h    |   3 +-
>  drivers/gpu/drm/i915/display/intel_link_bw.c  | 226 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
>  6 files changed, 325 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 1b2e02e9d92cb..de4967c141f00 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -268,6 +268,7 @@ i915-y += \
>  	display/intel_hotplug.o \
>  	display/intel_hotplug_irq.o \
>  	display/intel_hti.o \
> +	display/intel_link_bw.o \
>  	display/intel_load_detect.o \
>  	display/intel_lpe_audio.o \
>  	display/intel_modeset_lock.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> index 182c6dd64f47c..1eda6a9f19aa8 100644
> --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
>  	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
>  	crtc_state->scaler_state.scaler_id = -1;
>  	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> +	crtc_state->max_link_bpp_x16 = INT_MAX;

Are we sure we won't end up doing random arithmetic with that which could
overflow?

>  }
>  
>  static struct intel_crtc *intel_crtc_alloc(void)
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index fe3b6844e063d..0f30723a68cc0 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -87,6 +87,7 @@
>  #include "intel_frontbuffer.h"
>  #include "intel_hdmi.h"
>  #include "intel_hotplug.h"
> +#include "intel_link_bw.h"
>  #include "intel_lvds.h"
>  #include "intel_lvds_regs.h"
>  #include "intel_modeset_setup.h"
> @@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
>  
>  static int
>  intel_modeset_pipe_config(struct intel_atomic_state *state,
> -			  struct intel_crtc *crtc)
> +			  struct intel_crtc *crtc,
> +			  const struct intel_link_bw_limits *limits)
>  {
>  	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
>  	struct intel_crtc_state *crtc_state =
> @@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> +	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
> +
> +	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
> +		drm_dbg_kms(&i915->drm,
> +			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> +			    crtc->base.base.id, crtc->base.name,
> +			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> +	}
> +
>  	base_bpp = crtc_state->pipe_bpp;
>  
>  	/*
> @@ -6195,7 +6206,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
>  	return 0;
>  }
>  
> -static int intel_atomic_check_config(struct intel_atomic_state *state)
> +static int intel_atomic_check_config(struct intel_atomic_state *state,
> +				     struct intel_link_bw_limits *limits,
> +				     enum pipe *failed_pipe)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct intel_crtc_state *new_crtc_state;
> @@ -6203,6 +6216,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  	int ret;
>  	int i;
>  
> +	*failed_pipe = INVALID_PIPE;
> +
>  	ret = intel_bigjoiner_add_affected_crtcs(state);
>  	if (ret)
>  		return ret;
> @@ -6228,7 +6243,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  		if (!new_crtc_state->hw.enable)
>  			continue;
>  
> -		ret = intel_modeset_pipe_config(state, crtc);
> +		ret = intel_modeset_pipe_config(state, crtc, limits);
>  		if (ret)
>  			break;
>  
> @@ -6237,9 +6252,47 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  			break;
>  	}
>  
> +	if (ret)
> +		*failed_pipe = crtc->pipe;
> +
>  	return ret;
>  }
>  
> +static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_link_bw_limits new_limits;
> +	struct intel_link_bw_limits old_limits;
> +	int ret;
> +
> +	intel_link_bw_init_limits(i915, &new_limits);
> +	old_limits = new_limits;
> +
> +	while (true) {
> +		enum pipe failed_pipe;
> +
> +		ret = intel_atomic_check_config(state, &new_limits,
> +						&failed_pipe);
> +		if (ret) {
> +			if (ret == -EINVAL &&
> +			    intel_link_bw_reset_pipe_limit_to_min(state,
> +								  &old_limits,
> +								  &new_limits,
> +								  failed_pipe))
> +				continue;
> +
> +			break;
> +		}
> +
> +		old_limits = new_limits;
> +
> +		ret = intel_link_bw_atomic_check(state, &new_limits);
> +		if (ret != -EAGAIN)
> +			break;
> +	}
> +
> +	return ret;
> +}
>  /**
>   * intel_atomic_check - validate state object
>   * @dev: drm device
> @@ -6284,7 +6337,7 @@ int intel_atomic_check(struct drm_device *dev,
>  			return ret;
>  	}
>  
> -	ret = intel_atomic_check_config(state);
> +	ret = intel_atomic_check_config_and_link(state);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 966163ccbd7a3..514977ebc17b0 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1189,7 +1189,8 @@ struct intel_crtc_state {
>  		u32 ctrl, div;
>  	} dsi_pll;
>  
> -	int pipe_bpp;
> +	int max_link_bpp_x16;	/* in 1/16 bpp units */
> +	int pipe_bpp;		/* in 1 bpp units */
>  	struct intel_link_m_n dp_m_n;
>  
>  	/* m2_n2 for eDP downclock */
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> new file mode 100644
> index 0000000000000..22494772b9d59
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> @@ -0,0 +1,226 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +
> +#include "intel_atomic.h"
> +#include "intel_display_types.h"
> +#include "intel_dp_mst.h"
> +#include "intel_fdi.h"
> +#include "intel_link_bw.h"
> +
> +/**
> + * intel_link_bw_init_limits - initialize BW limits
> + * @i915: device instance
> + * @limits: link BW limits
> + *
> + * Initialize @limits.
> + */
> +void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
> +{
> +	enum pipe pipe;
> +
> +	limits->min_bpp_pipes = 0;
> +	for_each_pipe(i915, pipe)
> +		limits->max_bpp_x16[pipe] = INT_MAX;
> +}
> +
> +/**
> + * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
> + * @crtc_state: the crtc state
> + *
> + * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
> + * call this function during state computation in the simple case where the
> + * link bpp will always match the pipe bpp. This is the case for all non-DP
> + * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
> + * of DSC compression.
> + *
> + * Returns %true in case of success, %false if pipe bpp would need to be
> + * reduced below its valid range.
> + */
> +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
> +{
> +	int pipe_bpp = min(crtc_state->pipe_bpp,
> +			   to_bpp_int(crtc_state->max_link_bpp_x16));
> +
> +	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
> +
> +	if (pipe_bpp < 6 * 3)
> +		return false;
> +
> +	crtc_state->pipe_bpp = pipe_bpp;
> +
> +	return true;
> +}
> +
> +/**
> + * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
> + * @state: atomic state
> + * @limits: link BW limits
> + * @pipe_mask: mask of pipes to select from
> + * @reason: explanation of why bpp reduction is needed
> + *
> + * Select the pipe from @pipe_mask with the biggest link bpp value and set the
> + * maximum of link bpp in @limits below this value. Modeset the selected pipe,
> + * so that its state will get recomputed.
> + *
> + * This function can be called to resolve a link's BW overallocation by reducing
> + * the link bpp of one pipe on the link and hence reducing the total link BW.
> + *
> + * Returns
> + *   - 0 in case of success
> + *   - %-ENOSPC if no pipe can further reduce its link bpp
> + *   - Other negative error, if modesetting the selected pipe failed
> + */
> +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> +			     struct intel_link_bw_limits *limits,
> +			     u8 pipe_mask,
> +			     const char *reason)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	enum pipe max_bpp_pipe = INVALID_PIPE;
> +	struct intel_crtc *crtc;
> +	int max_bpp = 0;
> +
> +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
> +		struct intel_crtc_state *crtc_state;
> +		int pipe_bpp;
> +
> +		if (limits->min_bpp_pipes & BIT(crtc->pipe))
> +			continue;
> +
> +		crtc_state = intel_atomic_get_crtc_state(&state->base,
> +							 crtc);
> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +
> +		if (crtc_state->dsc.compression_enable)
> +			pipe_bpp = crtc_state->dsc.compressed_bpp;
> +		else
> +			pipe_bpp = crtc_state->pipe_bpp;

That sounds like it should be 'link_bpp'.

Hmm. How does this work with 4:2:0 output?

> +
> +		if (pipe_bpp > max_bpp) {
> +			max_bpp = pipe_bpp;
> +			max_bpp_pipe = crtc->pipe;
> +		}
> +	}
> +
> +	if (max_bpp_pipe == INVALID_PIPE)
> +		return -ENOSPC;
> +
> +	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
> +
> +	return intel_modeset_pipes_in_mask_early(state, reason,
> +						 BIT(max_bpp_pipe));

So we always reduce just for one pipe at a time. I suppose that does
lead to the most optimal bandwidth usage, albeit with perhaps a
slighly slower convergence.

> +}
> +
> +/**
> + * intel_link_bw_reset_pipe_limit_to_min - reset BW limit for a pipe to its minimum
> + * @state: atomic state
> + * @old_limits: link BW limits
> + * @new_limits: link BW limits
> + * @pipe: pipe
> + *
> + * Reset the link bpp limit for @pipe in @new_limits to its value in
> + * @old_limits and mark this limit as the minimum. This function must be
> + * called after a pipe's compute config function failed, @old_limits
> + * containing the bpp limit with which compute config previously passed.
> + *
> + * The function will fail if setting a minimum is not possible, either
> + * because the old and new limits match (and so would lead to a pipe compute
> + * config failure) or the limit is already at the minimum.
> + *
> + * Returns %true in case of success.
> + */
> +bool
> +intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> +				       const struct intel_link_bw_limits *old_limits,
> +				       struct intel_link_bw_limits *new_limits,
> +				       enum pipe pipe)
> +{
> +	if (pipe == INVALID_PIPE)
> +		return false;
> +
> +	if (new_limits->min_bpp_pipes & BIT(pipe))
> +		return false;
> +
> +	if (new_limits->max_bpp_x16[pipe] ==
> +	    old_limits->max_bpp_x16[pipe])
> +		return false;
> +
> +	new_limits->max_bpp_x16[pipe] =
> +		old_limits->max_bpp_x16[pipe];
> +	new_limits->min_bpp_pipes |= BIT(pipe);

So that bitmask is keeping track of pipes which have reached what
they consider to be an absolute minimum usable bpp?

The naming confused me a bit, of both the bitmask and the function.
Maybe something like 'min_bpp_reached_pipes' would be a bit more
clear, and intel_link_bw_min_bpp_reached() or something for the
function name? Still doesn't really work when just reading the
code though...

> +
> +	return true;
> +}
> +
> +static int check_all_link_config(struct intel_atomic_state *state,
> +				 struct intel_link_bw_limits *limits)
> +{
> +	/* TODO: Check all shared display link configurations like FDI */
> +	return 0;
> +}
> +
> +static bool
> +assert_link_limit_change_valid(struct drm_i915_private *i915,
> +			       const struct intel_link_bw_limits *old_limits,
> +			       const struct intel_link_bw_limits *new_limits)
> +{
> +	bool bpps_changed = false;
> +	enum pipe pipe;
> +
> +	for_each_pipe(i915, pipe) {
> +		/* The bpp limit can only decrease. */
> +		if (drm_WARN_ON(&i915->drm,
> +				new_limits->max_bpp_x16[pipe] >
> +				old_limits->max_bpp_x16[pipe]))
> +			return false;
> +
> +		if (new_limits->max_bpp_x16[pipe] <
> +		    old_limits->max_bpp_x16[pipe])
> +			bpps_changed = true;
> +	}
> +
> +	/* At least one limit must change. */
> +	if (drm_WARN_ON(&i915->drm,
> +			!bpps_changed))
> +		return false;
> +
> +	return true;
> +}
> +
> +/**
> + * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
> + * @state: atomic state
> + * @new_limits: link BW limits
> + *
> + * Check the configuration of all shared display links in @state and set new BW
> + * limits in @new_limits if there is a BW limitation.
> + *
> + * Returns:
> + *   - 0 if the confugration is valid
> + *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
> + *     with fallback values with which the configuration of all CRTCs
> + *     in @state must be recomputed
> + *   - Other negative error, if the configuration is invalid without a
> + *     fallback possibility, or the check failed for another reason
> + */
> +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> +			       struct intel_link_bw_limits *new_limits)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_link_bw_limits old_limits = *new_limits;
> +	int ret;
> +
> +	ret = check_all_link_config(state, new_limits);
> +	if (ret != -EAGAIN)
> +		return ret;
> +
> +	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
> +		return -EINVAL;
> +
> +	return -EAGAIN;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
> new file mode 100644
> index 0000000000000..e514caff5898e
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef __INTEL_LINK_BW_H__
> +#define __INTEL_LINK_BW_H__
> +
> +#include <linux/types.h>
> +
> +#include "intel_display_limits.h"
> +
> +struct drm_i915_private;
> +
> +struct intel_atomic_state;
> +struct intel_crtc_state;
> +
> +struct intel_link_bw_limits {
> +	u8 min_bpp_pipes;
> +	/* in 1/16 bpp units */
> +	int max_bpp_x16[I915_MAX_PIPES];
> +};
> +
> +void intel_link_bw_init_limits(struct drm_i915_private *i915,
> +			       struct intel_link_bw_limits *limits);
> +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
> +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> +			     struct intel_link_bw_limits *limits,
> +			     u8 pipe_mask,
> +			     const char *reason);
> +bool intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> +					   const struct intel_link_bw_limits *old_limits,
> +					   struct intel_link_bw_limits *new_limits,
> +					   enum pipe pipe);
> +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> +			       struct intel_link_bw_limits *new_limits);
> +
> +#endif
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C Imre Deak
@ 2023-09-15 19:31   ` Ville Syrjälä
  2023-09-15 23:13     ` Imre Deak
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
  1 sibling, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-15 19:31 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:44PM +0300, Imre Deak wrote:
> At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
> lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
> link bpp in this case, until pipe B uses only up to 2 FDI lanes.
> 
> For this instead of the encoder compute config retry loop - which
> reduced link bpp only for the encoder's pipe - reduce the maximum link
> bpp for pipe B/C as required after all CRTC states are computed and
> recompute the CRTC states with the new bpp limit.
> 
> v2:
> - Don't assume that a CRTC is already in the atomic state, while
>   reducing its link bpp.
> - Add DocBook description to intel_fdi_atomic_check_link().
> v3:
> - Enable BW management for FDI links in a separate patch. (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
>  drivers/gpu/drm/i915/display/intel_crt.c     |  7 ++
>  drivers/gpu/drm/i915/display/intel_display.c | 14 +---
>  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
>  drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
>  drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
>  drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
>  drivers/gpu/drm/i915/display/intel_lvds.c    | 10 ++-
>  drivers/gpu/drm/i915/display/intel_sdvo.c    | 10 ++-
>  9 files changed, 107 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> index 634b14116d9dd..8b5d26cd3b85e 100644
> --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> @@ -19,6 +19,7 @@
>  #include "intel_fifo_underrun.h"
>  #include "intel_hdmi.h"
>  #include "intel_hotplug.h"
> +#include "intel_link_bw.h"
>  #include "intel_sdvo.h"
>  #include "vlv_sideband.h"
>  
> @@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>  	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>  
> -	if (HAS_PCH_SPLIT(i915))
> +	if (HAS_PCH_SPLIT(i915)) {
>  		crtc_state->has_pch_encoder = true;
> +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> +			return -EINVAL;
> +	}
>  
>  	if (IS_G4X(i915))
>  		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> index f6df6c4fa72ef..7aa89d0fa3d6c 100644
> --- a/drivers/gpu/drm/i915/display/intel_crt.c
> +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> @@ -49,6 +49,7 @@
>  #include "intel_gmbus.h"
>  #include "intel_hotplug.h"
>  #include "intel_hotplug_irq.h"
> +#include "intel_link_bw.h"
>  #include "intel_load_detect.h"
>  #include "intel_pch_display.h"
>  #include "intel_pch_refclk.h"
> @@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
>  		return -EINVAL;
>  
>  	pipe_config->has_pch_encoder = true;
> +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> +		return -EINVAL;
> +
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
>  
>  	return 0;
> @@ -435,6 +439,9 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
>  		return -EINVAL;
>  
>  	pipe_config->has_pch_encoder = true;
> +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> +		return -EINVAL;
> +
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
>  
>  	/* LPT FDI RX only supports 8bpc. */
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 29816153fdd59..aad16dcceb788 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  	struct drm_connector_state *connector_state;
>  	int pipe_src_w, pipe_src_h;
>  	int base_bpp, ret, i;
> -	bool retry = true;
>  
>  	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
>  
> @@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
>  			    crtc->base.base.id, crtc->base.name,
>  			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> +		crtc_state->bw_constrained = true;
>  	}
>  
>  	base_bpp = crtc_state->pipe_bpp;
> @@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  			crtc_state->output_types |= BIT(encoder->type);
>  	}
>  
> -encoder_retry:
>  	/* Ensure the port clock defaults are reset when retrying. */
>  	crtc_state->port_clock = 0;
>  	crtc_state->pixel_multiplier = 1;
> @@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  	ret = intel_crtc_compute_config(state, crtc);
>  	if (ret == -EDEADLK)
>  		return ret;
> -	if (ret == -EAGAIN) {
> -		if (drm_WARN(&i915->drm, !retry,
> -			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
> -			     crtc->base.base.id, crtc->base.name))
> -			return -EINVAL;
> -
> -		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
> -			    crtc->base.base.id, crtc->base.name);
> -		retry = false;
> -		goto encoder_retry;
> -	}
>  	if (ret < 0) {
>  		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
>  			    crtc->base.base.id, crtc->base.name, ret);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index d5e6813d36c8f..03010accc1c7f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
>  	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
>  	int max_link_bpp_x16;
>  
> -	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> +	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
> +			       to_bpp_x16(limits->pipe.max_bpp));
>  
>  	if (!dsc) {
>  		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
> diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> index 4d7d524c68017..ad01915a4a39b 100644
> --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> @@ -13,6 +13,7 @@
>  #include "intel_display_types.h"
>  #include "intel_fdi.h"
>  #include "intel_fdi_regs.h"
> +#include "intel_link_bw.h"
>  
>  struct intel_fdi_funcs {
>  	void (*fdi_link_train)(struct intel_crtc *crtc,
> @@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
>  }
>  
>  static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> -			       struct intel_crtc_state *pipe_config)
> +			       struct intel_crtc_state *pipe_config,
> +			       enum pipe *pipe_to_reduce)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct drm_atomic_state *state = pipe_config->uapi.state;
>  	struct intel_crtc *other_crtc;
>  	struct intel_crtc_state *other_crtc_state;
>  
> +	*pipe_to_reduce = pipe;
> +
>  	drm_dbg_kms(&dev_priv->drm,
>  		    "checking fdi config on pipe %c, lanes %i\n",
>  		    pipe_name(pipe), pipe_config->fdi_lanes);
> @@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
>  		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
>  			drm_dbg_kms(&dev_priv->drm,
>  				    "fdi link B uses too many lanes to enable link C\n");
> +
> +			*pipe_to_reduce = PIPE_B;
> +
>  			return -EINVAL;
>  		}
>  		return 0;
> @@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *i915 = to_i915(dev);
>  	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> -	int lane, link_bw, fdi_dotclock, ret;
> -	bool needs_recompute = false;
> +	int lane, link_bw, fdi_dotclock;
>  
> -retry:
>  	/* FDI is a binary signal running at ~2.7GHz, encoding
>  	 * each output octet as 10 bits. The actual frequency
>  	 * is stored as a divider into a 100MHz clock, and the
> @@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
>  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
>  			       link_bw, &pipe_config->fdi_m_n, false);
>  
> -	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
> -	if (ret == -EDEADLK)
> +	return 0;
> +}
> +
> +static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
> +				     struct intel_crtc *crtc,
> +				     struct intel_crtc_state *pipe_config,
> +				     struct intel_link_bw_limits *limits)
> +{
> +	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> +	enum pipe pipe_to_reduce;
> +	int ret;
> +
> +	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
> +				  &pipe_to_reduce);
> +	if (ret != -EINVAL)
>  		return ret;
>  
> -	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
> -		pipe_config->pipe_bpp -= 2*3;
> -		drm_dbg_kms(&i915->drm,
> -			    "fdi link bw constraint, reducing pipe bpp to %i\n",
> -			    pipe_config->pipe_bpp);
> -		needs_recompute = true;
> -		pipe_config->bw_constrained = true;
> -
> -		goto retry;
> +	ret = intel_link_bw_reduce_bpp(state, limits,
> +				       BIT(pipe_to_reduce),
> +				       "FDI link BW");
> +
> +	return ret ? : -EAGAIN;
> +}
> +
> +/**
> + * intel_fdi_atomic_check_link - check all modeset FDI link configuration
> + * @state: intel atomic state
> + * @limits: link BW limits
> + *
> + * Check the link configuration for all modeset FDI outputs. If the
> + * configuration is invalid @limits will be updated if possible to
> + * reduce the total BW, after which the configuration for all CRTCs in
> + * @state must be recomputed with the updated @limits.
> + *
> + * Returns:
> + *   - 0 if the confugration is valid
> + *   - %-EAGAIN, if the configuration is invalid and @limits got updated
> + *     with fallback values with which the configuration of all CRTCs
> + *     in @state must be recomputed
> + *   - Other negative error, if the configuration is invalid without a
> + *     fallback possibility, or the check failed for another reason
> + */
> +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> +				struct intel_link_bw_limits *limits)
> +{
> +	struct intel_crtc *crtc;
> +	struct intel_crtc_state *crtc_state;
> +	int i;
> +
> +	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> +		int ret;
> +
> +		if (!crtc_state->has_pch_encoder ||
> +		    !intel_crtc_needs_modeset(crtc_state) ||
> +		    !crtc_state->hw.enable)
> +			continue;
> +
> +		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
> +		if (ret)
> +			return ret;
>  	}
>  
> -	if (needs_recompute)
> -		return -EAGAIN;
> -
> -	return ret;
> +	return 0;
>  }
>  
>  static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
> diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> index 1cdb86172702f..129444c580f27 100644
> --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> @@ -8,14 +8,18 @@
>  
>  enum pipe;
>  struct drm_i915_private;
> +struct intel_atomic_state;
>  struct intel_crtc;
>  struct intel_crtc_state;
>  struct intel_encoder;
> +struct intel_link_bw_limits;
>  
>  int intel_fdi_link_freq(struct drm_i915_private *i915,
>  			const struct intel_crtc_state *pipe_config);
>  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
>  			   struct intel_crtc_state *pipe_config);
> +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> +				struct intel_link_bw_limits *limits);
>  void intel_fdi_normal_train(struct intel_crtc *crtc);
>  void ilk_fdi_disable(struct intel_crtc *crtc);
>  void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> index 22494772b9d59..aacf22bab3135 100644
> --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> @@ -160,7 +160,12 @@ intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
>  static int check_all_link_config(struct intel_atomic_state *state,
>  				 struct intel_link_bw_limits *limits)
>  {
> -	/* TODO: Check all shared display link configurations like FDI */
> +	int ret;
> +
> +	ret = intel_fdi_atomic_check_link(state, limits);
> +	if (ret)
> +		return ret;
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> index 3ace56979b70e..0366d4cc6b72b 100644
> --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> @@ -48,6 +48,7 @@
>  #include "intel_dpll.h"
>  #include "intel_fdi.h"
>  #include "intel_gmbus.h"
> +#include "intel_link_bw.h"
>  #include "intel_lvds.h"
>  #include "intel_lvds_regs.h"
>  #include "intel_panel.h"
> @@ -425,6 +426,12 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
>  		return -EINVAL;
>  	}
>  
> +	if (HAS_PCH_SPLIT(i915)) {
> +		crtc_state->has_pch_encoder = true;
> +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> +			return -EINVAL;
> +	}
> +
>  	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
>  		lvds_bpp = 8*3;
>  	else
> @@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
>  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
>  		return -EINVAL;
>  
> -	if (HAS_PCH_SPLIT(i915))
> -		crtc_state->has_pch_encoder = true;
> -
>  	ret = intel_panel_fitting(crtc_state, conn_state);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> index 135a2527fd1b4..3c912f3bc10ba 100644
> --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> @@ -48,6 +48,7 @@
>  #include "intel_gmbus.h"
>  #include "intel_hdmi.h"
>  #include "intel_hotplug.h"
> +#include "intel_link_bw.h"
>  #include "intel_panel.h"
>  #include "intel_sdvo.h"
>  #include "intel_sdvo_regs.h"
> @@ -1351,14 +1352,17 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
>  	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
>  	struct drm_display_mode *mode = &pipe_config->hw.mode;
>  
> +	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
> +		pipe_config->has_pch_encoder = true;
> +		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> +			return -EINVAL;
> +	}
> +
>  	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
>  	pipe_config->pipe_bpp = 8*3;

This seems borked. I think we want to force this to 8bpc only if we're
higher currently. Same for the LVDS case I think, though that one is a
bit more sane atm since it looks at the bw_constrained flag, though
I don't think we really need that flag anymore, at least for this 
purpose. Hmm, but maybe we do still need it for the LPT FDI case
where we do actually want to increase the bpc to 8 if the EDID
baseline is below that.

>  	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
>  
> -	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
> -		pipe_config->has_pch_encoder = true;
> -
>  	/*
>  	 * We need to construct preferred input timings based on our
>  	 * output timings.  To do that, we have to set the output
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes
  2023-09-15 18:34   ` Ville Syrjälä
@ 2023-09-15 20:03     ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-15 20:03 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Sep 15, 2023 at 09:34:26PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 14, 2023 at 10:26:40PM +0300, Imre Deak wrote:
> > Add intel_modeset_pipes_in_mask_early() to modeset a provided set of
> > pipes, used in a follow-up patch.
> > 
> > While at it add _late suffix to intel_modeset_all_pipes() for clarity
> > and add DocBook descriptions for the two exported functions.
> > 
> > v2:
> > - Add a flag controlling if active planes are force updated as well.
> > - Add DockBook descriptions.
> > v3:
> > - For clarity use _early/_late suffixes for the exported functions
> >   instead of the update_active_planes parameter. (Ville)
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_cdclk.c   |  2 +-
> >  drivers/gpu/drm/i915/display/intel_display.c | 45 ++++++++++++++++++--
> >  drivers/gpu/drm/i915/display/intel_display.h |  6 ++-
> >  drivers/gpu/drm/i915/display/skl_watermark.c |  2 +-
> >  4 files changed, 47 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
> > index ad5251ba6fe13..a2e20b25d6361 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> > +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> > @@ -3139,7 +3139,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
> >  	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
> >  					     &new_cdclk_state->actual)) {
> >  		/* All pipes must be switched off while we change the cdclk. */
> > -		ret = intel_modeset_all_pipes(state, "CDCLK change");
> > +		ret = intel_modeset_all_pipes_late(state, "CDCLK change");
> >  		if (ret)
> >  			return ret;
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index 6bbc9069754c4..27e6ea21e0a91 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -5407,8 +5407,9 @@ intel_verify_planes(struct intel_atomic_state *state)
> >  			     plane_state->uapi.visible);
> >  }
> >  
> > -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> > -			    const char *reason)
> > +static int intel_modeset_pipes_in_mask(struct intel_atomic_state *state,
> > +				       const char *reason, u8 mask,
> > +				       bool update_active_planes)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> >  	struct intel_crtc *crtc;
> > @@ -5417,7 +5418,7 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
> >  	 * Add all pipes to the state, and force
> >  	 * a modeset on all the active ones.
> >  	 */
> > -	for_each_intel_crtc(&dev_priv->drm, crtc) {
> > +	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, mask) {
> >  		struct intel_crtc_state *crtc_state;
> >  		int ret;
> >  
> > @@ -5448,7 +5449,9 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
> >  		if (ret)
> >  			return ret;
> >  
> > -		crtc_state->update_planes |= crtc_state->active_planes;
> > +		if (update_active_planes)
> > +			crtc_state->update_planes |= crtc_state->active_planes;
> 
> This thing still confuses me. We have a bunch of other "late modeset"
> stuff in there (async flip handling and clearing of fastset flag at
> least). I still think a clean split would be better than a confusing
> parameter.

Ok, makes sense. The rest of the flags start out as cleared, but the
only relevant thing for early modeset is setting uapi.mode_changed
(IIUC).

Also, adding hw.enable && !hw.active CRTCs to the state could be
done only during an early modeset.

> > +
> >  		crtc_state->async_flip_planes = 0;
> >  		crtc_state->do_async_flip = false;
> >  	}
> > @@ -5456,6 +5459,40 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
> >  	return 0;
> >  }
> >  
> > +/**
> > + * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
> > + * @state: intel atomic state
> > + * @reason: the reason for the full modeset
> > + * @mask: mask of pipes to modeset
> > + *
> > + * Force a full modeset on pipes in @mask due to the description in @reason.
> > + * This function can be called only before new plane states are computed.
> > + *
> > + * Returns 0 in case of success, negative error code otherwise.
> > + */
> > +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> > +				      const char *reason, u8 mask)
> > +{
> > +	return intel_modeset_pipes_in_mask(state, reason, mask, false);
> > +}
> > +
> > +/**
> > + * intel_modeset_all_pipes_late - force a full modeset on all pipes
> > + * @state: intel atomic state
> > + * @reason: the reason for the full modeset
> > + *
> > + * Force a full modeset on all pipes due to the description in @reason.
> > + * This function can be called only after new plane states are computed
> > + * already.
> > + *
> > + * Returns 0 in case of success, negative error code otherwise.
> > + */
> > +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> > +				 const char *reason)
> > +{
> > +	return intel_modeset_pipes_in_mask(state, reason, -1, true);
> > +}
> > +
> >  /*
> >   * This implements the workaround described in the "notes" section of the mode
> >   * set sequence documentation. When going from no pipes or single pipe to
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> > index 49ac8473b988b..64a5be7859331 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display.h
> > @@ -513,8 +513,10 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
> >  void intel_update_watermarks(struct drm_i915_private *i915);
> >  
> >  /* modesetting */
> > -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> > -			    const char *reason);
> > +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> > +				      const char *reason, u8 pipe_mask);
> > +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> > +				 const char *reason);
> >  void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
> >  					  struct intel_power_domain_mask *old_domains);
> >  void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
> > diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
> > index 063929a42a42f..a29d9b717deed 100644
> > --- a/drivers/gpu/drm/i915/display/skl_watermark.c
> > +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
> > @@ -2616,7 +2616,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
> >  
> >  		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
> >  			/* TODO: Implement vblank synchronized MBUS joining changes */
> > -			ret = intel_modeset_all_pipes(state, "MBUS joining change");
> > +			ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
> >  			if (ret)
> >  				return ret;
> >  		}
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v4 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-15 19:11     ` Ville Syrjälä
@ 2023-09-15 21:01       ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-15 21:01 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Sep 15, 2023 at 10:11:38PM +0300, Ville Syrjälä wrote:
> On Fri, Sep 15, 2023 at 03:33:54AM +0300, Imre Deak wrote:
> > At the moment a modeset fails if the config computation of a pipe can't
> > fit its required BW to the available link BW even though the limitation
> > may be resolved by reducing the BW requirement of other pipes.
> > 
> > To improve the above this patch adds helper functions checking the
> > overall BW limits after all CRTC states have been computed. If the check
> > fails the maximum link bpp for a selected pipe will be reduced and all
> > the CRTC states will be recomputed until either the overall BW limit
> > check passes, or further bpp reduction is not possible (because all
> > pipes/encoders sharing the link BW reached their minimum link bpp).
> > 
> > This change prepares for upcoming patches enabling the above BW
> > management on FDI and MST links.
> > 
> > v2:
> > - Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
> >   intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
> > v3:
> > - Add the helper functions in a separate patch. (Ville)
> > - Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
> > - Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
> >   limit failure.
> > v4:
> > - Make intel_atomic_check_config() static.
> > 
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/Makefile                 |   1 +
> >  drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
> >  drivers/gpu/drm/i915/display/intel_display.c  |  61 ++++-
> >  .../drm/i915/display/intel_display_types.h    |   3 +-
> >  drivers/gpu/drm/i915/display/intel_link_bw.c  | 226 ++++++++++++++++++
> >  drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
> >  6 files changed, 325 insertions(+), 5 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index 1b2e02e9d92cb..de4967c141f00 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -268,6 +268,7 @@ i915-y += \
> >  	display/intel_hotplug.o \
> >  	display/intel_hotplug_irq.o \
> >  	display/intel_hti.o \
> > +	display/intel_link_bw.o \
> >  	display/intel_load_detect.o \
> >  	display/intel_lpe_audio.o \
> >  	display/intel_modeset_lock.o \
> > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> > index 182c6dd64f47c..1eda6a9f19aa8 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> > @@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> >  	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> >  	crtc_state->scaler_state.scaler_id = -1;
> >  	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> > +	crtc_state->max_link_bpp_x16 = INT_MAX;
> 
> Are we sure we won't end up doing random arithmetic with that which could
> overflow?

It's only used limiting values to an upper bound, so can't see at least
where it could overflow.

> >  }
> >  
> >  static struct intel_crtc *intel_crtc_alloc(void)
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index fe3b6844e063d..0f30723a68cc0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -87,6 +87,7 @@
> >  #include "intel_frontbuffer.h"
> >  #include "intel_hdmi.h"
> >  #include "intel_hotplug.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_lvds.h"
> >  #include "intel_lvds_regs.h"
> >  #include "intel_modeset_setup.h"
> > @@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
> >  
> >  static int
> >  intel_modeset_pipe_config(struct intel_atomic_state *state,
> > -			  struct intel_crtc *crtc)
> > +			  struct intel_crtc *crtc,
> > +			  const struct intel_link_bw_limits *limits)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> >  	struct intel_crtc_state *crtc_state =
> > @@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  	if (ret)
> >  		return ret;
> >  
> > +	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
> > +
> > +	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
> > +		drm_dbg_kms(&i915->drm,
> > +			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> > +			    crtc->base.base.id, crtc->base.name,
> > +			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> > +	}
> > +
> >  	base_bpp = crtc_state->pipe_bpp;
> >  
> >  	/*
> > @@ -6195,7 +6206,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
> >  	return 0;
> >  }
> >  
> > -static int intel_atomic_check_config(struct intel_atomic_state *state)
> > +static int intel_atomic_check_config(struct intel_atomic_state *state,
> > +				     struct intel_link_bw_limits *limits,
> > +				     enum pipe *failed_pipe)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(state->base.dev);
> >  	struct intel_crtc_state *new_crtc_state;
> > @@ -6203,6 +6216,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  	int ret;
> >  	int i;
> >  
> > +	*failed_pipe = INVALID_PIPE;
> > +
> >  	ret = intel_bigjoiner_add_affected_crtcs(state);
> >  	if (ret)
> >  		return ret;
> > @@ -6228,7 +6243,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  		if (!new_crtc_state->hw.enable)
> >  			continue;
> >  
> > -		ret = intel_modeset_pipe_config(state, crtc);
> > +		ret = intel_modeset_pipe_config(state, crtc, limits);
> >  		if (ret)
> >  			break;
> >  
> > @@ -6237,9 +6252,47 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  			break;
> >  	}
> >  
> > +	if (ret)
> > +		*failed_pipe = crtc->pipe;
> > +
> >  	return ret;
> >  }
> >  
> > +static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	struct intel_link_bw_limits new_limits;
> > +	struct intel_link_bw_limits old_limits;
> > +	int ret;
> > +
> > +	intel_link_bw_init_limits(i915, &new_limits);
> > +	old_limits = new_limits;
> > +
> > +	while (true) {
> > +		enum pipe failed_pipe;
> > +
> > +		ret = intel_atomic_check_config(state, &new_limits,
> > +						&failed_pipe);
> > +		if (ret) {
> > +			if (ret == -EINVAL &&
> > +			    intel_link_bw_reset_pipe_limit_to_min(state,
> > +								  &old_limits,
> > +								  &new_limits,
> > +								  failed_pipe))
> > +				continue;
> > +
> > +			break;
> > +		}
> > +
> > +		old_limits = new_limits;
> > +
> > +		ret = intel_link_bw_atomic_check(state, &new_limits);
> > +		if (ret != -EAGAIN)
> > +			break;
> > +	}
> > +
> > +	return ret;
> > +}
> >  /**
> >   * intel_atomic_check - validate state object
> >   * @dev: drm device
> > @@ -6284,7 +6337,7 @@ int intel_atomic_check(struct drm_device *dev,
> >  			return ret;
> >  	}
> >  
> > -	ret = intel_atomic_check_config(state);
> > +	ret = intel_atomic_check_config_and_link(state);
> >  	if (ret)
> >  		goto fail;
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 966163ccbd7a3..514977ebc17b0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1189,7 +1189,8 @@ struct intel_crtc_state {
> >  		u32 ctrl, div;
> >  	} dsi_pll;
> >  
> > -	int pipe_bpp;
> > +	int max_link_bpp_x16;	/* in 1/16 bpp units */
> > +	int pipe_bpp;		/* in 1 bpp units */
> >  	struct intel_link_m_n dp_m_n;
> >  
> >  	/* m2_n2 for eDP downclock */
> > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > new file mode 100644
> > index 0000000000000..22494772b9d59
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > @@ -0,0 +1,226 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#include "i915_drv.h"
> > +
> > +#include "intel_atomic.h"
> > +#include "intel_display_types.h"
> > +#include "intel_dp_mst.h"
> > +#include "intel_fdi.h"
> > +#include "intel_link_bw.h"
> > +
> > +/**
> > + * intel_link_bw_init_limits - initialize BW limits
> > + * @i915: device instance
> > + * @limits: link BW limits
> > + *
> > + * Initialize @limits.
> > + */
> > +void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
> > +{
> > +	enum pipe pipe;
> > +
> > +	limits->min_bpp_pipes = 0;
> > +	for_each_pipe(i915, pipe)
> > +		limits->max_bpp_x16[pipe] = INT_MAX;
> > +}
> > +
> > +/**
> > + * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
> > + * @crtc_state: the crtc state
> > + *
> > + * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
> > + * call this function during state computation in the simple case where the
> > + * link bpp will always match the pipe bpp. This is the case for all non-DP
> > + * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
> > + * of DSC compression.
> > + *
> > + * Returns %true in case of success, %false if pipe bpp would need to be
> > + * reduced below its valid range.
> > + */
> > +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
> > +{
> > +	int pipe_bpp = min(crtc_state->pipe_bpp,
> > +			   to_bpp_int(crtc_state->max_link_bpp_x16));
> > +
> > +	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
> > +
> > +	if (pipe_bpp < 6 * 3)
> > +		return false;
> > +
> > +	crtc_state->pipe_bpp = pipe_bpp;
> > +
> > +	return true;
> > +}
> > +
> > +/**
> > + * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
> > + * @state: atomic state
> > + * @limits: link BW limits
> > + * @pipe_mask: mask of pipes to select from
> > + * @reason: explanation of why bpp reduction is needed
> > + *
> > + * Select the pipe from @pipe_mask with the biggest link bpp value and set the
> > + * maximum of link bpp in @limits below this value. Modeset the selected pipe,
> > + * so that its state will get recomputed.
> > + *
> > + * This function can be called to resolve a link's BW overallocation by reducing
> > + * the link bpp of one pipe on the link and hence reducing the total link BW.
> > + *
> > + * Returns
> > + *   - 0 in case of success
> > + *   - %-ENOSPC if no pipe can further reduce its link bpp
> > + *   - Other negative error, if modesetting the selected pipe failed
> > + */
> > +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> > +			     struct intel_link_bw_limits *limits,
> > +			     u8 pipe_mask,
> > +			     const char *reason)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	enum pipe max_bpp_pipe = INVALID_PIPE;
> > +	struct intel_crtc *crtc;
> > +	int max_bpp = 0;
> > +
> > +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
> > +		struct intel_crtc_state *crtc_state;
> > +		int pipe_bpp;
> > +
> > +		if (limits->min_bpp_pipes & BIT(crtc->pipe))
> > +			continue;
> > +
> > +		crtc_state = intel_atomic_get_crtc_state(&state->base,
> > +							 crtc);
> > +		if (IS_ERR(crtc_state))
> > +			return PTR_ERR(crtc_state);
> > +
> > +		if (crtc_state->dsc.compression_enable)
> > +			pipe_bpp = crtc_state->dsc.compressed_bpp;
> > +		else
> > +			pipe_bpp = crtc_state->pipe_bpp;
> 
> That sounds like it should be 'link_bpp'.

Yes, will change it.

> Hmm. How does this work with 4:2:0 output?

Didn't think about that, but looking at
intel_dp_compute_link_config_wide() now, in the uncompressed case only
half of crtc_state->pipe_bpp will be the actual bpp output. So in that
case this code will decrease the limit for 2x of the actual bpp output
until a valid configuration is found.

> > +
> > +		if (pipe_bpp > max_bpp) {
> > +			max_bpp = pipe_bpp;
> > +			max_bpp_pipe = crtc->pipe;
> > +		}
> > +	}
> > +
> > +	if (max_bpp_pipe == INVALID_PIPE)
> > +		return -ENOSPC;
> > +
> > +	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
> > +
> > +	return intel_modeset_pipes_in_mask_early(state, reason,
> > +						 BIT(max_bpp_pipe));
> 
> So we always reduce just for one pipe at a time. I suppose that does
> lead to the most optimal bandwidth usage, albeit with perhaps a
> slighly slower convergence.

Yes, assuming that the retry loop is not a significant overhead.

> > +}
> > +
> > +/**
> > + * intel_link_bw_reset_pipe_limit_to_min - reset BW limit for a pipe to its minimum
> > + * @state: atomic state
> > + * @old_limits: link BW limits
> > + * @new_limits: link BW limits
> > + * @pipe: pipe
> > + *
> > + * Reset the link bpp limit for @pipe in @new_limits to its value in
> > + * @old_limits and mark this limit as the minimum. This function must be
> > + * called after a pipe's compute config function failed, @old_limits
> > + * containing the bpp limit with which compute config previously passed.
> > + *
> > + * The function will fail if setting a minimum is not possible, either
> > + * because the old and new limits match (and so would lead to a pipe compute
> > + * config failure) or the limit is already at the minimum.
> > + *
> > + * Returns %true in case of success.
> > + */
> > +bool
> > +intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> > +				       const struct intel_link_bw_limits *old_limits,
> > +				       struct intel_link_bw_limits *new_limits,
> > +				       enum pipe pipe)
> > +{
> > +	if (pipe == INVALID_PIPE)
> > +		return false;
> > +
> > +	if (new_limits->min_bpp_pipes & BIT(pipe))
> > +		return false;
> > +
> > +	if (new_limits->max_bpp_x16[pipe] ==
> > +	    old_limits->max_bpp_x16[pipe])
> > +		return false;
> > +
> > +	new_limits->max_bpp_x16[pipe] =
> > +		old_limits->max_bpp_x16[pipe];
> > +	new_limits->min_bpp_pipes |= BIT(pipe);
> 
> So that bitmask is keeping track of pipes which have reached what
> they consider to be an absolute minimum usable bpp?

Yes.

> The naming confused me a bit, of both the bitmask and the function.
> Maybe something like 'min_bpp_reached_pipes' would be a bit more
> clear,

Ok, can rename it.

> and intel_link_bw_min_bpp_reached() or something for the
> function name?
> Still doesn't really work when just reading the code
> though...

Yes, couldn't think of a better name, I can rename it to the above.

I was thinking of an alternative way, where encoders could preset the
minimum bpp they support, but opted for deducting this from the compute
config functions' error/pass return value as that's more generic.

> > +
> > +	return true;
> > +}
> > +
> > +static int check_all_link_config(struct intel_atomic_state *state,
> > +				 struct intel_link_bw_limits *limits)
> > +{
> > +	/* TODO: Check all shared display link configurations like FDI */
> > +	return 0;
> > +}
> > +
> > +static bool
> > +assert_link_limit_change_valid(struct drm_i915_private *i915,
> > +			       const struct intel_link_bw_limits *old_limits,
> > +			       const struct intel_link_bw_limits *new_limits)
> > +{
> > +	bool bpps_changed = false;
> > +	enum pipe pipe;
> > +
> > +	for_each_pipe(i915, pipe) {
> > +		/* The bpp limit can only decrease. */
> > +		if (drm_WARN_ON(&i915->drm,
> > +				new_limits->max_bpp_x16[pipe] >
> > +				old_limits->max_bpp_x16[pipe]))
> > +			return false;
> > +
> > +		if (new_limits->max_bpp_x16[pipe] <
> > +		    old_limits->max_bpp_x16[pipe])
> > +			bpps_changed = true;
> > +	}
> > +
> > +	/* At least one limit must change. */
> > +	if (drm_WARN_ON(&i915->drm,
> > +			!bpps_changed))
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> > +/**
> > + * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
> > + * @state: atomic state
> > + * @new_limits: link BW limits
> > + *
> > + * Check the configuration of all shared display links in @state and set new BW
> > + * limits in @new_limits if there is a BW limitation.
> > + *
> > + * Returns:
> > + *   - 0 if the confugration is valid
> > + *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
> > + *     with fallback values with which the configuration of all CRTCs
> > + *     in @state must be recomputed
> > + *   - Other negative error, if the configuration is invalid without a
> > + *     fallback possibility, or the check failed for another reason
> > + */
> > +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> > +			       struct intel_link_bw_limits *new_limits)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	struct intel_link_bw_limits old_limits = *new_limits;
> > +	int ret;
> > +
> > +	ret = check_all_link_config(state, new_limits);
> > +	if (ret != -EAGAIN)
> > +		return ret;
> > +
> > +	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
> > +		return -EINVAL;
> > +
> > +	return -EAGAIN;
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
> > new file mode 100644
> > index 0000000000000..e514caff5898e
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#ifndef __INTEL_LINK_BW_H__
> > +#define __INTEL_LINK_BW_H__
> > +
> > +#include <linux/types.h>
> > +
> > +#include "intel_display_limits.h"
> > +
> > +struct drm_i915_private;
> > +
> > +struct intel_atomic_state;
> > +struct intel_crtc_state;
> > +
> > +struct intel_link_bw_limits {
> > +	u8 min_bpp_pipes;
> > +	/* in 1/16 bpp units */
> > +	int max_bpp_x16[I915_MAX_PIPES];
> > +};
> > +
> > +void intel_link_bw_init_limits(struct drm_i915_private *i915,
> > +			       struct intel_link_bw_limits *limits);
> > +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
> > +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> > +			     struct intel_link_bw_limits *limits,
> > +			     u8 pipe_mask,
> > +			     const char *reason);
> > +bool intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> > +					   const struct intel_link_bw_limits *old_limits,
> > +					   struct intel_link_bw_limits *new_limits,
> > +					   enum pipe pipe);
> > +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> > +			       struct intel_link_bw_limits *new_limits);
> > +
> > +#endif
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-15 19:31   ` Ville Syrjälä
@ 2023-09-15 23:13     ` Imre Deak
  2023-09-19 15:35       ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-15 23:13 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Sep 15, 2023 at 10:31:05PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 14, 2023 at 10:26:44PM +0300, Imre Deak wrote:
> > At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
> > lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
> > link bpp in this case, until pipe B uses only up to 2 FDI lanes.
> > 
> > For this instead of the encoder compute config retry loop - which
> > reduced link bpp only for the encoder's pipe - reduce the maximum link
> > bpp for pipe B/C as required after all CRTC states are computed and
> > recompute the CRTC states with the new bpp limit.
> > 
> > v2:
> > - Don't assume that a CRTC is already in the atomic state, while
> >   reducing its link bpp.
> > - Add DocBook description to intel_fdi_atomic_check_link().
> > v3:
> > - Enable BW management for FDI links in a separate patch. (Ville)
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
> >  drivers/gpu/drm/i915/display/intel_crt.c     |  7 ++
> >  drivers/gpu/drm/i915/display/intel_display.c | 14 +---
> >  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
> >  drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
> >  drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
> >  drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
> >  drivers/gpu/drm/i915/display/intel_lvds.c    | 10 ++-
> >  drivers/gpu/drm/i915/display/intel_sdvo.c    | 10 ++-
> >  9 files changed, 107 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > index 634b14116d9dd..8b5d26cd3b85e 100644
> > --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > @@ -19,6 +19,7 @@
> >  #include "intel_fifo_underrun.h"
> >  #include "intel_hdmi.h"
> >  #include "intel_hotplug.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_sdvo.h"
> >  #include "vlv_sideband.h"
> >  
> > @@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
> >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> >  	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> >  
> > -	if (HAS_PCH_SPLIT(i915))
> > +	if (HAS_PCH_SPLIT(i915)) {
> >  		crtc_state->has_pch_encoder = true;
> > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > +			return -EINVAL;
> > +	}
> >  
> >  	if (IS_G4X(i915))
> >  		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
> > diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> > index f6df6c4fa72ef..7aa89d0fa3d6c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crt.c
> > +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> > @@ -49,6 +49,7 @@
> >  #include "intel_gmbus.h"
> >  #include "intel_hotplug.h"
> >  #include "intel_hotplug_irq.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_load_detect.h"
> >  #include "intel_pch_display.h"
> >  #include "intel_pch_refclk.h"
> > @@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
> >  		return -EINVAL;
> >  
> >  	pipe_config->has_pch_encoder = true;
> > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > +		return -EINVAL;
> > +
> >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> >  
> >  	return 0;
> > @@ -435,6 +439,9 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
> >  		return -EINVAL;
> >  
> >  	pipe_config->has_pch_encoder = true;
> > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > +		return -EINVAL;
> > +
> >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> >  
> >  	/* LPT FDI RX only supports 8bpc. */
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index 29816153fdd59..aad16dcceb788 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  	struct drm_connector_state *connector_state;
> >  	int pipe_src_w, pipe_src_h;
> >  	int base_bpp, ret, i;
> > -	bool retry = true;
> >  
> >  	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
> >  
> > @@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> >  			    crtc->base.base.id, crtc->base.name,
> >  			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> > +		crtc_state->bw_constrained = true;
> >  	}
> >  
> >  	base_bpp = crtc_state->pipe_bpp;
> > @@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  			crtc_state->output_types |= BIT(encoder->type);
> >  	}
> >  
> > -encoder_retry:
> >  	/* Ensure the port clock defaults are reset when retrying. */
> >  	crtc_state->port_clock = 0;
> >  	crtc_state->pixel_multiplier = 1;
> > @@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  	ret = intel_crtc_compute_config(state, crtc);
> >  	if (ret == -EDEADLK)
> >  		return ret;
> > -	if (ret == -EAGAIN) {
> > -		if (drm_WARN(&i915->drm, !retry,
> > -			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
> > -			     crtc->base.base.id, crtc->base.name))
> > -			return -EINVAL;
> > -
> > -		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
> > -			    crtc->base.base.id, crtc->base.name);
> > -		retry = false;
> > -		goto encoder_retry;
> > -	}
> >  	if (ret < 0) {
> >  		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
> >  			    crtc->base.base.id, crtc->base.name, ret);
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index d5e6813d36c8f..03010accc1c7f 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
> >  	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> >  	int max_link_bpp_x16;
> >  
> > -	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> > +	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
> > +			       to_bpp_x16(limits->pipe.max_bpp));
> >  
> >  	if (!dsc) {
> >  		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
> > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> > index 4d7d524c68017..ad01915a4a39b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> > @@ -13,6 +13,7 @@
> >  #include "intel_display_types.h"
> >  #include "intel_fdi.h"
> >  #include "intel_fdi_regs.h"
> > +#include "intel_link_bw.h"
> >  
> >  struct intel_fdi_funcs {
> >  	void (*fdi_link_train)(struct intel_crtc *crtc,
> > @@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
> >  }
> >  
> >  static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > -			       struct intel_crtc_state *pipe_config)
> > +			       struct intel_crtc_state *pipe_config,
> > +			       enum pipe *pipe_to_reduce)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct drm_atomic_state *state = pipe_config->uapi.state;
> >  	struct intel_crtc *other_crtc;
> >  	struct intel_crtc_state *other_crtc_state;
> >  
> > +	*pipe_to_reduce = pipe;
> > +
> >  	drm_dbg_kms(&dev_priv->drm,
> >  		    "checking fdi config on pipe %c, lanes %i\n",
> >  		    pipe_name(pipe), pipe_config->fdi_lanes);
> > @@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> >  		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
> >  			drm_dbg_kms(&dev_priv->drm,
> >  				    "fdi link B uses too many lanes to enable link C\n");
> > +
> > +			*pipe_to_reduce = PIPE_B;
> > +
> >  			return -EINVAL;
> >  		}
> >  		return 0;
> > @@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> >  	struct drm_device *dev = crtc->base.dev;
> >  	struct drm_i915_private *i915 = to_i915(dev);
> >  	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> > -	int lane, link_bw, fdi_dotclock, ret;
> > -	bool needs_recompute = false;
> > +	int lane, link_bw, fdi_dotclock;
> >  
> > -retry:
> >  	/* FDI is a binary signal running at ~2.7GHz, encoding
> >  	 * each output octet as 10 bits. The actual frequency
> >  	 * is stored as a divider into a 100MHz clock, and the
> > @@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> >  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
> >  			       link_bw, &pipe_config->fdi_m_n, false);
> >  
> > -	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
> > -	if (ret == -EDEADLK)
> > +	return 0;
> > +}
> > +
> > +static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
> > +				     struct intel_crtc *crtc,
> > +				     struct intel_crtc_state *pipe_config,
> > +				     struct intel_link_bw_limits *limits)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> > +	enum pipe pipe_to_reduce;
> > +	int ret;
> > +
> > +	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
> > +				  &pipe_to_reduce);
> > +	if (ret != -EINVAL)
> >  		return ret;
> >  
> > -	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
> > -		pipe_config->pipe_bpp -= 2*3;
> > -		drm_dbg_kms(&i915->drm,
> > -			    "fdi link bw constraint, reducing pipe bpp to %i\n",
> > -			    pipe_config->pipe_bpp);
> > -		needs_recompute = true;
> > -		pipe_config->bw_constrained = true;
> > -
> > -		goto retry;
> > +	ret = intel_link_bw_reduce_bpp(state, limits,
> > +				       BIT(pipe_to_reduce),
> > +				       "FDI link BW");
> > +
> > +	return ret ? : -EAGAIN;
> > +}
> > +
> > +/**
> > + * intel_fdi_atomic_check_link - check all modeset FDI link configuration
> > + * @state: intel atomic state
> > + * @limits: link BW limits
> > + *
> > + * Check the link configuration for all modeset FDI outputs. If the
> > + * configuration is invalid @limits will be updated if possible to
> > + * reduce the total BW, after which the configuration for all CRTCs in
> > + * @state must be recomputed with the updated @limits.
> > + *
> > + * Returns:
> > + *   - 0 if the confugration is valid
> > + *   - %-EAGAIN, if the configuration is invalid and @limits got updated
> > + *     with fallback values with which the configuration of all CRTCs
> > + *     in @state must be recomputed
> > + *   - Other negative error, if the configuration is invalid without a
> > + *     fallback possibility, or the check failed for another reason
> > + */
> > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > +				struct intel_link_bw_limits *limits)
> > +{
> > +	struct intel_crtc *crtc;
> > +	struct intel_crtc_state *crtc_state;
> > +	int i;
> > +
> > +	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> > +		int ret;
> > +
> > +		if (!crtc_state->has_pch_encoder ||
> > +		    !intel_crtc_needs_modeset(crtc_state) ||
> > +		    !crtc_state->hw.enable)
> > +			continue;
> > +
> > +		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
> > +		if (ret)
> > +			return ret;
> >  	}
> >  
> > -	if (needs_recompute)
> > -		return -EAGAIN;
> > -
> > -	return ret;
> > +	return 0;
> >  }
> >  
> >  static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
> > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> > index 1cdb86172702f..129444c580f27 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> > +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> > @@ -8,14 +8,18 @@
> >  
> >  enum pipe;
> >  struct drm_i915_private;
> > +struct intel_atomic_state;
> >  struct intel_crtc;
> >  struct intel_crtc_state;
> >  struct intel_encoder;
> > +struct intel_link_bw_limits;
> >  
> >  int intel_fdi_link_freq(struct drm_i915_private *i915,
> >  			const struct intel_crtc_state *pipe_config);
> >  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> >  			   struct intel_crtc_state *pipe_config);
> > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > +				struct intel_link_bw_limits *limits);
> >  void intel_fdi_normal_train(struct intel_crtc *crtc);
> >  void ilk_fdi_disable(struct intel_crtc *crtc);
> >  void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
> > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > index 22494772b9d59..aacf22bab3135 100644
> > --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > @@ -160,7 +160,12 @@ intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> >  static int check_all_link_config(struct intel_atomic_state *state,
> >  				 struct intel_link_bw_limits *limits)
> >  {
> > -	/* TODO: Check all shared display link configurations like FDI */
> > +	int ret;
> > +
> > +	ret = intel_fdi_atomic_check_link(state, limits);
> > +	if (ret)
> > +		return ret;
> > +
> >  	return 0;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> > index 3ace56979b70e..0366d4cc6b72b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> > @@ -48,6 +48,7 @@
> >  #include "intel_dpll.h"
> >  #include "intel_fdi.h"
> >  #include "intel_gmbus.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_lvds.h"
> >  #include "intel_lvds_regs.h"
> >  #include "intel_panel.h"
> > @@ -425,6 +426,12 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> >  		return -EINVAL;
> >  	}
> >  
> > +	if (HAS_PCH_SPLIT(i915)) {
> > +		crtc_state->has_pch_encoder = true;
> > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > +			return -EINVAL;
> > +	}
> > +
> >  	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
> >  		lvds_bpp = 8*3;
> >  	else
> > @@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> >  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> >  		return -EINVAL;
> >  
> > -	if (HAS_PCH_SPLIT(i915))
> > -		crtc_state->has_pch_encoder = true;
> > -
> >  	ret = intel_panel_fitting(crtc_state, conn_state);
> >  	if (ret)
> >  		return ret;
> > diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > index 135a2527fd1b4..3c912f3bc10ba 100644
> > --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> > +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > @@ -48,6 +48,7 @@
> >  #include "intel_gmbus.h"
> >  #include "intel_hdmi.h"
> >  #include "intel_hotplug.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_panel.h"
> >  #include "intel_sdvo.h"
> >  #include "intel_sdvo_regs.h"
> > @@ -1351,14 +1352,17 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
> >  	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> >  	struct drm_display_mode *mode = &pipe_config->hw.mode;
> >  
> > +	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
> > +		pipe_config->has_pch_encoder = true;
> > +		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > +			return -EINVAL;
> > +	}
> > +
> >  	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
> >  	pipe_config->pipe_bpp = 8*3;
> 
> This seems borked. I think we want to force this to 8bpc only if we're
> higher currently.

This would fail the modeset if pipe_bpp would need to be reduced to 6*3
due to a BW limit and that's what happens before this change as well
afaics. I agree it's strange to detect that only later in the retry loop
and the above should return already error in that case. Are you ok with
that (if crtc_state->max_link_bpp < 8*3 -> return -EINVAL) ?

If you meant that increasing an EDID (6 bpc) baseline to 8 bpc (if BW
allows otherwise) doesn't make sense either here, that would be an issue
already before this change. I can add a FIXME: comment for that.

> Same for the LVDS case I think, though that one is a bit more sane atm
> since it looks at the bw_constrained flag, though I don't think we
> really need that flag anymore, at least for this purpose.

This patch doesn't change the behavior there either, but bw_constrained
could be replaced with crtc_state->max_link_bpp < lvds_bpp (as a
follow-up imo).

> Hmm, but maybe we do still need it for the LPT FDI case where we do
> actually want to increase the bpc to 8 if the EDID baseline is below
> that.

I suppose bw_constrained && pipe_bpp < 24 there could be also replaced
with crtc_state->max_link_bpp < 24.

> >  	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> >  
> > -	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
> > -		pipe_config->has_pch_encoder = true;
> > -
> >  	/*
> >  	 * We need to construct preferred input timings based on our
> >  	 * output timings.  To do that, we have to set the output
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* [Intel-gfx] [PATCH v5 06/25] drm/i915: Add helper to modeset a set of pipes
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes Imre Deak
  2023-09-15 18:34   ` Ville Syrjälä
@ 2023-09-18 18:25   ` Imre Deak
  2023-09-19 14:25     ` Ville Syrjälä
  1 sibling, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-18 18:25 UTC (permalink / raw)
  To: intel-gfx

Add intel_modeset_pipes_in_mask_early() to modeset a provided set of
pipes, used in a follow-up patch.

As opposed intel_modeset_all_pipes() which modesets only the active
pipes - others don't requiring programming the HW - modeset all enabled
pipes in intel_modeset_pipes_in_mask_early() which may need to recompute
their state even if they are not active (that is in the DPMS off state).

While at it add DocBook descriptions for the two exported functions.

v2:
- Add a flag controlling if active planes are force updated as well.
- Add DockBook descriptions.
v3:
- For clarity use _early/_late suffixes for the exported functions
  instead of the update_active_planes parameter. (Ville)
v4:
- In intel_modeset_pipes_in_mask_early() update only the crtc
  flags relevant to the early phase. (Ville)
- Rename intel_modeset_all_pipes() in a separate patch.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 102 +++++++++++++++----
 drivers/gpu/drm/i915/display/intel_display.h |   2 +
 2 files changed, 83 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 6bbc9069754c4..1c9a128f4af27 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5407,16 +5407,90 @@ intel_verify_planes(struct intel_atomic_state *state)
 			     plane_state->uapi.visible);
 }
 
+static int intel_modeset_pipe(struct intel_atomic_state *state,
+			      struct intel_crtc_state *crtc_state,
+			      const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
+		    crtc->base.base.id, crtc->base.name, reason);
+
+	ret = drm_atomic_add_affected_connectors(&state->base,
+						 &crtc->base);
+	if (ret)
+		return ret;
+
+	ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
+	if (ret)
+		return ret;
+
+	ret = intel_atomic_add_affected_planes(state, crtc);
+	if (ret)
+		return ret;
+
+	crtc_state->uapi.mode_changed = true;
+
+	return 0;
+}
+
+/**
+ * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ * @mask: mask of pipes to modeset
+ *
+ * Add pipes in @mask to @state and force a full modeset on the enabled ones
+ * due to the description in @reason.
+ * This function can be called only before new plane states are computed.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+				      const char *reason, u8 mask)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc *crtc;
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mask) {
+		struct intel_crtc_state *crtc_state;
+		int ret;
+
+		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		if (!crtc_state->hw.enable ||
+		    intel_crtc_needs_modeset(crtc_state))
+			continue;
+
+		ret = intel_modeset_pipe(state, crtc_state, reason);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * intel_modeset_all_pipes - force a full modeset on all pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ *
+ * Add all pipes to @state and force a full modeset on the active ones due to
+ * the description in @reason.
+ * This function can be called only after new plane states are computed already.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
 int intel_modeset_all_pipes(struct intel_atomic_state *state,
 			    const char *reason)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc *crtc;
 
-	/*
-	 * Add all pipes to the state, and force
-	 * a modeset on all the active ones.
-	 */
 	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		struct intel_crtc_state *crtc_state;
 		int ret;
@@ -5429,25 +5503,11 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 		    intel_crtc_needs_modeset(crtc_state))
 			continue;
 
-		drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
-			    crtc->base.base.id, crtc->base.name, reason);
+		ret = intel_modeset_pipe(state, crtc_state, reason);
+		if (ret)
+			return ret;
 
-		crtc_state->uapi.mode_changed = true;
 		crtc_state->update_pipe = false;
-
-		ret = drm_atomic_add_affected_connectors(&state->base,
-							 &crtc->base);
-		if (ret)
-			return ret;
-
-		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
-		if (ret)
-			return ret;
-
-		ret = intel_atomic_add_affected_planes(state, crtc);
-		if (ret)
-			return ret;
-
 		crtc_state->update_planes |= crtc_state->active_planes;
 		crtc_state->async_flip_planes = 0;
 		crtc_state->do_async_flip = false;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 49ac8473b988b..3008e8b2b437e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -513,6 +513,8 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
 void intel_update_watermarks(struct drm_i915_private *i915);
 
 /* modesetting */
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+				      const char *reason, u8 pipe_mask);
 int intel_modeset_all_pipes(struct intel_atomic_state *state,
 			    const char *reason);
 void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
-- 
2.37.2


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

* [Intel-gfx] [PATCH v5 07/25] drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 07/25] drm/i915: During modeset forcing handle inactive but enabled pipes Imre Deak
@ 2023-09-18 18:25   ` Imre Deak
  2023-09-19 14:26     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-18 18:25 UTC (permalink / raw)
  To: intel-gfx

Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late() to
clarify when the function can be called (vs.
intel_modeset_pipes_in_mask_early()).

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_cdclk.c   | 2 +-
 drivers/gpu/drm/i915/display/intel_display.c | 6 +++---
 drivers/gpu/drm/i915/display/intel_display.h | 4 ++--
 drivers/gpu/drm/i915/display/skl_watermark.c | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index ad5251ba6fe13..a2e20b25d6361 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -3139,7 +3139,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
 	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
 					     &new_cdclk_state->actual)) {
 		/* All pipes must be switched off while we change the cdclk. */
-		ret = intel_modeset_all_pipes(state, "CDCLK change");
+		ret = intel_modeset_all_pipes_late(state, "CDCLK change");
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 1c9a128f4af27..9a69b8848fee6 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5475,7 +5475,7 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
 }
 
 /**
- * intel_modeset_all_pipes - force a full modeset on all pipes
+ * intel_modeset_all_pipes_late - force a full modeset on all pipes
  * @state: intel atomic state
  * @reason: the reason for the full modeset
  *
@@ -5485,8 +5485,8 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
  *
  * Returns 0 in case of success, negative error code otherwise.
  */
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason)
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+				 const char *reason)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct intel_crtc *crtc;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 3008e8b2b437e..64a5be7859331 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -515,8 +515,8 @@ void intel_update_watermarks(struct drm_i915_private *i915);
 /* modesetting */
 int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
 				      const char *reason, u8 pipe_mask);
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason);
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+				 const char *reason);
 void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
 					  struct intel_power_domain_mask *old_domains);
 void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 063929a42a42f..a29d9b717deed 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2616,7 +2616,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
 
 		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
 			/* TODO: Implement vblank synchronized MBUS joining changes */
-			ret = intel_modeset_all_pipes(state, "MBUS joining change");
+			ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
 			if (ret)
 				return ret;
 		}
-- 
2.37.2


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

* [Intel-gfx] [PATCH v5 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-15  0:33   ` [Intel-gfx] [PATCH v4 " Imre Deak
  2023-09-15 19:11     ` Ville Syrjälä
@ 2023-09-18 18:25     ` Imre Deak
  2023-09-19 15:21       ` Ville Syrjälä
  1 sibling, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-18 18:25 UTC (permalink / raw)
  To: intel-gfx

At the moment a modeset fails if the config computation of a pipe can't
fit its required BW to the available link BW even though the limitation
may be resolved by reducing the BW requirement of other pipes.

To improve the above this patch adds helper functions checking the
overall BW limits after all CRTC states have been computed. If the check
fails the maximum link bpp for a selected pipe will be reduced and all
the CRTC states will be recomputed until either the overall BW limit
check passes, or further bpp reduction is not possible (because all
pipes/encoders sharing the link BW reached their minimum link bpp).

Atm, the MST encoder allocates twice the required BW for YUV420 format
streams. A follow-up patchset will fix that, add a code comment about
this.

This change prepares for upcoming patches enabling the above BW
management on FDI and MST links.

v2:
- Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
  intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
v3:
- Add the helper functions in a separate patch. (Ville)
- Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
- Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
  limit failure.
v4:
- Make intel_atomic_check_config() static.
v5: (Ville)
- Rename intel_link_bw_limits::min_bpp_pipes to min_bpp_reached_pipes
  and intel_link_bw_reset_pipe_limit_to_min() to
  intel_link_bw_set_min_bpp_for_pipe().
- Rename pipe_bpp to link_bpp in intel_link_bw_reduce_bpp().
- Add FIXME: comment about MST encoder's YUV420 BW allocation and
  tracking the link bpp limit accordingly.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  65 ++++-
 .../drm/i915/display/intel_display_types.h    |   3 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   4 +
 drivers/gpu/drm/i915/display/intel_link_bw.c  | 232 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
 7 files changed, 339 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1b2e02e9d92cb..de4967c141f00 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -268,6 +268,7 @@ i915-y += \
 	display/intel_hotplug.o \
 	display/intel_hotplug_irq.o \
 	display/intel_hti.o \
+	display/intel_link_bw.o \
 	display/intel_load_detect.o \
 	display/intel_lpe_audio.o \
 	display/intel_modeset_lock.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 182c6dd64f47c..1eda6a9f19aa8 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
 	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
 	crtc_state->scaler_state.scaler_id = -1;
 	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+	crtc_state->max_link_bpp_x16 = INT_MAX;
 }
 
 static struct intel_crtc *intel_crtc_alloc(void)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 3bdc338a22e19..537884035304c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -87,6 +87,7 @@
 #include "intel_frontbuffer.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_modeset_setup.h"
@@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
 
 static int
 intel_modeset_pipe_config(struct intel_atomic_state *state,
-			  struct intel_crtc *crtc)
+			  struct intel_crtc *crtc,
+			  const struct intel_link_bw_limits *limits)
 {
 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
 	struct intel_crtc_state *crtc_state =
@@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
+
+	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
+		drm_dbg_kms(&i915->drm,
+			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
+			    crtc->base.base.id, crtc->base.name,
+			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+	}
+
 	base_bpp = crtc_state->pipe_bpp;
 
 	/*
@@ -6218,7 +6229,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 	return 0;
 }
 
-static int intel_atomic_check_config(struct intel_atomic_state *state)
+static int intel_atomic_check_config(struct intel_atomic_state *state,
+				     struct intel_link_bw_limits *limits,
+				     enum pipe *failed_pipe)
 {
 	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct intel_crtc_state *new_crtc_state;
@@ -6226,6 +6239,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 	int ret;
 	int i;
 
+	*failed_pipe = INVALID_PIPE;
+
 	ret = intel_bigjoiner_add_affected_crtcs(state);
 	if (ret)
 		return ret;
@@ -6251,7 +6266,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 		if (!new_crtc_state->hw.enable)
 			continue;
 
-		ret = intel_modeset_pipe_config(state, crtc);
+		ret = intel_modeset_pipe_config(state, crtc, limits);
 		if (ret)
 			break;
 
@@ -6260,9 +6275,51 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
 			break;
 	}
 
+	if (ret)
+		*failed_pipe = crtc->pipe;
+
 	return ret;
 }
 
+static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits new_limits;
+	struct intel_link_bw_limits old_limits;
+	int ret;
+
+	intel_link_bw_init_limits(i915, &new_limits);
+	old_limits = new_limits;
+
+	while (true) {
+		enum pipe failed_pipe;
+
+		ret = intel_atomic_check_config(state, &new_limits,
+						&failed_pipe);
+		if (ret) {
+			/*
+			 * The bpp limit for a pipe is below the minimum it supports, set the
+			 * limit to the minimum and recalculate the config.
+			 */
+			if (ret == -EINVAL &&
+			    intel_link_bw_set_min_bpp_for_pipe(state,
+							       &old_limits,
+							       &new_limits,
+							       failed_pipe))
+				continue;
+
+			break;
+		}
+
+		old_limits = new_limits;
+
+		ret = intel_link_bw_atomic_check(state, &new_limits);
+		if (ret != -EAGAIN)
+			break;
+	}
+
+	return ret;
+}
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -6307,7 +6364,7 @@ int intel_atomic_check(struct drm_device *dev,
 			return ret;
 	}
 
-	ret = intel_atomic_check_config(state);
+	ret = intel_atomic_check_config_and_link(state);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 50a22261f5eec..4d7948fa4bbba 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1189,7 +1189,8 @@ struct intel_crtc_state {
 		u32 ctrl, div;
 	} dsi_pll;
 
-	int pipe_bpp;
+	int max_link_bpp_x16;	/* in 1/16 bpp units */
+	int pipe_bpp;		/* in 1 bpp units */
 	struct intel_link_m_n dp_m_n;
 
 	/* m2_n2 for eDP downclock */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index a914d83ab3dde..f26c2eecb2778 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -157,6 +157,10 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
 	int slots = -EINVAL;
 	int link_bpp;
 
+	/*
+	 * FIXME: allocate the BW according to link_bpp, which in the case of
+	 * YUV420 is only half of the pipe bpp value.
+	 */
 	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
 						     to_bpp_int(limits->link.max_bpp_x16),
 						     to_bpp_int(limits->link.min_bpp_x16),
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
new file mode 100644
index 0000000000000..9b6d0891345d7
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+
+#include "intel_atomic.h"
+#include "intel_display_types.h"
+#include "intel_dp_mst.h"
+#include "intel_fdi.h"
+#include "intel_link_bw.h"
+
+/**
+ * intel_link_bw_init_limits - initialize BW limits
+ * @i915: device instance
+ * @limits: link BW limits
+ *
+ * Initialize @limits.
+ */
+void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
+{
+	enum pipe pipe;
+
+	limits->min_bpp_reached_pipes = 0;
+	for_each_pipe(i915, pipe)
+		limits->max_bpp_x16[pipe] = INT_MAX;
+}
+
+/**
+ * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
+ * @crtc_state: the crtc state
+ *
+ * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
+ * call this function during state computation in the simple case where the
+ * link bpp will always match the pipe bpp. This is the case for all non-DP
+ * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
+ * of DSC compression.
+ *
+ * Returns %true in case of success, %false if pipe bpp would need to be
+ * reduced below its valid range.
+ */
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
+{
+	int pipe_bpp = min(crtc_state->pipe_bpp,
+			   to_bpp_int(crtc_state->max_link_bpp_x16));
+
+	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
+
+	if (pipe_bpp < 6 * 3)
+		return false;
+
+	crtc_state->pipe_bpp = pipe_bpp;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
+ * @state: atomic state
+ * @limits: link BW limits
+ * @pipe_mask: mask of pipes to select from
+ * @reason: explanation of why bpp reduction is needed
+ *
+ * Select the pipe from @pipe_mask with the biggest link bpp value and set the
+ * maximum of link bpp in @limits below this value. Modeset the selected pipe,
+ * so that its state will get recomputed.
+ *
+ * This function can be called to resolve a link's BW overallocation by reducing
+ * the link bpp of one pipe on the link and hence reducing the total link BW.
+ *
+ * Returns
+ *   - 0 in case of success
+ *   - %-ENOSPC if no pipe can further reduce its link bpp
+ *   - Other negative error, if modesetting the selected pipe failed
+ */
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	enum pipe max_bpp_pipe = INVALID_PIPE;
+	struct intel_crtc *crtc;
+	int max_bpp = 0;
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
+		struct intel_crtc_state *crtc_state;
+		int link_bpp;
+
+		if (limits->min_bpp_reached_pipes & BIT(crtc->pipe))
+			continue;
+
+		crtc_state = intel_atomic_get_crtc_state(&state->base,
+							 crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		if (crtc_state->dsc.compression_enable)
+			link_bpp = crtc_state->dsc.compressed_bpp;
+		else
+			/*
+			 * TODO: for YUV420 the actual link bpp is only half
+			 * of the pipe bpp value. The MST encoder's BW allocation
+			 * is based on the pipe bpp value, set the actual link bpp
+			 * limit here once the MST BW allocation is fixed.
+			 */
+			link_bpp = crtc_state->pipe_bpp;
+
+		if (link_bpp > max_bpp) {
+			max_bpp = link_bpp;
+			max_bpp_pipe = crtc->pipe;
+		}
+	}
+
+	if (max_bpp_pipe == INVALID_PIPE)
+		return -ENOSPC;
+
+	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
+
+	return intel_modeset_pipes_in_mask_early(state, reason,
+						 BIT(max_bpp_pipe));
+}
+
+/**
+ * intel_link_bw_set_min_bpp_for_pipe - set link bpp limit for a pipe to its minimum
+ * @state: atomic state
+ * @old_limits: link BW limits
+ * @new_limits: link BW limits
+ * @pipe: pipe
+ *
+ * Set the link bpp limit for @pipe in @new_limits to its value in
+ * @old_limits and mark this limit as the minimum. This function must be
+ * called after a pipe's compute config function failed, @old_limits
+ * containing the bpp limit with which compute config previously passed.
+ *
+ * The function will fail if setting a minimum is not possible, either
+ * because the old and new limits match (and so would lead to a pipe compute
+ * config failure) or the limit is already at the minimum.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
+				   const struct intel_link_bw_limits *old_limits,
+				   struct intel_link_bw_limits *new_limits,
+				   enum pipe pipe)
+{
+	if (pipe == INVALID_PIPE)
+		return false;
+
+	if (new_limits->min_bpp_reached_pipes & BIT(pipe))
+		return false;
+
+	if (new_limits->max_bpp_x16[pipe] ==
+	    old_limits->max_bpp_x16[pipe])
+		return false;
+
+	new_limits->max_bpp_x16[pipe] =
+		old_limits->max_bpp_x16[pipe];
+	new_limits->min_bpp_reached_pipes |= BIT(pipe);
+
+	return true;
+}
+
+static int check_all_link_config(struct intel_atomic_state *state,
+				 struct intel_link_bw_limits *limits)
+{
+	/* TODO: Check all shared display link configurations like FDI */
+	return 0;
+}
+
+static bool
+assert_link_limit_change_valid(struct drm_i915_private *i915,
+			       const struct intel_link_bw_limits *old_limits,
+			       const struct intel_link_bw_limits *new_limits)
+{
+	bool bpps_changed = false;
+	enum pipe pipe;
+
+	for_each_pipe(i915, pipe) {
+		/* The bpp limit can only decrease. */
+		if (drm_WARN_ON(&i915->drm,
+				new_limits->max_bpp_x16[pipe] >
+				old_limits->max_bpp_x16[pipe]))
+			return false;
+
+		if (new_limits->max_bpp_x16[pipe] <
+		    old_limits->max_bpp_x16[pipe])
+			bpps_changed = true;
+	}
+
+	/* At least one limit must change. */
+	if (drm_WARN_ON(&i915->drm,
+			!bpps_changed))
+		return false;
+
+	return true;
+}
+
+/**
+ * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
+ * @state: atomic state
+ * @new_limits: link BW limits
+ *
+ * Check the configuration of all shared display links in @state and set new BW
+ * limits in @new_limits if there is a BW limitation.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
+ *     with fallback values with which the configuration of all CRTCs
+ *     in @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_link_bw_limits old_limits = *new_limits;
+	int ret;
+
+	ret = check_all_link_config(state, new_limits);
+	if (ret != -EAGAIN)
+		return ret;
+
+	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
+		return -EINVAL;
+
+	return -EAGAIN;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
new file mode 100644
index 0000000000000..0f666c9712f3c
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_LINK_BW_H__
+#define __INTEL_LINK_BW_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+struct drm_i915_private;
+
+struct intel_atomic_state;
+struct intel_crtc_state;
+
+struct intel_link_bw_limits {
+	u8 min_bpp_reached_pipes;
+	/* in 1/16 bpp units */
+	int max_bpp_x16[I915_MAX_PIPES];
+};
+
+void intel_link_bw_init_limits(struct drm_i915_private *i915,
+			       struct intel_link_bw_limits *limits);
+bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+			     struct intel_link_bw_limits *limits,
+			     u8 pipe_mask,
+			     const char *reason);
+bool intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
+					const struct intel_link_bw_limits *old_limits,
+					struct intel_link_bw_limits *new_limits,
+					enum pipe pipe);
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+			       struct intel_link_bw_limits *new_limits);
+
+#endif
-- 
2.37.2


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

* [Intel-gfx] [PATCH v5 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C Imre Deak
  2023-09-15 19:31   ` Ville Syrjälä
@ 2023-09-18 18:25   ` Imre Deak
  1 sibling, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-18 18:25 UTC (permalink / raw)
  To: intel-gfx

At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
link bpp in this case, until pipe B uses only up to 2 FDI lanes.

For this instead of the encoder compute config retry loop - which
reduced link bpp only for the encoder's pipe - reduce the maximum link
bpp for pipe B/C as required after all CRTC states are computed and
recompute the CRTC states with the new bpp limit.

Atm, all FDI encoder's compute config function returns an error if a BW
constrain prevents increasing the pipe bpp value. SDVO is an exception
where this case is only handled in the outer config retry loop, failing
the modeset. For consistency handle this case already during compute
config similarly to the other encoders.

v2:
- Don't assume that a CRTC is already in the atomic state, while
  reducing its link bpp.
- Add DocBook description to intel_fdi_atomic_check_link().
v3:
- Enable BW management for FDI links in a separate patch. (Ville)
v4: (Ville)
- Fail the SDVO encoder config computation if it doesn't support the
  link bpp limit.
- Add TODO: comments about checking link_bpp_x16 instead of
  bw_constrained.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
 drivers/gpu/drm/i915/display/intel_crt.c     |  8 ++
 drivers/gpu/drm/i915/display/intel_display.c | 14 +---
 drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
 drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
 drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
 drivers/gpu/drm/i915/display/intel_lvds.c    | 11 ++-
 drivers/gpu/drm/i915/display/intel_sdvo.c    | 14 +++-
 9 files changed, 113 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 634b14116d9dd..8b5d26cd3b85e 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -19,6 +19,7 @@
 #include "intel_fifo_underrun.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_sdvo.h"
 #include "vlv_sideband.h"
 
@@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
 
-	if (HAS_PCH_SPLIT(i915))
+	if (HAS_PCH_SPLIT(i915)) {
 		crtc_state->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
+			return -EINVAL;
+	}
 
 	if (IS_G4X(i915))
 		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 595e65f1c13aa..1745c860a3db3 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -49,6 +49,7 @@
 #include "intel_gmbus.h"
 #include "intel_hotplug.h"
 #include "intel_hotplug_irq.h"
+#include "intel_link_bw.h"
 #include "intel_load_detect.h"
 #include "intel_pch_display.h"
 #include "intel_pch_refclk.h"
@@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 
 	pipe_config->has_pch_encoder = true;
+	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+		return -EINVAL;
+
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
 	return 0;
@@ -435,10 +439,14 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 
 	pipe_config->has_pch_encoder = true;
+	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+		return -EINVAL;
+
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
 	/* LPT FDI RX only supports 8bpc. */
 	if (HAS_PCH_LPT(dev_priv)) {
+		/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
 		if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
 			drm_dbg_kms(&dev_priv->drm,
 				    "LPT only supports 24bpp\n");
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 537884035304c..a6656d6c985e6 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	struct drm_connector_state *connector_state;
 	int pipe_src_w, pipe_src_h;
 	int base_bpp, ret, i;
-	bool retry = true;
 
 	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
 
@@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
 			    crtc->base.base.id, crtc->base.name,
 			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+		crtc_state->bw_constrained = true;
 	}
 
 	base_bpp = crtc_state->pipe_bpp;
@@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 			crtc_state->output_types |= BIT(encoder->type);
 	}
 
-encoder_retry:
 	/* Ensure the port clock defaults are reset when retrying. */
 	crtc_state->port_clock = 0;
 	crtc_state->pixel_multiplier = 1;
@@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	ret = intel_crtc_compute_config(state, crtc);
 	if (ret == -EDEADLK)
 		return ret;
-	if (ret == -EAGAIN) {
-		if (drm_WARN(&i915->drm, !retry,
-			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
-			     crtc->base.base.id, crtc->base.name))
-			return -EINVAL;
-
-		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
-			    crtc->base.base.id, crtc->base.name);
-		retry = false;
-		goto encoder_retry;
-	}
 	if (ret < 0) {
 		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
 			    crtc->base.base.id, crtc->base.name, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 59761958832b1..338de1889a4bf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
 	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
 	int max_link_bpp_x16;
 
-	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
+			       to_bpp_x16(limits->pipe.max_bpp));
 
 	if (!dsc) {
 		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 4d7d524c68017..ad01915a4a39b 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -13,6 +13,7 @@
 #include "intel_display_types.h"
 #include "intel_fdi.h"
 #include "intel_fdi_regs.h"
+#include "intel_link_bw.h"
 
 struct intel_fdi_funcs {
 	void (*fdi_link_train)(struct intel_crtc *crtc,
@@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
 }
 
 static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
-			       struct intel_crtc_state *pipe_config)
+			       struct intel_crtc_state *pipe_config,
+			       enum pipe *pipe_to_reduce)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_atomic_state *state = pipe_config->uapi.state;
 	struct intel_crtc *other_crtc;
 	struct intel_crtc_state *other_crtc_state;
 
+	*pipe_to_reduce = pipe;
+
 	drm_dbg_kms(&dev_priv->drm,
 		    "checking fdi config on pipe %c, lanes %i\n",
 		    pipe_name(pipe), pipe_config->fdi_lanes);
@@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
 		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
 			drm_dbg_kms(&dev_priv->drm,
 				    "fdi link B uses too many lanes to enable link C\n");
+
+			*pipe_to_reduce = PIPE_B;
+
 			return -EINVAL;
 		}
 		return 0;
@@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *i915 = to_i915(dev);
 	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
-	int lane, link_bw, fdi_dotclock, ret;
-	bool needs_recompute = false;
+	int lane, link_bw, fdi_dotclock;
 
-retry:
 	/* FDI is a binary signal running at ~2.7GHz, encoding
 	 * each output octet as 10 bits. The actual frequency
 	 * is stored as a divider into a 100MHz clock, and the
@@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
 	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
 			       link_bw, &pipe_config->fdi_m_n, false);
 
-	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
-	if (ret == -EDEADLK)
+	return 0;
+}
+
+static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
+				     struct intel_crtc *crtc,
+				     struct intel_crtc_state *pipe_config,
+				     struct intel_link_bw_limits *limits)
+{
+	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	enum pipe pipe_to_reduce;
+	int ret;
+
+	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
+				  &pipe_to_reduce);
+	if (ret != -EINVAL)
 		return ret;
 
-	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
-		pipe_config->pipe_bpp -= 2*3;
-		drm_dbg_kms(&i915->drm,
-			    "fdi link bw constraint, reducing pipe bpp to %i\n",
-			    pipe_config->pipe_bpp);
-		needs_recompute = true;
-		pipe_config->bw_constrained = true;
-
-		goto retry;
+	ret = intel_link_bw_reduce_bpp(state, limits,
+				       BIT(pipe_to_reduce),
+				       "FDI link BW");
+
+	return ret ? : -EAGAIN;
+}
+
+/**
+ * intel_fdi_atomic_check_link - check all modeset FDI link configuration
+ * @state: intel atomic state
+ * @limits: link BW limits
+ *
+ * Check the link configuration for all modeset FDI outputs. If the
+ * configuration is invalid @limits will be updated if possible to
+ * reduce the total BW, after which the configuration for all CRTCs in
+ * @state must be recomputed with the updated @limits.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @limits got updated
+ *     with fallback values with which the configuration of all CRTCs
+ *     in @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+				struct intel_link_bw_limits *limits)
+{
+	struct intel_crtc *crtc;
+	struct intel_crtc_state *crtc_state;
+	int i;
+
+	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+		int ret;
+
+		if (!crtc_state->has_pch_encoder ||
+		    !intel_crtc_needs_modeset(crtc_state) ||
+		    !crtc_state->hw.enable)
+			continue;
+
+		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
+		if (ret)
+			return ret;
 	}
 
-	if (needs_recompute)
-		return -EAGAIN;
-
-	return ret;
+	return 0;
 }
 
 static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
index 1cdb86172702f..129444c580f27 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.h
+++ b/drivers/gpu/drm/i915/display/intel_fdi.h
@@ -8,14 +8,18 @@
 
 enum pipe;
 struct drm_i915_private;
+struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_encoder;
+struct intel_link_bw_limits;
 
 int intel_fdi_link_freq(struct drm_i915_private *i915,
 			const struct intel_crtc_state *pipe_config);
 int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
 			   struct intel_crtc_state *pipe_config);
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+				struct intel_link_bw_limits *limits);
 void intel_fdi_normal_train(struct intel_crtc *crtc);
 void ilk_fdi_disable(struct intel_crtc *crtc);
 void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 9b6d0891345d7..9d95e4a8478f7 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -166,7 +166,12 @@ intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
 static int check_all_link_config(struct intel_atomic_state *state,
 				 struct intel_link_bw_limits *limits)
 {
-	/* TODO: Check all shared display link configurations like FDI */
+	int ret;
+
+	ret = intel_fdi_atomic_check_link(state, limits);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 2306e133e3f60..f46e8ad12ec1f 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -48,6 +48,7 @@
 #include "intel_dpll.h"
 #include "intel_fdi.h"
 #include "intel_gmbus.h"
+#include "intel_link_bw.h"
 #include "intel_lvds.h"
 #include "intel_lvds_regs.h"
 #include "intel_panel.h"
@@ -425,11 +426,18 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
 		return -EINVAL;
 	}
 
+	if (HAS_PCH_SPLIT(i915)) {
+		crtc_state->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
+			return -EINVAL;
+	}
+
 	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
 		lvds_bpp = 8*3;
 	else
 		lvds_bpp = 6*3;
 
+	/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
 	if (lvds_bpp != crtc_state->pipe_bpp && !crtc_state->bw_constrained) {
 		drm_dbg_kms(&i915->drm,
 			    "forcing display bpp (was %d) to LVDS (%d)\n",
@@ -453,9 +461,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
-	if (HAS_PCH_SPLIT(i915))
-		crtc_state->has_pch_encoder = true;
-
 	ret = intel_panel_fitting(crtc_state, conn_state);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 881bbbb8513f4..fd273b0a6464d 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -48,6 +48,7 @@
 #include "intel_gmbus.h"
 #include "intel_hdmi.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_panel.h"
 #include "intel_sdvo.h"
 #include "intel_sdvo_regs.h"
@@ -1351,14 +1352,21 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct drm_display_mode *mode = &pipe_config->hw.mode;
 
+	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
+		pipe_config->has_pch_encoder = true;
+		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
+			return -EINVAL;
+	}
+
 	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
+
+	if (pipe_config->max_link_bpp_x16 < to_bpp_x16(8 * 3))
+		return -EINVAL;
+
 	pipe_config->pipe_bpp = 8*3;
 	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
-	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
-		pipe_config->has_pch_encoder = true;
-
 	/*
 	 * We need to construct preferred input timings based on our
 	 * output timings.  To do that, we have to set the output
-- 
2.37.2


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

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev9)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (29 preceding siblings ...)
  2023-09-15 12:39 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
@ 2023-09-19  1:11 ` Patchwork
  2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev10) Patchwork
                   ` (2 subsequent siblings)
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-19  1:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev9)
URL   : https://patchwork.freedesktop.org/series/122589/
State : failure

== Summary ==

Error: patch https://patchwork.freedesktop.org/api/1.0/series/122589/revisions/9/mbox/ not applied
Applying: drm/i915/dp: Factor out helpers to compute the link limits
Applying: drm/i915/dp: Track the pipe and link bpp limits separately
Applying: drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
Applying: drm/i915/dp: Update the link bpp limits for DSC mode
Applying: drm/i915/dp: Limit the output link bpp in DSC mode
Applying: drm/i915: Add helper to modeset a set of pipes
Applying: drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
Applying: drm/i915: Factor out a helper to check/compute all the CRTC states
Applying: drm/i915: Add helpers for BW management on shared display links
Applying: drm/i915/fdi: Improve FDI BW sharing between pipe B and C
Applying: drm/i915/fdi: Recompute state for affected CRTCs on FDI links
Applying: drm/dp_mst: Fix fractional DSC bpp handling
Applying: drm/dp_mst: Add a way to calculate PBN values with FEC overhead
Applying: drm/dp_mst: Add helper to determine if an MST port is downstream of another port
Applying: drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
Applying: drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
Applying: drm/i915/dp_mst: Fix PBN calculation with FEC overhead
Applying: drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
Applying: drm/i915/dp_mst: Program the DSC PPS SDP for each stream
Applying: drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
Applying: drm/i915/dp_mst: Enable DSC decompression if any stream needs this
Applying: drm/i915/dp_mst: Add missing DSC compression disabling
Applying: drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
Applying: drm/i915/dp_mst: Improve BW sharing between MST streams
error: sha1 information is lacking or useless (drivers/gpu/drm/i915/display/intel_display.c).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0024 drm/i915/dp_mst: Improve BW sharing between MST streams
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Build failed, no error log produced



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

* [Intel-gfx] [PATCH v5 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams Imre Deak
@ 2023-09-19 10:52   ` Imre Deak
  2023-09-25  7:42     ` Lisovskiy, Stanislav
  0 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-19 10:52 UTC (permalink / raw)
  To: intel-gfx

At the moment modesetting a stream CRTC will fail if the stream's BW
along with the current BW of all the other streams on the same MST link
is above the total BW of the MST link. Make the BW sharing more dynamic
by trying to reduce the link bpp of one or more streams on the MST link
in this case.

When selecting a stream to reduce the BW for, take into account which
link segment in the MST topology ran out of BW and which streams go
through this link segment. For instance with A,B,C streams in the same
MST topology A and B may share the BW of a link segment downstream of a
branch device, stream C not downstream of the branch device, hence not
affecting this BW. If this link segment's BW runs out one or both of
stream A/B's BW will be reduced until their total BW is within limits.

While reducing the link bpp for a given stream DSC may need to be
enabled for it, which requires FEC on the whole MST link. Check for this
condition and recompute the state for all streams taking the FEC
overhead into account (on 8b/10b links).

v2:
- Rebase on s/min_bpp_pipes/min_bpp_reached_pipes/ change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |   5 +-
 drivers/gpu/drm/i915/display/intel_dp.c      |  13 +-
 drivers/gpu/drm/i915/display/intel_dp.h      |   2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 129 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h  |   3 +
 drivers/gpu/drm/i915/display/intel_link_bw.c |  15 ++-
 drivers/gpu/drm/i915/display/intel_link_bw.h |   1 +
 7 files changed, 159 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 8af22cf9a49de..565a6f20ffbfd 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4629,6 +4629,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe);
 	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
 
 	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
@@ -6435,10 +6436,6 @@ int intel_atomic_check(struct drm_device *dev,
 		goto fail;
 	}
 
-	ret = drm_dp_mst_atomic_check(&state->base);
-	if (ret)
-		goto fail;
-
 	ret = intel_atomic_check_planes(state);
 	if (ret)
 		goto fail;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 3d2ede31aa4e8..9b5070d8c8984 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1369,8 +1369,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
 	return false;
 }
 
-static bool intel_dp_supports_fec(struct intel_dp *intel_dp,
-				  const struct intel_crtc_state *pipe_config)
+bool intel_dp_supports_fec(struct intel_dp *intel_dp,
+			   const struct intel_crtc_state *pipe_config)
 {
 	return intel_dp_source_supports_fec(intel_dp, pipe_config) &&
 		drm_dp_sink_supports_fec(intel_dp->fec_capable);
@@ -2111,8 +2111,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 		&pipe_config->hw.adjusted_mode;
 	int ret;
 
-	pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
-		intel_dp_supports_fec(intel_dp, pipe_config);
+	pipe_config->fec_enable = pipe_config->fec_enable ||
+		(!intel_dp_is_edp(intel_dp) &&
+		 intel_dp_supports_fec(intel_dp, pipe_config));
 
 	if (!intel_dp_supports_dsc(intel_dp, pipe_config))
 		return -EINVAL;
@@ -2308,6 +2309,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	bool dsc_needed;
 	int ret = 0;
 
+	if (pipe_config->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, pipe_config))
+		return -EINVAL;
+
 	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
 				    adjusted_mode->crtc_clock))
 		pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 2cf3681bac64a..612105a303419 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -135,6 +135,8 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
 	return ~((1 << lane_count) - 1) & 0xf;
 }
 
+bool intel_dp_supports_fec(struct intel_dp *intel_dp,
+			   const struct intel_crtc_state *pipe_config);
 u32 intel_dp_mode_to_fec_clock(u32 mode_clock);
 u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 9681708acaa1a..ce69122fb4e54 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -43,6 +43,7 @@
 #include "intel_dpio_phy.h"
 #include "intel_hdcp.h"
 #include "intel_hotplug.h"
+#include "intel_link_bw.h"
 #include "intel_vdsc.h"
 #include "skl_scaler.h"
 
@@ -373,6 +374,10 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	bool dsc_needed;
 	int ret = 0;
 
+	if (pipe_config->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, pipe_config))
+		return -EINVAL;
+
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
@@ -492,6 +497,130 @@ intel_dp_mst_transcoder_mask(struct intel_atomic_state *state,
 	return transcoders;
 }
 
+static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
+					   struct drm_dp_mst_topology_mgr *mst_mgr,
+					   struct drm_dp_mst_port *parent_port)
+{
+	const struct intel_digital_connector_state *conn_state;
+	struct intel_connector *connector;
+	u8 mask = 0;
+	int i;
+
+	for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
+		if (!conn_state->base.crtc)
+			continue;
+
+		if (&connector->mst_port->mst_mgr != mst_mgr)
+			continue;
+
+		if (connector->port != parent_port &&
+		    !drm_dp_mst_port_downstream_of_parent(mst_mgr,
+							  connector->port,
+							  parent_port))
+			continue;
+
+		mask |= BIT(to_intel_crtc(conn_state->base.crtc)->pipe);
+	}
+
+	return mask;
+}
+
+static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
+					 struct drm_dp_mst_topology_mgr *mst_mgr,
+					 struct intel_link_bw_limits *limits)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc *crtc;
+	u8 mst_pipe_mask;
+	u8 fec_pipe_mask = 0;
+	int ret;
+
+	mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
+
+	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mst_pipe_mask) {
+		struct intel_crtc_state *crtc_state =
+			intel_atomic_get_new_crtc_state(state, crtc);
+
+		/* Atomic connector check should've added all the MST CRTCs. */
+		if (drm_WARN_ON(&i915->drm, !crtc_state))
+			return -EINVAL;
+
+		if (crtc_state->fec_enable)
+			fec_pipe_mask |= BIT(crtc->pipe);
+	}
+
+	if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask)
+		return 0;
+
+	limits->force_fec_pipes |= mst_pipe_mask;
+
+	ret = intel_modeset_pipes_in_mask_early(state, "MST FEC",
+						mst_pipe_mask);
+
+	return ret ? : -EAGAIN;
+}
+
+static int intel_dp_mst_check_bw(struct intel_atomic_state *state,
+				 struct drm_dp_mst_topology_mgr *mst_mgr,
+				 struct drm_dp_mst_topology_state *mst_state,
+				 struct intel_link_bw_limits *limits)
+{
+	struct drm_dp_mst_port *mst_port;
+	u8 mst_port_pipes;
+	int ret;
+
+	ret = drm_dp_mst_atomic_check_mgr(&state->base, mst_mgr, mst_state, &mst_port);
+	if (ret != -ENOSPC)
+		return ret;
+
+	mst_port_pipes = get_pipes_downstream_of_mst_port(state, mst_mgr, mst_port);
+
+	ret = intel_link_bw_reduce_bpp(state, limits,
+				       mst_port_pipes, "MST link BW");
+
+	return ret ? : -EAGAIN;
+}
+
+/**
+ * intel_dp_mst_atomic_check_link - check all modeset MST link configuration
+ * @state: intel atomic state
+ * @limits: link BW limits
+ *
+ * Check the link configuration for all modeset MST outputs. If the
+ * configuration is invalid @limits will be updated if possible to
+ * reduce the total BW, after which the configuration for all CRTCs in
+ * @state must be recomputed with the updated @limits.
+ *
+ * Returns:
+ *   - 0 if the confugration is valid
+ *   - %-EAGAIN, if the configuration is invalid and @limits got updated
+ *     with fallback values with which the configuration of all CRTCs in
+ *     @state must be recomputed
+ *   - Other negative error, if the configuration is invalid without a
+ *     fallback possibility, or the check failed for another reason
+ */
+int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
+				   struct intel_link_bw_limits *limits)
+{
+	struct drm_dp_mst_topology_mgr *mgr;
+	struct drm_dp_mst_topology_state *mst_state;
+	int ret;
+	int i;
+
+	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
+		ret = intel_dp_mst_check_fec_change(state, mgr, limits);
+		if (ret)
+			return ret;
+
+		ret = intel_dp_mst_check_bw(state, mgr, mst_state,
+					    limits);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int intel_dp_mst_compute_config_late(struct intel_encoder *encoder,
 					    struct intel_crtc_state *crtc_state,
 					    struct drm_connector_state *conn_state)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index f1815bb722672..4e836b9ac6061 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -13,6 +13,7 @@ struct intel_crtc;
 struct intel_crtc_state;
 struct intel_digital_port;
 struct intel_dp;
+struct intel_link_bw_limits;
 
 int intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port);
@@ -22,5 +23,7 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
 int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 					     struct intel_crtc *crtc);
+int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
+				   struct intel_link_bw_limits *limits);
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
index 9d95e4a8478f7..85ceae2a5aaf1 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -22,6 +22,7 @@ void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_
 {
 	enum pipe pipe;
 
+	limits->force_fec_pipes = 0;
 	limits->min_bpp_reached_pipes = 0;
 	for_each_pipe(i915, pipe)
 		limits->max_bpp_x16[pipe] = INT_MAX;
@@ -168,6 +169,10 @@ static int check_all_link_config(struct intel_atomic_state *state,
 {
 	int ret;
 
+	ret = intel_dp_mst_atomic_check_link(state, limits);
+	if (ret)
+		return ret;
+
 	ret = intel_fdi_atomic_check_link(state, limits);
 	if (ret)
 		return ret;
@@ -183,6 +188,12 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
 	bool bpps_changed = false;
 	enum pipe pipe;
 
+	/* FEC can't be forced off after it was forced on. */
+	if (drm_WARN_ON(&i915->drm,
+			(old_limits->force_fec_pipes & new_limits->force_fec_pipes) !=
+			old_limits->force_fec_pipes))
+		return false;
+
 	for_each_pipe(i915, pipe) {
 		/* The bpp limit can only decrease. */
 		if (drm_WARN_ON(&i915->drm,
@@ -197,7 +208,9 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
 
 	/* At least one limit must change. */
 	if (drm_WARN_ON(&i915->drm,
-			!bpps_changed))
+			!bpps_changed &&
+			new_limits->force_fec_pipes ==
+			old_limits->force_fec_pipes))
 		return false;
 
 	return true;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
index 0f666c9712f3c..33b9a338beeb6 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -16,6 +16,7 @@ struct intel_atomic_state;
 struct intel_crtc_state;
 
 struct intel_link_bw_limits {
+	u8 force_fec_pipes;
 	u8 min_bpp_reached_pipes;
 	/* in 1/16 bpp units */
 	int max_bpp_x16[I915_MAX_PIPES];
-- 
2.37.2


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev10)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (30 preceding siblings ...)
  2023-09-19  1:11 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev9) Patchwork
@ 2023-09-19 11:38 ` Patchwork
  2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
  2023-09-19 11:55 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-19 11:38 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev10)
URL   : https://patchwork.freedesktop.org/series/122589/
State : warning

== Summary ==

Error: dim checkpatch failed
0e769abe103a drm/i915/dp: Factor out helpers to compute the link limits
-:122: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#122: FILE: drivers/gpu/drm/i915/display/intel_dp_mst.c:305:
+	limits->min_rate = limits->max_rate =

-:125: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#125: FILE: drivers/gpu/drm/i915/display/intel_dp_mst.c:308:
+	limits->min_lane_count = limits->max_lane_count =

total: 0 errors, 0 warnings, 2 checks, 147 lines checked
1525f98fbe12 drm/i915/dp: Track the pipe and link bpp limits separately
-:49: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#49: FILE: drivers/gpu/drm/i915/display/intel_dp.c:1473:
+		limits->pipe.min_bpp = limits->pipe.max_bpp = bpp;

-:106: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#106: FILE: drivers/gpu/drm/i915/display/intel_dp.c:2211:
+	limits->pipe.max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
+						     respect_downstream_limits);

total: 0 errors, 0 warnings, 2 checks, 146 lines checked
1416f13a8059 drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
0f6491c4f5d1 drm/i915/dp: Update the link bpp limits for DSC mode
-:42: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#42: FILE: drivers/gpu/drm/i915/display/intel_display_types.h:2123:
+#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)

-:42: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'bpp_x16' - possible side-effects?
#42: FILE: drivers/gpu/drm/i915/display/intel_display_types.h:2123:
+#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)

-:102: WARNING:LONG_LINE: line length of 164 exceeds 100 columns
#102: FILE: drivers/gpu/drm/i915/display/intel_dp.c:2239:
+		    "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",

total: 1 errors, 1 warnings, 1 checks, 201 lines checked
839860a573d8 drm/i915/dp: Limit the output link bpp in DSC mode
689a28deb22c drm/i915: Add helper to modeset a set of pipes
acfb411e320f drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
ec1406d466a8 drm/i915: Factor out a helper to check/compute all the CRTC states
6e1d98550ce4 drm/i915: Add helpers for BW management on shared display links
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
-:232: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#232: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 419 lines checked
700d5cceef18 drm/i915/fdi: Improve FDI BW sharing between pipe B and C
59191742c173 drm/i915/fdi: Recompute state for affected CRTCs on FDI links
9d9701a8f56a drm/dp_mst: Fix fractional DSC bpp handling
817d92348eb9 drm/dp_mst: Add a way to calculate PBN values with FEC overhead
a91522685352 drm/dp_mst: Add helper to determine if an MST port is downstream of another port
81f7101e39b5 drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
58bf9b9347e9 drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
2ca95c87c30d drm/i915/dp_mst: Fix PBN calculation with FEC overhead
80ec3153a9a7 drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
06742b5c7c2e drm/i915/dp_mst: Program the DSC PPS SDP for each stream
1fea76ef43d3 drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
b6af7d5578b3 drm/i915/dp_mst: Enable DSC decompression if any stream needs this
612154343be9 drm/i915/dp_mst: Add missing DSC compression disabling
2dacce68ab64 drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
3a5e55eb4bc7 drm/i915/dp_mst: Improve BW sharing between MST streams
4592c30e1159 drm/i915/dp_mst: Check BW limitations only after all streams are computed



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Improve BW management on shared display links (rev10)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (31 preceding siblings ...)
  2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev10) Patchwork
@ 2023-09-19 11:38 ` Patchwork
  2023-09-19 11:55 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
  33 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2023-09-19 11:38 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev10)
URL   : https://patchwork.freedesktop.org/series/122589/
State : warning

== Summary ==

Error: dim sparse failed
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✗ Fi.CI.BAT: failure for drm/i915: Improve BW management on shared display links (rev10)
  2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
                   ` (32 preceding siblings ...)
  2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2023-09-19 11:55 ` Patchwork
  2023-09-19 13:29   ` Imre Deak
  33 siblings, 1 reply; 72+ messages in thread
From: Patchwork @ 2023-09-19 11:55 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 7277 bytes --]

== Series Details ==

Series: drm/i915: Improve BW management on shared display links (rev10)
URL   : https://patchwork.freedesktop.org/series/122589/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_13651 -> Patchwork_122589v10
====================================================

Summary
-------

  **FAILURE**

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

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

Participating hosts (38 -> 37)
------------------------------

  Additional (2): fi-kbl-soraka bat-rpls-2 
  Missing    (3): fi-tgl-1115g4 bat-atsm-1 fi-snb-2520m 

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@i915_module_load@load:
    - bat-mtlp-8:         [PASS][1] -> [INCOMPLETE][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/bat-mtlp-8/igt@i915_module_load@load.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-mtlp-8/igt@i915_module_load@load.html

  * igt@runner@aborted:
    - bat-rpls-2:         NOTRUN -> [FAIL][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-rpls-2/igt@runner@aborted.html

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

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

### CI changes ###

#### Issues hit ####

  * boot:
    - fi-hsw-4770:        [PASS][4] -> [FAIL][5] ([i915#8293])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-hsw-4770/boot.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-hsw-4770/boot.html

  

### IGT changes ###

#### Issues hit ####

  * igt@gem_huc_copy@huc-copy:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][6] ([fdo#109271] / [i915#2190])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@basic:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][7] ([fdo#109271] / [i915#4613]) +3 other tests skip
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@gem_lmem_swapping@basic.html

  * igt@i915_selftest@live@gt_pm:
    - fi-kbl-soraka:      NOTRUN -> [DMESG-FAIL][8] ([i915#1886] / [i915#7913])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@i915_selftest@live@gt_pm.html

  * igt@kms_dsc@dsc-basic:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][9] ([fdo#109271]) +9 other tests skip
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@kms_dsc@dsc-basic.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@execlists:
    - fi-bsw-n3050:       [ABORT][10] ([i915#7913]) -> [PASS][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-bsw-n3050/igt@i915_selftest@live@execlists.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-bsw-n3050/igt@i915_selftest@live@execlists.html

  * igt@kms_chamelium_edid@hdmi-edid-read:
    - {bat-dg2-13}:       [DMESG-WARN][12] ([i915#7952]) -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/bat-dg2-13/igt@kms_chamelium_edid@hdmi-edid-read.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-dg2-13/igt@kms_chamelium_edid@hdmi-edid-read.html

  * igt@kms_hdmi_inject@inject-audio:
    - fi-kbl-guc:         [FAIL][14] ([IGT#3] / [i915#6121]) -> [PASS][15]
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html

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

  [IGT#3]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/3
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1886]: https://gitlab.freedesktop.org/drm/intel/issues/1886
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#6121]: https://gitlab.freedesktop.org/drm/intel/issues/6121
  [i915#7913]: https://gitlab.freedesktop.org/drm/intel/issues/7913
  [i915#7952]: https://gitlab.freedesktop.org/drm/intel/issues/7952
  [i915#8293]: https://gitlab.freedesktop.org/drm/intel/issues/8293


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

  * Linux: CI_DRM_13651 -> Patchwork_122589v10

  CI-20190529: 20190529
  CI_DRM_13651: 61b71c3f061a44a6ab1dcf756918886aa03a5480 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_7493: 2517e42d612e0c1ca096acf8b5f6177f7ef4bce7 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_122589v10: 61b71c3f061a44a6ab1dcf756918886aa03a5480 @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

083e3c934233 drm/i915/dp_mst: Check BW limitations only after all streams are computed
981a0f4e3e4c drm/i915/dp_mst: Improve BW sharing between MST streams
56ef0e4b6625 drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
d6dd87fac678 drm/i915/dp_mst: Add missing DSC compression disabling
1a32e08efe98 drm/i915/dp_mst: Enable DSC decompression if any stream needs this
6cc7e9ed99c7 drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
11fc2f2b8219 drm/i915/dp_mst: Program the DSC PPS SDP for each stream
1ae3523042c4 drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
a0ef3c0a67ac drm/i915/dp_mst: Fix PBN calculation with FEC overhead
cbeff948d039 drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
53b98fbfae49 drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
08dccb8ead0c drm/dp_mst: Add helper to determine if an MST port is downstream of another port
9ce658a8cf6c drm/dp_mst: Add a way to calculate PBN values with FEC overhead
0a1f353ad215 drm/dp_mst: Fix fractional DSC bpp handling
ff78e7f980c5 drm/i915/fdi: Recompute state for affected CRTCs on FDI links
94262c175ffd drm/i915/fdi: Improve FDI BW sharing between pipe B and C
bfb10a7239d1 drm/i915: Add helpers for BW management on shared display links
0899c01543f4 drm/i915: Factor out a helper to check/compute all the CRTC states
81ea58177388 drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
f3bc271dbb8b drm/i915: Add helper to modeset a set of pipes
45a2fb673630 drm/i915/dp: Limit the output link bpp in DSC mode
a14f3e77aa9f drm/i915/dp: Update the link bpp limits for DSC mode
7b7d3300dc14 drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
94fc9fc20497 drm/i915/dp: Track the pipe and link bpp limits separately
33e00687bb18 drm/i915/dp: Factor out helpers to compute the link limits

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/index.html

[-- Attachment #2: Type: text/html, Size: 8505 bytes --]

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

* Re: [Intel-gfx]  ✗ Fi.CI.BAT: failure for drm/i915: Improve BW management on shared display links (rev10)
  2023-09-19 11:55 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
@ 2023-09-19 13:29   ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-19 13:29 UTC (permalink / raw)
  To: intel-gfx

On Tue, Sep 19, 2023 at 11:55:30AM +0000, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915: Improve BW management on shared display links (rev10)
> URL   : https://patchwork.freedesktop.org/series/122589/
> State : failure
> 
> == Summary ==
> 
> CI Bug Log - changes from CI_DRM_13651 -> Patchwork_122589v10
> ====================================================
> 
> Summary
> -------
> 
>   **FAILURE**
> 
>   Serious unknown changes coming with Patchwork_122589v10 absolutely need to be
>   verified manually.
>   
>   If you think the reported changes have nothing to do with the changes
>   introduced in Patchwork_122589v10, please notify your bug team (lgci.bug.filing@intel.com) to allow them
>   to document this new failure mode, which will reduce false positives in CI.
> 
>   External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/index.html
> 
> Participating hosts (38 -> 37)
> ------------------------------
> 
>   Additional (2): fi-kbl-soraka bat-rpls-2 
>   Missing    (3): fi-tgl-1115g4 bat-atsm-1 fi-snb-2520m 
> 
> Possible new issues
> -------------------
> 
>   Here are the unknown changes that may have been introduced in Patchwork_122589v10:
> 
> ### IGT changes ###
> 
> #### Possible regressions ####
> 
>   * igt@i915_module_load@load:
>     - bat-mtlp-8:         [PASS][1] -> [INCOMPLETE][2]
>    [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/bat-mtlp-8/igt@i915_module_load@load.html
>    [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-mtlp-8/igt@i915_module_load@load.html

Looks like an issue in 
intel_crtc_initial_plane_config() -> intel_plane_disable_noatomic()

which has been happening on different mtlp machines, recently in
CI_DRM_13651 / re-mtlp-7. I opened a ticket for it:
https://gitlab.freedesktop.org/drm/intel/-/issues/9366

>   * igt@runner@aborted:
>     - bat-rpls-2:         NOTRUN -> [FAIL][3]
>    [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-rpls-2/igt@runner@aborted.html

This is an issue unrelated to i915, happening before loading the driver:

6>[   12.711379] pcieport 0000:00:1d.0:   bridge window [mem 0x6001000000-0x60019fffff 64bit pref]

<4>[   12.715089] ======================================================
<4>[   12.721385] WARNING: possible circular locking dependency detected
<4>[   12.727676] 6.6.0-rc2-Patchwork_122589v10-g61b71c3f061a+ #1 Not tainted
<4>[   12.734394] ------------------------------------------------------
<4>[   12.740680] irq/123-pciehp/150 is trying to acquire lock:
<4>[   12.746193] ffff888105adc2f8 (&ctrl->reset_lock){.+.+}-{3:3}, at: pciehp_configure_device+0xb5/0x160
<4>[   12.755573]
                  but task is already holding lock:
<4>[   12.761693] ffffffff827aeb68 (pci_rescan_remove_lock){+.+.}-{3:3}, at: pciehp_configure_device+0x23/0x160

> Known issues
> ------------
> 
>   Here are the changes found in Patchwork_122589v10 that come from known issues:
> 
> ### CI changes ###
> 
> #### Issues hit ####
> 
>   * boot:
>     - fi-hsw-4770:        [PASS][4] -> [FAIL][5] ([i915#8293])
>    [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-hsw-4770/boot.html
>    [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-hsw-4770/boot.html
> 
>   
> 
> ### IGT changes ###
> 
> #### Issues hit ####
> 
>   * igt@gem_huc_copy@huc-copy:
>     - fi-kbl-soraka:      NOTRUN -> [SKIP][6] ([fdo#109271] / [i915#2190])
>    [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@gem_huc_copy@huc-copy.html
> 
>   * igt@gem_lmem_swapping@basic:
>     - fi-kbl-soraka:      NOTRUN -> [SKIP][7] ([fdo#109271] / [i915#4613]) +3 other tests skip
>    [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@gem_lmem_swapping@basic.html
> 
>   * igt@i915_selftest@live@gt_pm:
>     - fi-kbl-soraka:      NOTRUN -> [DMESG-FAIL][8] ([i915#1886] / [i915#7913])
>    [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@i915_selftest@live@gt_pm.html
> 
>   * igt@kms_dsc@dsc-basic:
>     - fi-kbl-soraka:      NOTRUN -> [SKIP][9] ([fdo#109271]) +9 other tests skip
>    [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-soraka/igt@kms_dsc@dsc-basic.html
> 
>   
> #### Possible fixes ####
> 
>   * igt@i915_selftest@live@execlists:
>     - fi-bsw-n3050:       [ABORT][10] ([i915#7913]) -> [PASS][11]
>    [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-bsw-n3050/igt@i915_selftest@live@execlists.html
>    [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-bsw-n3050/igt@i915_selftest@live@execlists.html
> 
>   * igt@kms_chamelium_edid@hdmi-edid-read:
>     - {bat-dg2-13}:       [DMESG-WARN][12] ([i915#7952]) -> [PASS][13]
>    [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/bat-dg2-13/igt@kms_chamelium_edid@hdmi-edid-read.html
>    [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/bat-dg2-13/igt@kms_chamelium_edid@hdmi-edid-read.html
> 
>   * igt@kms_hdmi_inject@inject-audio:
>     - fi-kbl-guc:         [FAIL][14] ([IGT#3] / [i915#6121]) -> [PASS][15]
>    [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_13651/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html
>    [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/fi-kbl-guc/igt@kms_hdmi_inject@inject-audio.html
> 
>   
>   {name}: This element is suppressed. This means it is ignored when computing
>           the status of the difference (SUCCESS, WARNING, or FAILURE).
> 
>   [IGT#3]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/3
>   [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
>   [i915#1886]: https://gitlab.freedesktop.org/drm/intel/issues/1886
>   [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
>   [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
>   [i915#6121]: https://gitlab.freedesktop.org/drm/intel/issues/6121
>   [i915#7913]: https://gitlab.freedesktop.org/drm/intel/issues/7913
>   [i915#7952]: https://gitlab.freedesktop.org/drm/intel/issues/7952
>   [i915#8293]: https://gitlab.freedesktop.org/drm/intel/issues/8293
> 
> 
> Build changes
> -------------
> 
>   * Linux: CI_DRM_13651 -> Patchwork_122589v10
> 
>   CI-20190529: 20190529
>   CI_DRM_13651: 61b71c3f061a44a6ab1dcf756918886aa03a5480 @ git://anongit.freedesktop.org/gfx-ci/linux
>   IGT_7493: 2517e42d612e0c1ca096acf8b5f6177f7ef4bce7 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
>   Patchwork_122589v10: 61b71c3f061a44a6ab1dcf756918886aa03a5480 @ git://anongit.freedesktop.org/gfx-ci/linux
> 
> 
> ### Linux commits
> 
> 083e3c934233 drm/i915/dp_mst: Check BW limitations only after all streams are computed
> 981a0f4e3e4c drm/i915/dp_mst: Improve BW sharing between MST streams
> 56ef0e4b6625 drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
> d6dd87fac678 drm/i915/dp_mst: Add missing DSC compression disabling
> 1a32e08efe98 drm/i915/dp_mst: Enable DSC decompression if any stream needs this
> 6cc7e9ed99c7 drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
> 11fc2f2b8219 drm/i915/dp_mst: Program the DSC PPS SDP for each stream
> 1ae3523042c4 drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
> a0ef3c0a67ac drm/i915/dp_mst: Fix PBN calculation with FEC overhead
> cbeff948d039 drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations
> 53b98fbfae49 drm/dp_mst: Factor out a helper to check the atomic state of a topology manager
> 08dccb8ead0c drm/dp_mst: Add helper to determine if an MST port is downstream of another port
> 9ce658a8cf6c drm/dp_mst: Add a way to calculate PBN values with FEC overhead
> 0a1f353ad215 drm/dp_mst: Fix fractional DSC bpp handling
> ff78e7f980c5 drm/i915/fdi: Recompute state for affected CRTCs on FDI links
> 94262c175ffd drm/i915/fdi: Improve FDI BW sharing between pipe B and C
> bfb10a7239d1 drm/i915: Add helpers for BW management on shared display links
> 0899c01543f4 drm/i915: Factor out a helper to check/compute all the CRTC states
> 81ea58177388 drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
> f3bc271dbb8b drm/i915: Add helper to modeset a set of pipes
> 45a2fb673630 drm/i915/dp: Limit the output link bpp in DSC mode
> a14f3e77aa9f drm/i915/dp: Update the link bpp limits for DSC mode
> 7b7d3300dc14 drm/i915/dp: Skip computing a non-DSC link config if DSC is needed
> 94fc9fc20497 drm/i915/dp: Track the pipe and link bpp limits separately
> 33e00687bb18 drm/i915/dp: Factor out helpers to compute the link limits
> 
> == Logs ==
> 
> For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_122589v10/index.html

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

* Re: [Intel-gfx] [PATCH v5 06/25] drm/i915: Add helper to modeset a set of pipes
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
@ 2023-09-19 14:25     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 14:25 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Sep 18, 2023 at 09:25:03PM +0300, Imre Deak wrote:
> Add intel_modeset_pipes_in_mask_early() to modeset a provided set of
> pipes, used in a follow-up patch.
> 
> As opposed intel_modeset_all_pipes() which modesets only the active
> pipes - others don't requiring programming the HW - modeset all enabled
> pipes in intel_modeset_pipes_in_mask_early() which may need to recompute
> their state even if they are not active (that is in the DPMS off state).
> 
> While at it add DocBook descriptions for the two exported functions.
> 
> v2:
> - Add a flag controlling if active planes are force updated as well.
> - Add DockBook descriptions.
> v3:
> - For clarity use _early/_late suffixes for the exported functions
>   instead of the update_active_planes parameter. (Ville)
> v4:
> - In intel_modeset_pipes_in_mask_early() update only the crtc
>   flags relevant to the early phase. (Ville)
> - Rename intel_modeset_all_pipes() in a separate patch.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>

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

> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 102 +++++++++++++++----
>  drivers/gpu/drm/i915/display/intel_display.h |   2 +
>  2 files changed, 83 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 6bbc9069754c4..1c9a128f4af27 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5407,16 +5407,90 @@ intel_verify_planes(struct intel_atomic_state *state)
>  			     plane_state->uapi.visible);
>  }
>  
> +static int intel_modeset_pipe(struct intel_atomic_state *state,
> +			      struct intel_crtc_state *crtc_state,
> +			      const char *reason)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	int ret;
> +
> +	drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
> +		    crtc->base.base.id, crtc->base.name, reason);
> +
> +	ret = drm_atomic_add_affected_connectors(&state->base,
> +						 &crtc->base);
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_atomic_add_affected_planes(state, crtc);
> +	if (ret)
> +		return ret;
> +
> +	crtc_state->uapi.mode_changed = true;
> +
> +	return 0;
> +}
> +
> +/**
> + * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
> + * @state: intel atomic state
> + * @reason: the reason for the full modeset
> + * @mask: mask of pipes to modeset
> + *
> + * Add pipes in @mask to @state and force a full modeset on the enabled ones
> + * due to the description in @reason.
> + * This function can be called only before new plane states are computed.
> + *
> + * Returns 0 in case of success, negative error code otherwise.
> + */
> +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> +				      const char *reason, u8 mask)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_crtc *crtc;
> +
> +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mask) {
> +		struct intel_crtc_state *crtc_state;
> +		int ret;
> +
> +		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +
> +		if (!crtc_state->hw.enable ||
> +		    intel_crtc_needs_modeset(crtc_state))
> +			continue;
> +
> +		ret = intel_modeset_pipe(state, crtc_state, reason);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * intel_modeset_all_pipes - force a full modeset on all pipes
> + * @state: intel atomic state
> + * @reason: the reason for the full modeset
> + *
> + * Add all pipes to @state and force a full modeset on the active ones due to
> + * the description in @reason.
> + * This function can be called only after new plane states are computed already.
> + *
> + * Returns 0 in case of success, negative error code otherwise.
> + */
>  int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  			    const char *reason)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
>  
> -	/*
> -	 * Add all pipes to the state, and force
> -	 * a modeset on all the active ones.
> -	 */
>  	for_each_intel_crtc(&dev_priv->drm, crtc) {
>  		struct intel_crtc_state *crtc_state;
>  		int ret;
> @@ -5429,25 +5503,11 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  		    intel_crtc_needs_modeset(crtc_state))
>  			continue;
>  
> -		drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
> -			    crtc->base.base.id, crtc->base.name, reason);
> +		ret = intel_modeset_pipe(state, crtc_state, reason);
> +		if (ret)
> +			return ret;
>  
> -		crtc_state->uapi.mode_changed = true;
>  		crtc_state->update_pipe = false;
> -
> -		ret = drm_atomic_add_affected_connectors(&state->base,
> -							 &crtc->base);
> -		if (ret)
> -			return ret;
> -
> -		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
> -		if (ret)
> -			return ret;
> -
> -		ret = intel_atomic_add_affected_planes(state, crtc);
> -		if (ret)
> -			return ret;
> -
>  		crtc_state->update_planes |= crtc_state->active_planes;
>  		crtc_state->async_flip_planes = 0;
>  		crtc_state->do_async_flip = false;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 49ac8473b988b..3008e8b2b437e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -513,6 +513,8 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
>  void intel_update_watermarks(struct drm_i915_private *i915);
>  
>  /* modesetting */
> +int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
> +				      const char *reason, u8 pipe_mask);
>  int intel_modeset_all_pipes(struct intel_atomic_state *state,
>  			    const char *reason);
>  void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v5 07/25] drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late()
  2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 07/25] drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late() Imre Deak
@ 2023-09-19 14:26     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 14:26 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Sep 18, 2023 at 09:25:04PM +0300, Imre Deak wrote:
> Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late() to
> clarify when the function can be called (vs.
> intel_modeset_pipes_in_mask_early()).
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>

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

> ---
>  drivers/gpu/drm/i915/display/intel_cdclk.c   | 2 +-
>  drivers/gpu/drm/i915/display/intel_display.c | 6 +++---
>  drivers/gpu/drm/i915/display/intel_display.h | 4 ++--
>  drivers/gpu/drm/i915/display/skl_watermark.c | 2 +-
>  4 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index ad5251ba6fe13..a2e20b25d6361 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -3139,7 +3139,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
>  	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
>  					     &new_cdclk_state->actual)) {
>  		/* All pipes must be switched off while we change the cdclk. */
> -		ret = intel_modeset_all_pipes(state, "CDCLK change");
> +		ret = intel_modeset_all_pipes_late(state, "CDCLK change");
>  		if (ret)
>  			return ret;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 1c9a128f4af27..9a69b8848fee6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5475,7 +5475,7 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
>  }
>  
>  /**
> - * intel_modeset_all_pipes - force a full modeset on all pipes
> + * intel_modeset_all_pipes_late - force a full modeset on all pipes
>   * @state: intel atomic state
>   * @reason: the reason for the full modeset
>   *
> @@ -5485,8 +5485,8 @@ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
>   *
>   * Returns 0 in case of success, negative error code otherwise.
>   */
> -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> -			    const char *reason)
> +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> +				 const char *reason)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct intel_crtc *crtc;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 3008e8b2b437e..64a5be7859331 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -515,8 +515,8 @@ void intel_update_watermarks(struct drm_i915_private *i915);
>  /* modesetting */
>  int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
>  				      const char *reason, u8 pipe_mask);
> -int intel_modeset_all_pipes(struct intel_atomic_state *state,
> -			    const char *reason);
> +int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
> +				 const char *reason);
>  void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
>  					  struct intel_power_domain_mask *old_domains);
>  void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
> diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
> index 063929a42a42f..a29d9b717deed 100644
> --- a/drivers/gpu/drm/i915/display/skl_watermark.c
> +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
> @@ -2616,7 +2616,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
>  
>  		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
>  			/* TODO: Implement vblank synchronized MBUS joining changes */
> -			ret = intel_modeset_all_pipes(state, "MBUS joining change");
> +			ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
>  			if (ret)
>  				return ret;
>  		}
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode Imre Deak
@ 2023-09-19 14:48   ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 14:48 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:38PM +0300, Imre Deak wrote:
> In non-DSC mode the link bpp can be set in 2*3 bpp steps in the pipe bpp
> range, while in DSC mode it can be set in 1/16 bpp steps to any value
> up to the maximum pipe bpp. Update the limits accordingly in both modes
> to prepare for a follow-up patch which may need to reduce the max link
> bpp value and starts to check the link bpp limits in DSC mode as well.
> 
> While at it add more detail to the link limit debug print and print it
> also for DSC mode.
> 
> v2:
> - Add to_bpp_frac_dec() instead of open coding it. (Jani)
> v3: (Ville)
> - Add BPP_X16_FMT / BPP_X16_ARG.
> - Add TODO: comment about initializing the DSC link bpp limits earlier.
> 
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  8 ++
>  drivers/gpu/drm/i915/display/intel_dp.c       | 93 +++++++++++++++----
>  drivers/gpu/drm/i915/display/intel_dp.h       |  6 ++
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 23 +++--
>  4 files changed, 108 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index bdad675e03fb8..50fe8ff354137 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -2115,6 +2115,14 @@ static inline int to_bpp_int(int bpp_x16)
>  	return bpp_x16 >> 4;
>  }
>  
> +static inline int to_bpp_frac(int bpp_x16)
> +{
> +	return bpp_x16 & 0xf;
> +}
> +
> +#define BPP_X16_FMT		"%d.%04d"
> +#define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
> +
>  static inline int to_bpp_x16(int bpp)
>  {
>  	return bpp << 4;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index bdaaad34463fb..2a45eefc83ebf 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2190,16 +2190,72 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
>  	return 0;
>  }
>  
> -static void
> +/**
> + * intel_dp_compute_config_link_bpp_limits - compute output link bpp limits
> + * @intel_dp: intel DP
> + * @crtc_state: crtc state
> + * @dsc: DSC compression mode
> + * @limits: link configuration limits
> + *
> + * Calculates the output link min, max bpp values in @limits based on the
> + * pipe bpp range, @crtc_state and @dsc mode.
> + *
> + * Returns %true in case of success.
> + */
> +bool
> +intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
> +					const struct intel_crtc_state *crtc_state,
> +					bool dsc,
> +					struct link_config_limits *limits)
> +{
> +	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
> +	const struct drm_display_mode *adjusted_mode =
> +		&crtc_state->hw.adjusted_mode;
> +	const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +	int max_link_bpp_x16;
> +
> +	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> +
> +	if (!dsc) {
> +		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
> +
> +		if (max_link_bpp_x16 < to_bpp_x16(limits->pipe.min_bpp))
> +			return false;
> +
> +		limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
> +	} else {
> +		/*
> +		 * TODO: set the DSC link limits already here, atm these are
> +		 * initialized only later in intel_edp_dsc_compute_pipe_bpp() /
> +		 * intel_dp_dsc_compute_pipe_bpp()
> +		 */
> +		limits->link.min_bpp_x16 = 0;
> +	}
> +
> +	limits->link.max_bpp_x16 = max_link_bpp_x16;
> +
> +	drm_dbg_kms(&i915->drm,
> +		    "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",

Could do a followup patch to print also the min limits.

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

> +		    encoder->base.base.id, encoder->base.name,
> +		    crtc->base.base.id, crtc->base.name,
> +		    adjusted_mode->crtc_clock,
> +		    dsc ? "on" : "off",
> +		    limits->max_lane_count,
> +		    limits->max_rate,
> +		    limits->pipe.max_bpp,
> +		    BPP_X16_ARGS(limits->link.max_bpp_x16));
> +
> +	return true;
> +}
> +
> +static bool
>  intel_dp_compute_config_limits(struct intel_dp *intel_dp,
>  			       struct intel_crtc_state *crtc_state,
>  			       bool respect_downstream_limits,
> +			       bool dsc,
>  			       struct link_config_limits *limits)
>  {
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -	const struct drm_display_mode *adjusted_mode =
> -		&crtc_state->hw.adjusted_mode;
> -
>  	limits->min_rate = intel_dp_common_rate(intel_dp, 0);
>  	limits->max_rate = intel_dp_max_link_rate(intel_dp);
>  
> @@ -2225,13 +2281,10 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
>  
>  	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
>  
> -	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
> -	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> -
> -	drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
> -		    "max rate %d max bpp %d pixel clock %iKHz\n",
> -		    limits->max_lane_count, limits->max_rate,
> -		    to_bpp_int(limits->link.max_bpp_x16), adjusted_mode->crtc_clock);
> +	return intel_dp_compute_config_link_bpp_limits(intel_dp,
> +						       crtc_state,
> +						       dsc,
> +						       limits);
>  }
>  
>  static int
> @@ -2250,9 +2303,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  	bool dsc_needed;
>  	int ret = 0;
>  
> -	intel_dp_compute_config_limits(intel_dp, pipe_config,
> -				       respect_downstream_limits, &limits);
> -
>  	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
>  				    adjusted_mode->crtc_clock))
>  		pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> @@ -2264,7 +2314,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  	 */
>  	joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
>  
> -	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en;
> +	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> +		     !intel_dp_compute_config_limits(intel_dp, pipe_config,
> +						     respect_downstream_limits,
> +						     false,
> +						     &limits);
>  
>  	if (!dsc_needed) {
>  		/*
> @@ -2281,6 +2335,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  		drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
>  			    str_yes_no(ret), str_yes_no(joiner_needs_dsc),
>  			    str_yes_no(intel_dp->force_dsc_en));
> +
> +		if (!intel_dp_compute_config_limits(intel_dp, pipe_config,
> +						    respect_downstream_limits,
> +						    true,
> +						    &limits))
> +			return -EINVAL;
> +
>  		ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
>  						  conn_state, &limits, 64, true);
>  		if (ret < 0)
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index 98c60ab6e182e..2cf3681bac64a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -156,4 +156,10 @@ void intel_dp_phy_test(struct intel_encoder *encoder);
>  void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
>  int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
>  
> +bool
> +intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
> +					const struct intel_crtc_state *crtc_state,
> +					bool dsc,
> +					struct link_config_limits *limits);
> +
>  #endif /* __INTEL_DP_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 2a0f2caf5b8d7..7d84689d69fad 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -295,9 +295,10 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
>  	return 0;
>  }
>  
> -static void
> +static bool
>  intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
>  				   struct intel_crtc_state *crtc_state,
> +				   bool dsc,
>  				   struct link_config_limits *limits)
>  {
>  	/*
> @@ -323,8 +324,10 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
>  
>  	intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
>  
> -	limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
> -	limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> +	return intel_dp_compute_config_link_bpp_limits(intel_dp,
> +						       crtc_state,
> +						       dsc,
> +						       limits);
>  }
>  
>  static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
> @@ -347,9 +350,11 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
>  	pipe_config->has_pch_encoder = false;
>  
> -	intel_dp_mst_compute_config_limits(intel_dp, pipe_config, &limits);
> -
> -	dsc_needed = intel_dp->force_dsc_en;
> +	dsc_needed = intel_dp->force_dsc_en ||
> +		     !intel_dp_mst_compute_config_limits(intel_dp,
> +							 pipe_config,
> +							 false,
> +							 &limits);
>  
>  	if (!dsc_needed) {
>  		ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
> @@ -368,6 +373,12 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  			    str_yes_no(ret),
>  			    str_yes_no(intel_dp->force_dsc_en));
>  
> +		if (!intel_dp_mst_compute_config_limits(intel_dp,
> +							pipe_config,
> +							true,
> +							&limits))
> +			return -EINVAL;
> +
>  		/*
>  		 * FIXME: As bpc is hardcoded to 8, as mentioned above,
>  		 * WARN and ignore the debug flag force_dsc_bpc for now.
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in DSC mode
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in " Imre Deak
@ 2023-09-19 14:49   ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 14:49 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:39PM +0300, Imre Deak wrote:
> Limit the output link bpp in DSC mode to the link_config_limits
> link.min_bpp_x16 .. max_bpp_x16 range the same way it's done in non-DSC
> mode.  Atm this doesn't make a difference, the link bpp range being
> 0 .. max pipe bpp, but a follow-up patch will need a way to reduce max
> link bpp below its current value.
> 
> v2:
> - Add to_bpp_int_roundup() instead of open coding it. (Jani)
> 
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>

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

> ---
>  drivers/gpu/drm/i915/display/intel_display_types.h | 5 +++++
>  drivers/gpu/drm/i915/display/intel_dp.c            | 4 ++++
>  drivers/gpu/drm/i915/display/intel_dp_mst.c        | 3 +++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 50fe8ff354137..966163ccbd7a3 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -2123,6 +2123,11 @@ static inline int to_bpp_frac(int bpp_x16)
>  #define BPP_X16_FMT		"%d.%04d"
>  #define BPP_X16_ARGS(bpp_x16)	to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
>  
> +static inline int to_bpp_int_roundup(int bpp_x16)
> +{
> +	return (bpp_x16 + 0xf) >> 4;
> +}
> +
>  static inline int to_bpp_x16(int bpp)
>  {
>  	return bpp << 4;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2a45eefc83ebf..d5e6813d36c8f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1925,6 +1925,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
>  	dsc_src_min_bpp = dsc_src_min_compressed_bpp();
>  	dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
>  	dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
> +	dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
>  
>  	dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
>  	dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(intel_dp, pipe_config, pipe_bpp / 3);
> @@ -1934,6 +1935,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
>  								adjusted_mode->hdisplay,
>  								pipe_config->bigjoiner_pipes);
>  	dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
> +	dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
>  
>  	if (DISPLAY_VER(i915) >= 13)
>  		return xelpd_dsc_compute_link_config(intel_dp, pipe_config, limits,
> @@ -2079,10 +2081,12 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
>  	dsc_src_min_bpp = dsc_src_min_compressed_bpp();
>  	dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
>  	dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
> +	dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
>  
>  	dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
>  	dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(intel_dp, pipe_config, pipe_bpp / 3);
>  	dsc_max_bpp = dsc_sink_max_bpp ? min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp;
> +	dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
>  
>  	/* Compressed BPP should be less than the Input DSC bpp */
>  	dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 7d84689d69fad..d38d0dd23fc39 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -233,6 +233,9 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
>  	if (max_bpp > sink_max_bpp)
>  		max_bpp = sink_max_bpp;
>  
> +	min_bpp = max(min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
> +	max_bpp = min(max_bpp, to_bpp_int(limits->link.max_bpp_x16));
> +
>  	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp,
>  						     min_bpp, limits,
>  						     conn_state, 2 * 3, true);
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v5 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-18 18:25     ` [Intel-gfx] [PATCH v5 " Imre Deak
@ 2023-09-19 15:21       ` Ville Syrjälä
  2023-09-19 17:40         ` Imre Deak
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 15:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Sep 18, 2023 at 09:25:05PM +0300, Imre Deak wrote:
> At the moment a modeset fails if the config computation of a pipe can't
> fit its required BW to the available link BW even though the limitation
> may be resolved by reducing the BW requirement of other pipes.
> 
> To improve the above this patch adds helper functions checking the
> overall BW limits after all CRTC states have been computed. If the check
> fails the maximum link bpp for a selected pipe will be reduced and all
> the CRTC states will be recomputed until either the overall BW limit
> check passes, or further bpp reduction is not possible (because all
> pipes/encoders sharing the link BW reached their minimum link bpp).
> 
> Atm, the MST encoder allocates twice the required BW for YUV420 format
> streams. A follow-up patchset will fix that, add a code comment about
> this.
> 
> This change prepares for upcoming patches enabling the above BW
> management on FDI and MST links.
> 
> v2:
> - Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
>   intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
> v3:
> - Add the helper functions in a separate patch. (Ville)
> - Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
> - Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
>   limit failure.
> v4:
> - Make intel_atomic_check_config() static.
> v5: (Ville)
> - Rename intel_link_bw_limits::min_bpp_pipes to min_bpp_reached_pipes
>   and intel_link_bw_reset_pipe_limit_to_min() to
>   intel_link_bw_set_min_bpp_for_pipe().
> - Rename pipe_bpp to link_bpp in intel_link_bw_reduce_bpp().
> - Add FIXME: comment about MST encoder's YUV420 BW allocation and
>   tracking the link bpp limit accordingly.
> 
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |  65 ++++-
>  .../drm/i915/display/intel_display_types.h    |   3 +-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |   4 +
>  drivers/gpu/drm/i915/display/intel_link_bw.c  | 232 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
>  7 files changed, 339 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 1b2e02e9d92cb..de4967c141f00 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -268,6 +268,7 @@ i915-y += \
>  	display/intel_hotplug.o \
>  	display/intel_hotplug_irq.o \
>  	display/intel_hti.o \
> +	display/intel_link_bw.o \
>  	display/intel_load_detect.o \
>  	display/intel_lpe_audio.o \
>  	display/intel_modeset_lock.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> index 182c6dd64f47c..1eda6a9f19aa8 100644
> --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
>  	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
>  	crtc_state->scaler_state.scaler_id = -1;
>  	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> +	crtc_state->max_link_bpp_x16 = INT_MAX;
>  }
>  
>  static struct intel_crtc *intel_crtc_alloc(void)
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 3bdc338a22e19..537884035304c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -87,6 +87,7 @@
>  #include "intel_frontbuffer.h"
>  #include "intel_hdmi.h"
>  #include "intel_hotplug.h"
> +#include "intel_link_bw.h"
>  #include "intel_lvds.h"
>  #include "intel_lvds_regs.h"
>  #include "intel_modeset_setup.h"
> @@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
>  
>  static int
>  intel_modeset_pipe_config(struct intel_atomic_state *state,
> -			  struct intel_crtc *crtc)
> +			  struct intel_crtc *crtc,
> +			  const struct intel_link_bw_limits *limits)
>  {
>  	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
>  	struct intel_crtc_state *crtc_state =
> @@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> +	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
> +
> +	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
> +		drm_dbg_kms(&i915->drm,
> +			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> +			    crtc->base.base.id, crtc->base.name,
> +			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> +	}
> +
>  	base_bpp = crtc_state->pipe_bpp;
>  
>  	/*
> @@ -6218,7 +6229,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
>  	return 0;
>  }
>  
> -static int intel_atomic_check_config(struct intel_atomic_state *state)
> +static int intel_atomic_check_config(struct intel_atomic_state *state,
> +				     struct intel_link_bw_limits *limits,
> +				     enum pipe *failed_pipe)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct intel_crtc_state *new_crtc_state;
> @@ -6226,6 +6239,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  	int ret;
>  	int i;
>  
> +	*failed_pipe = INVALID_PIPE;
> +
>  	ret = intel_bigjoiner_add_affected_crtcs(state);
>  	if (ret)
>  		return ret;
> @@ -6251,7 +6266,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  		if (!new_crtc_state->hw.enable)
>  			continue;
>  
> -		ret = intel_modeset_pipe_config(state, crtc);
> +		ret = intel_modeset_pipe_config(state, crtc, limits);
>  		if (ret)
>  			break;
>  
> @@ -6260,9 +6275,51 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
>  			break;
>  	}
>  
> +	if (ret)
> +		*failed_pipe = crtc->pipe;
> +
>  	return ret;
>  }
>  
> +static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_link_bw_limits new_limits;
> +	struct intel_link_bw_limits old_limits;
> +	int ret;
> +
> +	intel_link_bw_init_limits(i915, &new_limits);
> +	old_limits = new_limits;
> +
> +	while (true) {
> +		enum pipe failed_pipe;
> +
> +		ret = intel_atomic_check_config(state, &new_limits,
> +						&failed_pipe);
> +		if (ret) {
> +			/*
> +			 * The bpp limit for a pipe is below the minimum it supports, set the
> +			 * limit to the minimum and recalculate the config.
> +			 */
> +			if (ret == -EINVAL &&
> +			    intel_link_bw_set_min_bpp_for_pipe(state,
> +							       &old_limits,
> +							       &new_limits,
> +							       failed_pipe))
> +				continue;
> +
> +			break;
> +		}
> +
> +		old_limits = new_limits;
> +
> +		ret = intel_link_bw_atomic_check(state, &new_limits);
> +		if (ret != -EAGAIN)
> +			break;
> +	}
> +
> +	return ret;
> +}
>  /**
>   * intel_atomic_check - validate state object
>   * @dev: drm device
> @@ -6307,7 +6364,7 @@ int intel_atomic_check(struct drm_device *dev,
>  			return ret;
>  	}
>  
> -	ret = intel_atomic_check_config(state);
> +	ret = intel_atomic_check_config_and_link(state);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 50a22261f5eec..4d7948fa4bbba 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1189,7 +1189,8 @@ struct intel_crtc_state {
>  		u32 ctrl, div;
>  	} dsi_pll;
>  
> -	int pipe_bpp;
> +	int max_link_bpp_x16;	/* in 1/16 bpp units */
> +	int pipe_bpp;		/* in 1 bpp units */
>  	struct intel_link_m_n dp_m_n;
>  
>  	/* m2_n2 for eDP downclock */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index a914d83ab3dde..f26c2eecb2778 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -157,6 +157,10 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
>  	int slots = -EINVAL;
>  	int link_bpp;
>  
> +	/*
> +	 * FIXME: allocate the BW according to link_bpp, which in the case of
> +	 * YUV420 is only half of the pipe bpp value.
> +	 */
>  	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
>  						     to_bpp_int(limits->link.max_bpp_x16),
>  						     to_bpp_int(limits->link.min_bpp_x16),
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> new file mode 100644
> index 0000000000000..9b6d0891345d7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> @@ -0,0 +1,232 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +
> +#include "intel_atomic.h"
> +#include "intel_display_types.h"
> +#include "intel_dp_mst.h"
> +#include "intel_fdi.h"
> +#include "intel_link_bw.h"
> +
> +/**
> + * intel_link_bw_init_limits - initialize BW limits
> + * @i915: device instance
> + * @limits: link BW limits
> + *
> + * Initialize @limits.
> + */
> +void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
> +{
> +	enum pipe pipe;
> +
> +	limits->min_bpp_reached_pipes = 0;
> +	for_each_pipe(i915, pipe)
> +		limits->max_bpp_x16[pipe] = INT_MAX;
> +}
> +
> +/**
> + * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
> + * @crtc_state: the crtc state
> + *
> + * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
> + * call this function during state computation in the simple case where the
> + * link bpp will always match the pipe bpp. This is the case for all non-DP
> + * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
> + * of DSC compression.
> + *
> + * Returns %true in case of success, %false if pipe bpp would need to be
> + * reduced below its valid range.
> + */
> +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
> +{
> +	int pipe_bpp = min(crtc_state->pipe_bpp,
> +			   to_bpp_int(crtc_state->max_link_bpp_x16));
> +
> +	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
> +
> +	if (pipe_bpp < 6 * 3)
> +		return false;
> +
> +	crtc_state->pipe_bpp = pipe_bpp;
> +
> +	return true;
> +}

Hmm. The fact that you can't use this for DP makes this rather
non-generic. Maybe it should just live in intel_fdi.c or something?
Or are we going to use it for something else as well?

> +
> +/**
> + * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
> + * @state: atomic state
> + * @limits: link BW limits
> + * @pipe_mask: mask of pipes to select from
> + * @reason: explanation of why bpp reduction is needed
> + *
> + * Select the pipe from @pipe_mask with the biggest link bpp value and set the
> + * maximum of link bpp in @limits below this value. Modeset the selected pipe,
> + * so that its state will get recomputed.
> + *
> + * This function can be called to resolve a link's BW overallocation by reducing
> + * the link bpp of one pipe on the link and hence reducing the total link BW.
> + *
> + * Returns
> + *   - 0 in case of success
> + *   - %-ENOSPC if no pipe can further reduce its link bpp
> + *   - Other negative error, if modesetting the selected pipe failed
> + */
> +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> +			     struct intel_link_bw_limits *limits,
> +			     u8 pipe_mask,
> +			     const char *reason)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	enum pipe max_bpp_pipe = INVALID_PIPE;
> +	struct intel_crtc *crtc;
> +	int max_bpp = 0;
> +
> +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
> +		struct intel_crtc_state *crtc_state;
> +		int link_bpp;
> +
> +		if (limits->min_bpp_reached_pipes & BIT(crtc->pipe))
> +			continue;
> +
> +		crtc_state = intel_atomic_get_crtc_state(&state->base,
> +							 crtc);
> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +
> +		if (crtc_state->dsc.compression_enable)
> +			link_bpp = crtc_state->dsc.compressed_bpp;
> +		else
> +			/*
> +			 * TODO: for YUV420 the actual link bpp is only half
> +			 * of the pipe bpp value. The MST encoder's BW allocation
> +			 * is based on the pipe bpp value, set the actual link bpp
> +			 * limit here once the MST BW allocation is fixed.
> +			 */
> +			link_bpp = crtc_state->pipe_bpp;

Not quite sure how we should handle all this in the end. IIRC the current
SST logic will attempt both 4:4:4 and 4:2:0 immediately. Dunno if that
makes sense or if we should try to stick to 4:4:4 a bit more aggressively
before allowing 4:2:0 fallback. But I guess that's more or less the
same kind of problem as the DSC vs. no DSC issue.

I was also pondering if the respect_downstream_limits stuff could
also matter here, but I think we use that just for some TMDS link
stuff so there should be no wider implications from it.

> +
> +		if (link_bpp > max_bpp) {
> +			max_bpp = link_bpp;
> +			max_bpp_pipe = crtc->pipe;
> +		}
> +	}
> +
> +	if (max_bpp_pipe == INVALID_PIPE)
> +		return -ENOSPC;
> +
> +	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
> +
> +	return intel_modeset_pipes_in_mask_early(state, reason,
> +						 BIT(max_bpp_pipe));
> +}
> +
> +/**
> + * intel_link_bw_set_min_bpp_for_pipe - set link bpp limit for a pipe to its minimum
> + * @state: atomic state
> + * @old_limits: link BW limits
> + * @new_limits: link BW limits
> + * @pipe: pipe
> + *
> + * Set the link bpp limit for @pipe in @new_limits to its value in
> + * @old_limits and mark this limit as the minimum. This function must be
> + * called after a pipe's compute config function failed, @old_limits
> + * containing the bpp limit with which compute config previously passed.
> + *
> + * The function will fail if setting a minimum is not possible, either
> + * because the old and new limits match (and so would lead to a pipe compute
> + * config failure) or the limit is already at the minimum.
> + *
> + * Returns %true in case of success.
> + */
> +bool
> +intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
> +				   const struct intel_link_bw_limits *old_limits,
> +				   struct intel_link_bw_limits *new_limits,
> +				   enum pipe pipe)
> +{
> +	if (pipe == INVALID_PIPE)
> +		return false;
> +
> +	if (new_limits->min_bpp_reached_pipes & BIT(pipe))
> +		return false;

I suppose this check is a bit redundant and it should also be
caught by the == check below. But I suppose no harm in having this
too.

The naming is still bugging me though. The "min_bpp" might end up
being a bit confusing since we have a min_bpp member in the limits
but we're setting the max_bpp here. Maybe s/min_bpp/bpp_limit/ or
something like that would be a bit better?

> +
> +	if (new_limits->max_bpp_x16[pipe] ==
> +	    old_limits->max_bpp_x16[pipe])
> +		return false;
> +
> +	new_limits->max_bpp_x16[pipe] =
> +		old_limits->max_bpp_x16[pipe];
> +	new_limits->min_bpp_reached_pipes |= BIT(pipe);
> +
> +	return true;
> +}
> +
> +static int check_all_link_config(struct intel_atomic_state *state,
> +				 struct intel_link_bw_limits *limits)
> +{
> +	/* TODO: Check all shared display link configurations like FDI */
> +	return 0;
> +}
> +
> +static bool
> +assert_link_limit_change_valid(struct drm_i915_private *i915,
> +			       const struct intel_link_bw_limits *old_limits,
> +			       const struct intel_link_bw_limits *new_limits)
> +{
> +	bool bpps_changed = false;
> +	enum pipe pipe;
> +
> +	for_each_pipe(i915, pipe) {
> +		/* The bpp limit can only decrease. */
> +		if (drm_WARN_ON(&i915->drm,
> +				new_limits->max_bpp_x16[pipe] >
> +				old_limits->max_bpp_x16[pipe]))
> +			return false;
> +
> +		if (new_limits->max_bpp_x16[pipe] <
> +		    old_limits->max_bpp_x16[pipe])
> +			bpps_changed = true;
> +	}
> +
> +	/* At least one limit must change. */
> +	if (drm_WARN_ON(&i915->drm,
> +			!bpps_changed))
> +		return false;
> +
> +	return true;
> +}
> +
> +/**
> + * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
> + * @state: atomic state
> + * @new_limits: link BW limits
> + *
> + * Check the configuration of all shared display links in @state and set new BW
> + * limits in @new_limits if there is a BW limitation.
> + *
> + * Returns:
> + *   - 0 if the confugration is valid
> + *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
> + *     with fallback values with which the configuration of all CRTCs
> + *     in @state must be recomputed
> + *   - Other negative error, if the configuration is invalid without a
> + *     fallback possibility, or the check failed for another reason
> + */
> +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> +			       struct intel_link_bw_limits *new_limits)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_link_bw_limits old_limits = *new_limits;
> +	int ret;
> +
> +	ret = check_all_link_config(state, new_limits);
> +	if (ret != -EAGAIN)
> +		return ret;
> +
> +	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
> +		return -EINVAL;
> +
> +	return -EAGAIN;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
> new file mode 100644
> index 0000000000000..0f666c9712f3c
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef __INTEL_LINK_BW_H__
> +#define __INTEL_LINK_BW_H__
> +
> +#include <linux/types.h>
> +
> +#include "intel_display_limits.h"
> +
> +struct drm_i915_private;
> +
> +struct intel_atomic_state;
> +struct intel_crtc_state;
> +
> +struct intel_link_bw_limits {
> +	u8 min_bpp_reached_pipes;
> +	/* in 1/16 bpp units */
> +	int max_bpp_x16[I915_MAX_PIPES];
> +};
> +
> +void intel_link_bw_init_limits(struct drm_i915_private *i915,
> +			       struct intel_link_bw_limits *limits);
> +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
> +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> +			     struct intel_link_bw_limits *limits,
> +			     u8 pipe_mask,
> +			     const char *reason);
> +bool intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
> +					const struct intel_link_bw_limits *old_limits,
> +					struct intel_link_bw_limits *new_limits,
> +					enum pipe pipe);
> +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> +			       struct intel_link_bw_limits *new_limits);
> +
> +#endif
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-15 23:13     ` Imre Deak
@ 2023-09-19 15:35       ` Ville Syrjälä
  2023-09-19 17:45         ` Imre Deak
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 15:35 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Sat, Sep 16, 2023 at 02:13:53AM +0300, Imre Deak wrote:
> On Fri, Sep 15, 2023 at 10:31:05PM +0300, Ville Syrjälä wrote:
> > On Thu, Sep 14, 2023 at 10:26:44PM +0300, Imre Deak wrote:
> > > At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
> > > lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
> > > link bpp in this case, until pipe B uses only up to 2 FDI lanes.
> > > 
> > > For this instead of the encoder compute config retry loop - which
> > > reduced link bpp only for the encoder's pipe - reduce the maximum link
> > > bpp for pipe B/C as required after all CRTC states are computed and
> > > recompute the CRTC states with the new bpp limit.
> > > 
> > > v2:
> > > - Don't assume that a CRTC is already in the atomic state, while
> > >   reducing its link bpp.
> > > - Add DocBook description to intel_fdi_atomic_check_link().
> > > v3:
> > > - Enable BW management for FDI links in a separate patch. (Ville)
> > > 
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
> > >  drivers/gpu/drm/i915/display/intel_crt.c     |  7 ++
> > >  drivers/gpu/drm/i915/display/intel_display.c | 14 +---
> > >  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
> > >  drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
> > >  drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
> > >  drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
> > >  drivers/gpu/drm/i915/display/intel_lvds.c    | 10 ++-
> > >  drivers/gpu/drm/i915/display/intel_sdvo.c    | 10 ++-
> > >  9 files changed, 107 insertions(+), 41 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > index 634b14116d9dd..8b5d26cd3b85e 100644
> > > --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > @@ -19,6 +19,7 @@
> > >  #include "intel_fifo_underrun.h"
> > >  #include "intel_hdmi.h"
> > >  #include "intel_hotplug.h"
> > > +#include "intel_link_bw.h"
> > >  #include "intel_sdvo.h"
> > >  #include "vlv_sideband.h"
> > >  
> > > @@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
> > >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > >  	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > >  
> > > -	if (HAS_PCH_SPLIT(i915))
> > > +	if (HAS_PCH_SPLIT(i915)) {
> > >  		crtc_state->has_pch_encoder = true;
> > > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > > +			return -EINVAL;
> > > +	}
> > >  
> > >  	if (IS_G4X(i915))
> > >  		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> > > index f6df6c4fa72ef..7aa89d0fa3d6c 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_crt.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> > > @@ -49,6 +49,7 @@
> > >  #include "intel_gmbus.h"
> > >  #include "intel_hotplug.h"
> > >  #include "intel_hotplug_irq.h"
> > > +#include "intel_link_bw.h"
> > >  #include "intel_load_detect.h"
> > >  #include "intel_pch_display.h"
> > >  #include "intel_pch_refclk.h"
> > > @@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
> > >  		return -EINVAL;
> > >  
> > >  	pipe_config->has_pch_encoder = true;
> > > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > +		return -EINVAL;
> > > +
> > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > >  
> > >  	return 0;
> > > @@ -435,6 +439,9 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
> > >  		return -EINVAL;
> > >  
> > >  	pipe_config->has_pch_encoder = true;
> > > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > +		return -EINVAL;
> > > +
> > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > >  
> > >  	/* LPT FDI RX only supports 8bpc. */
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > > index 29816153fdd59..aad16dcceb788 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > @@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > >  	struct drm_connector_state *connector_state;
> > >  	int pipe_src_w, pipe_src_h;
> > >  	int base_bpp, ret, i;
> > > -	bool retry = true;
> > >  
> > >  	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
> > >  
> > > @@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > >  			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> > >  			    crtc->base.base.id, crtc->base.name,
> > >  			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> > > +		crtc_state->bw_constrained = true;
> > >  	}
> > >  
> > >  	base_bpp = crtc_state->pipe_bpp;
> > > @@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > >  			crtc_state->output_types |= BIT(encoder->type);
> > >  	}
> > >  
> > > -encoder_retry:
> > >  	/* Ensure the port clock defaults are reset when retrying. */
> > >  	crtc_state->port_clock = 0;
> > >  	crtc_state->pixel_multiplier = 1;
> > > @@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > >  	ret = intel_crtc_compute_config(state, crtc);
> > >  	if (ret == -EDEADLK)
> > >  		return ret;
> > > -	if (ret == -EAGAIN) {
> > > -		if (drm_WARN(&i915->drm, !retry,
> > > -			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
> > > -			     crtc->base.base.id, crtc->base.name))
> > > -			return -EINVAL;
> > > -
> > > -		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
> > > -			    crtc->base.base.id, crtc->base.name);
> > > -		retry = false;
> > > -		goto encoder_retry;
> > > -	}
> > >  	if (ret < 0) {
> > >  		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
> > >  			    crtc->base.base.id, crtc->base.name, ret);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > > index d5e6813d36c8f..03010accc1c7f 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > @@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
> > >  	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> > >  	int max_link_bpp_x16;
> > >  
> > > -	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> > > +	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
> > > +			       to_bpp_x16(limits->pipe.max_bpp));
> > >  
> > >  	if (!dsc) {
> > >  		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > index 4d7d524c68017..ad01915a4a39b 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > @@ -13,6 +13,7 @@
> > >  #include "intel_display_types.h"
> > >  #include "intel_fdi.h"
> > >  #include "intel_fdi_regs.h"
> > > +#include "intel_link_bw.h"
> > >  
> > >  struct intel_fdi_funcs {
> > >  	void (*fdi_link_train)(struct intel_crtc *crtc,
> > > @@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
> > >  }
> > >  
> > >  static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > > -			       struct intel_crtc_state *pipe_config)
> > > +			       struct intel_crtc_state *pipe_config,
> > > +			       enum pipe *pipe_to_reduce)
> > >  {
> > >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > >  	struct drm_atomic_state *state = pipe_config->uapi.state;
> > >  	struct intel_crtc *other_crtc;
> > >  	struct intel_crtc_state *other_crtc_state;
> > >  
> > > +	*pipe_to_reduce = pipe;
> > > +
> > >  	drm_dbg_kms(&dev_priv->drm,
> > >  		    "checking fdi config on pipe %c, lanes %i\n",
> > >  		    pipe_name(pipe), pipe_config->fdi_lanes);
> > > @@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > >  		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
> > >  			drm_dbg_kms(&dev_priv->drm,
> > >  				    "fdi link B uses too many lanes to enable link C\n");
> > > +
> > > +			*pipe_to_reduce = PIPE_B;
> > > +
> > >  			return -EINVAL;
> > >  		}
> > >  		return 0;
> > > @@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> > >  	struct drm_device *dev = crtc->base.dev;
> > >  	struct drm_i915_private *i915 = to_i915(dev);
> > >  	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> > > -	int lane, link_bw, fdi_dotclock, ret;
> > > -	bool needs_recompute = false;
> > > +	int lane, link_bw, fdi_dotclock;
> > >  
> > > -retry:
> > >  	/* FDI is a binary signal running at ~2.7GHz, encoding
> > >  	 * each output octet as 10 bits. The actual frequency
> > >  	 * is stored as a divider into a 100MHz clock, and the
> > > @@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> > >  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
> > >  			       link_bw, &pipe_config->fdi_m_n, false);
> > >  
> > > -	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
> > > -	if (ret == -EDEADLK)
> > > +	return 0;
> > > +}
> > > +
> > > +static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
> > > +				     struct intel_crtc *crtc,
> > > +				     struct intel_crtc_state *pipe_config,
> > > +				     struct intel_link_bw_limits *limits)
> > > +{
> > > +	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> > > +	enum pipe pipe_to_reduce;
> > > +	int ret;
> > > +
> > > +	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
> > > +				  &pipe_to_reduce);
> > > +	if (ret != -EINVAL)
> > >  		return ret;
> > >  
> > > -	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
> > > -		pipe_config->pipe_bpp -= 2*3;
> > > -		drm_dbg_kms(&i915->drm,
> > > -			    "fdi link bw constraint, reducing pipe bpp to %i\n",
> > > -			    pipe_config->pipe_bpp);
> > > -		needs_recompute = true;
> > > -		pipe_config->bw_constrained = true;
> > > -
> > > -		goto retry;
> > > +	ret = intel_link_bw_reduce_bpp(state, limits,
> > > +				       BIT(pipe_to_reduce),
> > > +				       "FDI link BW");
> > > +
> > > +	return ret ? : -EAGAIN;
> > > +}
> > > +
> > > +/**
> > > + * intel_fdi_atomic_check_link - check all modeset FDI link configuration
> > > + * @state: intel atomic state
> > > + * @limits: link BW limits
> > > + *
> > > + * Check the link configuration for all modeset FDI outputs. If the
> > > + * configuration is invalid @limits will be updated if possible to
> > > + * reduce the total BW, after which the configuration for all CRTCs in
> > > + * @state must be recomputed with the updated @limits.
> > > + *
> > > + * Returns:
> > > + *   - 0 if the confugration is valid
> > > + *   - %-EAGAIN, if the configuration is invalid and @limits got updated
> > > + *     with fallback values with which the configuration of all CRTCs
> > > + *     in @state must be recomputed
> > > + *   - Other negative error, if the configuration is invalid without a
> > > + *     fallback possibility, or the check failed for another reason
> > > + */
> > > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > > +				struct intel_link_bw_limits *limits)
> > > +{
> > > +	struct intel_crtc *crtc;
> > > +	struct intel_crtc_state *crtc_state;
> > > +	int i;
> > > +
> > > +	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> > > +		int ret;
> > > +
> > > +		if (!crtc_state->has_pch_encoder ||
> > > +		    !intel_crtc_needs_modeset(crtc_state) ||
> > > +		    !crtc_state->hw.enable)
> > > +			continue;
> > > +
> > > +		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
> > > +		if (ret)
> > > +			return ret;
> > >  	}
> > >  
> > > -	if (needs_recompute)
> > > -		return -EAGAIN;
> > > -
> > > -	return ret;
> > > +	return 0;
> > >  }
> > >  
> > >  static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > index 1cdb86172702f..129444c580f27 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > @@ -8,14 +8,18 @@
> > >  
> > >  enum pipe;
> > >  struct drm_i915_private;
> > > +struct intel_atomic_state;
> > >  struct intel_crtc;
> > >  struct intel_crtc_state;
> > >  struct intel_encoder;
> > > +struct intel_link_bw_limits;
> > >  
> > >  int intel_fdi_link_freq(struct drm_i915_private *i915,
> > >  			const struct intel_crtc_state *pipe_config);
> > >  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> > >  			   struct intel_crtc_state *pipe_config);
> > > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > > +				struct intel_link_bw_limits *limits);
> > >  void intel_fdi_normal_train(struct intel_crtc *crtc);
> > >  void ilk_fdi_disable(struct intel_crtc *crtc);
> > >  void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > index 22494772b9d59..aacf22bab3135 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > @@ -160,7 +160,12 @@ intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> > >  static int check_all_link_config(struct intel_atomic_state *state,
> > >  				 struct intel_link_bw_limits *limits)
> > >  {
> > > -	/* TODO: Check all shared display link configurations like FDI */
> > > +	int ret;
> > > +
> > > +	ret = intel_fdi_atomic_check_link(state, limits);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > >  	return 0;
> > >  }
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> > > index 3ace56979b70e..0366d4cc6b72b 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> > > @@ -48,6 +48,7 @@
> > >  #include "intel_dpll.h"
> > >  #include "intel_fdi.h"
> > >  #include "intel_gmbus.h"
> > > +#include "intel_link_bw.h"
> > >  #include "intel_lvds.h"
> > >  #include "intel_lvds_regs.h"
> > >  #include "intel_panel.h"
> > > @@ -425,6 +426,12 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> > >  		return -EINVAL;
> > >  	}
> > >  
> > > +	if (HAS_PCH_SPLIT(i915)) {
> > > +		crtc_state->has_pch_encoder = true;
> > > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > > +			return -EINVAL;
> > > +	}
> > > +
> > >  	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
> > >  		lvds_bpp = 8*3;
> > >  	else
> > > @@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> > >  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> > >  		return -EINVAL;
> > >  
> > > -	if (HAS_PCH_SPLIT(i915))
> > > -		crtc_state->has_pch_encoder = true;
> > > -
> > >  	ret = intel_panel_fitting(crtc_state, conn_state);
> > >  	if (ret)
> > >  		return ret;
> > > diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > index 135a2527fd1b4..3c912f3bc10ba 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > @@ -48,6 +48,7 @@
> > >  #include "intel_gmbus.h"
> > >  #include "intel_hdmi.h"
> > >  #include "intel_hotplug.h"
> > > +#include "intel_link_bw.h"
> > >  #include "intel_panel.h"
> > >  #include "intel_sdvo.h"
> > >  #include "intel_sdvo_regs.h"
> > > @@ -1351,14 +1352,17 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
> > >  	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> > >  	struct drm_display_mode *mode = &pipe_config->hw.mode;
> > >  
> > > +	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
> > > +		pipe_config->has_pch_encoder = true;
> > > +		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > +			return -EINVAL;
> > > +	}
> > > +
> > >  	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
> > >  	pipe_config->pipe_bpp = 8*3;
> > 
> > This seems borked. I think we want to force this to 8bpc only if we're
> > higher currently.
> 
> This would fail the modeset if pipe_bpp would need to be reduced to 6*3
> due to a BW limit and that's what happens before this change as well
> afaics. I agree it's strange to detect that only later in the retry loop
> and the above should return already error in that case. Are you ok with
> that (if crtc_state->max_link_bpp < 8*3 -> return -EINVAL) ?

I don't think forcing to 8bpc makes any real sense, other than as an
upper limit (since SDVO can only transmit 8bpc data). So I think this
should just use 'min(pipe_bpp, 8*3)'. But we should do that change
as a separate patch.

> 
> If you meant that increasing an EDID (6 bpc) baseline to 8 bpc (if BW
> allows otherwise) doesn't make sense either here, that would be an issue
> already before this change. I can add a FIXME: comment for that.
> 
> > Same for the LVDS case I think, though that one is a bit more sane atm
> > since it looks at the bw_constrained flag, though I don't think we
> > really need that flag anymore, at least for this purpose.
> 
> This patch doesn't change the behavior there either, but bw_constrained
> could be replaced with crtc_state->max_link_bpp < lvds_bpp (as a
> follow-up imo).
> 
> > Hmm, but maybe we do still need it for the LPT FDI case where we do
> > actually want to increase the bpc to 8 if the EDID baseline is below
> > that.
> 
> I suppose bw_constrained && pipe_bpp < 24 there could be also replaced
> with crtc_state->max_link_bpp < 24.
> 
> > >  	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > >  
> > > -	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
> > > -		pipe_config->has_pch_encoder = true;
> > > -
> > >  	/*
> > >  	 * We need to construct preferred input timings based on our
> > >  	 * output timings.  To do that, we have to set the output
> > > -- 
> > > 2.37.2
> > 
> > -- 
> > Ville Syrjälä
> > Intel

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links Imre Deak
@ 2023-09-19 15:44   ` Ville Syrjälä
  2023-09-19 18:14     ` Imre Deak
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-19 15:44 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:45PM +0300, Imre Deak wrote:
> Recompute the state of all CRTCs on an FDI link during a modeset that
> may be affected by the modeset of other CRTCs on the same link. This
> ensures that each CRTC on the link maximizes its BW use (after another
> CRTC is disabled).
> 
> In practice this means recomputing pipe B's config on IVB if pipe C gets
> disabled.
> 
> v2:
> - Add the change recomputing affected CRTC states in a separate patch.
>   (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c |  4 ++
>  drivers/gpu/drm/i915/display/intel_fdi.c     | 53 ++++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_fdi.h     |  1 +
>  3 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index aad16dcceb788..31297a333f50e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -6210,6 +6210,10 @@ int intel_atomic_check_config(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> +	ret = intel_fdi_add_affected_crtcs(state);
> +	if (ret)
> +		return ret;
> +
>  	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
>  		if (!intel_crtc_needs_modeset(new_crtc_state)) {
>  			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
> diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> index ad01915a4a39b..d723ae7e10d71 100644
> --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> @@ -120,6 +120,59 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
>  	dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
>  }
>  
> +/**
> + * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
> + * @state: intel atomic state
> + *
> + * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
> + * known to affect the available FDI BW for the former CRTC. In practice this
> + * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
> + * CRTC C) and CRTC C is getting disabled.
> + *
> + * Returns 0 in case of success, or a negative error code otherwise.
> + */
> +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_crtc_state *old_crtc_state;
> +	struct intel_crtc_state *new_crtc_state;

Both look like they can be const.

> +	struct intel_crtc *crtc;
> +
> +	if (!IS_IVYBRIDGE(i915))

Should also check num_pipes==3 since pipe C can (at least in theory)
be fused off.

> +		return 0;
> +
> +	crtc = intel_crtc_for_pipe(i915, PIPE_C);
> +	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> +
> +	if (!new_crtc_state)
> +		return 0;
> +
> +	old_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);

old vs. new mixup

> +
> +	if (!old_crtc_state->fdi_lanes)
> +		return 0;
> +
> +	if (!intel_crtc_needs_modeset(new_crtc_state))
> +		return 0;
> +
> +	if (new_crtc_state->uapi.enable)
> +		return 0;

We could be switching pipe C from driving a PCH port to driving
the CPU eDP port. So this check seems a bit wrong.

> +
> +	crtc = intel_crtc_for_pipe(i915, PIPE_B);
> +	new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> +
> +	if (IS_ERR(new_crtc_state))
> +		return PTR_ERR(old_crtc_state);
> +
> +	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
> +	if (!old_crtc_state->fdi_lanes)
> +		return 0;
> +
> +	return intel_modeset_pipes_in_mask_early(state,
> +						 "FDI link BW decrease on pipe C",
> +						 BIT(PIPE_B));
> +}
> +
>  /* units of 100MHz */
>  static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
>  {
> diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> index 129444c580f27..eb02b967bb440 100644
> --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> @@ -14,6 +14,7 @@ struct intel_crtc_state;
>  struct intel_encoder;
>  struct intel_link_bw_limits;
>  
> +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
>  int intel_fdi_link_freq(struct drm_i915_private *i915,
>  			const struct intel_crtc_state *pipe_config);
>  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v5 09/25] drm/i915: Add helpers for BW management on shared display links
  2023-09-19 15:21       ` Ville Syrjälä
@ 2023-09-19 17:40         ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-19 17:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Sep 19, 2023 at 06:21:52PM +0300, Ville Syrjälä wrote:
> On Mon, Sep 18, 2023 at 09:25:05PM +0300, Imre Deak wrote:
> > At the moment a modeset fails if the config computation of a pipe can't
> > fit its required BW to the available link BW even though the limitation
> > may be resolved by reducing the BW requirement of other pipes.
> > 
> > To improve the above this patch adds helper functions checking the
> > overall BW limits after all CRTC states have been computed. If the check
> > fails the maximum link bpp for a selected pipe will be reduced and all
> > the CRTC states will be recomputed until either the overall BW limit
> > check passes, or further bpp reduction is not possible (because all
> > pipes/encoders sharing the link BW reached their minimum link bpp).
> > 
> > Atm, the MST encoder allocates twice the required BW for YUV420 format
> > streams. A follow-up patchset will fix that, add a code comment about
> > this.
> > 
> > This change prepares for upcoming patches enabling the above BW
> > management on FDI and MST links.
> > 
> > v2:
> > - Rename intel_crtc_state::max_link_bpp to max_link_bpp_x16 and
> >   intel_link_bw_limits::max_bpp to max_bpp_x16. (Jani)
> > v3:
> > - Add the helper functions in a separate patch. (Ville)
> > - Add the functions to intel_link_bw.c instead of intel_atomic.c (Ville)
> > - Return -ENOSPC instead of -EINVAL to userspace in case of a link BW
> >   limit failure.
> > v4:
> > - Make intel_atomic_check_config() static.
> > v5: (Ville)
> > - Rename intel_link_bw_limits::min_bpp_pipes to min_bpp_reached_pipes
> >   and intel_link_bw_reset_pipe_limit_to_min() to
> >   intel_link_bw_set_min_bpp_for_pipe().
> > - Rename pipe_bpp to link_bpp in intel_link_bw_reduce_bpp().
> > - Add FIXME: comment about MST encoder's YUV420 BW allocation and
> >   tracking the link bpp limit accordingly.
> > 
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/Makefile                 |   1 +
> >  drivers/gpu/drm/i915/display/intel_crtc.c     |   1 +
> >  drivers/gpu/drm/i915/display/intel_display.c  |  65 ++++-
> >  .../drm/i915/display/intel_display_types.h    |   3 +-
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |   4 +
> >  drivers/gpu/drm/i915/display/intel_link_bw.c  | 232 ++++++++++++++++++
> >  drivers/gpu/drm/i915/display/intel_link_bw.h  |  38 +++
> >  7 files changed, 339 insertions(+), 5 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.c
> >  create mode 100644 drivers/gpu/drm/i915/display/intel_link_bw.h
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index 1b2e02e9d92cb..de4967c141f00 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -268,6 +268,7 @@ i915-y += \
> >  	display/intel_hotplug.o \
> >  	display/intel_hotplug_irq.o \
> >  	display/intel_hti.o \
> > +	display/intel_link_bw.o \
> >  	display/intel_load_detect.o \
> >  	display/intel_lpe_audio.o \
> >  	display/intel_modeset_lock.o \
> > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> > index 182c6dd64f47c..1eda6a9f19aa8 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> > @@ -175,6 +175,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> >  	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> >  	crtc_state->scaler_state.scaler_id = -1;
> >  	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> > +	crtc_state->max_link_bpp_x16 = INT_MAX;
> >  }
> >  
> >  static struct intel_crtc *intel_crtc_alloc(void)
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index 3bdc338a22e19..537884035304c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -87,6 +87,7 @@
> >  #include "intel_frontbuffer.h"
> >  #include "intel_hdmi.h"
> >  #include "intel_hotplug.h"
> > +#include "intel_link_bw.h"
> >  #include "intel_lvds.h"
> >  #include "intel_lvds_regs.h"
> >  #include "intel_modeset_setup.h"
> > @@ -4596,7 +4597,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
> >  
> >  static int
> >  intel_modeset_pipe_config(struct intel_atomic_state *state,
> > -			  struct intel_crtc *crtc)
> > +			  struct intel_crtc *crtc,
> > +			  const struct intel_link_bw_limits *limits)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> >  	struct intel_crtc_state *crtc_state =
> > @@ -4628,6 +4630,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> >  	if (ret)
> >  		return ret;
> >  
> > +	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
> > +
> > +	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
> > +		drm_dbg_kms(&i915->drm,
> > +			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> > +			    crtc->base.base.id, crtc->base.name,
> > +			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> > +	}
> > +
> >  	base_bpp = crtc_state->pipe_bpp;
> >  
> >  	/*
> > @@ -6218,7 +6229,9 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
> >  	return 0;
> >  }
> >  
> > -static int intel_atomic_check_config(struct intel_atomic_state *state)
> > +static int intel_atomic_check_config(struct intel_atomic_state *state,
> > +				     struct intel_link_bw_limits *limits,
> > +				     enum pipe *failed_pipe)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(state->base.dev);
> >  	struct intel_crtc_state *new_crtc_state;
> > @@ -6226,6 +6239,8 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  	int ret;
> >  	int i;
> >  
> > +	*failed_pipe = INVALID_PIPE;
> > +
> >  	ret = intel_bigjoiner_add_affected_crtcs(state);
> >  	if (ret)
> >  		return ret;
> > @@ -6251,7 +6266,7 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  		if (!new_crtc_state->hw.enable)
> >  			continue;
> >  
> > -		ret = intel_modeset_pipe_config(state, crtc);
> > +		ret = intel_modeset_pipe_config(state, crtc, limits);
> >  		if (ret)
> >  			break;
> >  
> > @@ -6260,9 +6275,51 @@ static int intel_atomic_check_config(struct intel_atomic_state *state)
> >  			break;
> >  	}
> >  
> > +	if (ret)
> > +		*failed_pipe = crtc->pipe;
> > +
> >  	return ret;
> >  }
> >  
> > +static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	struct intel_link_bw_limits new_limits;
> > +	struct intel_link_bw_limits old_limits;
> > +	int ret;
> > +
> > +	intel_link_bw_init_limits(i915, &new_limits);
> > +	old_limits = new_limits;
> > +
> > +	while (true) {
> > +		enum pipe failed_pipe;
> > +
> > +		ret = intel_atomic_check_config(state, &new_limits,
> > +						&failed_pipe);
> > +		if (ret) {
> > +			/*
> > +			 * The bpp limit for a pipe is below the minimum it supports, set the
> > +			 * limit to the minimum and recalculate the config.
> > +			 */
> > +			if (ret == -EINVAL &&
> > +			    intel_link_bw_set_min_bpp_for_pipe(state,
> > +							       &old_limits,
> > +							       &new_limits,
> > +							       failed_pipe))
> > +				continue;
> > +
> > +			break;
> > +		}
> > +
> > +		old_limits = new_limits;
> > +
> > +		ret = intel_link_bw_atomic_check(state, &new_limits);
> > +		if (ret != -EAGAIN)
> > +			break;
> > +	}
> > +
> > +	return ret;
> > +}
> >  /**
> >   * intel_atomic_check - validate state object
> >   * @dev: drm device
> > @@ -6307,7 +6364,7 @@ int intel_atomic_check(struct drm_device *dev,
> >  			return ret;
> >  	}
> >  
> > -	ret = intel_atomic_check_config(state);
> > +	ret = intel_atomic_check_config_and_link(state);
> >  	if (ret)
> >  		goto fail;
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 50a22261f5eec..4d7948fa4bbba 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1189,7 +1189,8 @@ struct intel_crtc_state {
> >  		u32 ctrl, div;
> >  	} dsi_pll;
> >  
> > -	int pipe_bpp;
> > +	int max_link_bpp_x16;	/* in 1/16 bpp units */
> > +	int pipe_bpp;		/* in 1 bpp units */
> >  	struct intel_link_m_n dp_m_n;
> >  
> >  	/* m2_n2 for eDP downclock */
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index a914d83ab3dde..f26c2eecb2778 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -157,6 +157,10 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
> >  	int slots = -EINVAL;
> >  	int link_bpp;
> >  
> > +	/*
> > +	 * FIXME: allocate the BW according to link_bpp, which in the case of
> > +	 * YUV420 is only half of the pipe bpp value.
> > +	 */
> >  	slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
> >  						     to_bpp_int(limits->link.max_bpp_x16),
> >  						     to_bpp_int(limits->link.min_bpp_x16),
> > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > new file mode 100644
> > index 0000000000000..9b6d0891345d7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > @@ -0,0 +1,232 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#include "i915_drv.h"
> > +
> > +#include "intel_atomic.h"
> > +#include "intel_display_types.h"
> > +#include "intel_dp_mst.h"
> > +#include "intel_fdi.h"
> > +#include "intel_link_bw.h"
> > +
> > +/**
> > + * intel_link_bw_init_limits - initialize BW limits
> > + * @i915: device instance
> > + * @limits: link BW limits
> > + *
> > + * Initialize @limits.
> > + */
> > +void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
> > +{
> > +	enum pipe pipe;
> > +
> > +	limits->min_bpp_reached_pipes = 0;
> > +	for_each_pipe(i915, pipe)
> > +		limits->max_bpp_x16[pipe] = INT_MAX;
> > +}
> > +
> > +/**
> > + * intel_link_bw_compute_pipe_bpp - compute pipe bpp limited by max link bpp
> > + * @crtc_state: the crtc state
> > + *
> > + * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
> > + * call this function during state computation in the simple case where the
> > + * link bpp will always match the pipe bpp. This is the case for all non-DP
> > + * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
> > + * of DSC compression.
> > + *
> > + * Returns %true in case of success, %false if pipe bpp would need to be
> > + * reduced below its valid range.
> > + */
> > +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
> > +{
> > +	int pipe_bpp = min(crtc_state->pipe_bpp,
> > +			   to_bpp_int(crtc_state->max_link_bpp_x16));
> > +
> > +	pipe_bpp = rounddown(pipe_bpp, 2 * 3);
> > +
> > +	if (pipe_bpp < 6 * 3)
> > +		return false;
> > +
> > +	crtc_state->pipe_bpp = pipe_bpp;
> > +
> > +	return true;
> > +}
> 
> Hmm. The fact that you can't use this for DP makes this rather
> non-generic. Maybe it should just live in intel_fdi.c or something?
> Or are we going to use it for something else as well?

No, it's only used for non-DP FDI encoders, so can move it to
intel_fdi.c

> > +
> > +/**
> > + * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
> > + * @state: atomic state
> > + * @limits: link BW limits
> > + * @pipe_mask: mask of pipes to select from
> > + * @reason: explanation of why bpp reduction is needed
> > + *
> > + * Select the pipe from @pipe_mask with the biggest link bpp value and set the
> > + * maximum of link bpp in @limits below this value. Modeset the selected pipe,
> > + * so that its state will get recomputed.
> > + *
> > + * This function can be called to resolve a link's BW overallocation by reducing
> > + * the link bpp of one pipe on the link and hence reducing the total link BW.
> > + *
> > + * Returns
> > + *   - 0 in case of success
> > + *   - %-ENOSPC if no pipe can further reduce its link bpp
> > + *   - Other negative error, if modesetting the selected pipe failed
> > + */
> > +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> > +			     struct intel_link_bw_limits *limits,
> > +			     u8 pipe_mask,
> > +			     const char *reason)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	enum pipe max_bpp_pipe = INVALID_PIPE;
> > +	struct intel_crtc *crtc;
> > +	int max_bpp = 0;
> > +
> > +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
> > +		struct intel_crtc_state *crtc_state;
> > +		int link_bpp;
> > +
> > +		if (limits->min_bpp_reached_pipes & BIT(crtc->pipe))
> > +			continue;
> > +
> > +		crtc_state = intel_atomic_get_crtc_state(&state->base,
> > +							 crtc);
> > +		if (IS_ERR(crtc_state))
> > +			return PTR_ERR(crtc_state);
> > +
> > +		if (crtc_state->dsc.compression_enable)
> > +			link_bpp = crtc_state->dsc.compressed_bpp;
> > +		else
> > +			/*
> > +			 * TODO: for YUV420 the actual link bpp is only half
> > +			 * of the pipe bpp value. The MST encoder's BW allocation
> > +			 * is based on the pipe bpp value, set the actual link bpp
> > +			 * limit here once the MST BW allocation is fixed.
> > +			 */
> > +			link_bpp = crtc_state->pipe_bpp;
> 
> Not quite sure how we should handle all this in the end. IIRC the current
> SST logic will attempt both 4:4:4 and 4:2:0 immediately. Dunno if that
> makes sense or if we should try to stick to 4:4:4 a bit more aggressively
> before allowing 4:2:0 fallback. But I guess that's more or less the
> same kind of problem as the DSC vs. no DSC issue.

Ok, didn't think about the 4:4:4 fallback. IIUC the encoder tries both
formats first without then with DSC. This looks to me a reasonable way
BW utilization-wise. Which order the encoder tries the configs could be
encoder specific in any case, selecting one based only on the available
BW (minimum of the sink's and the passed in link - via max_link_bpp -
BW) and the resulting quality. (An additional factor may be the
granularity of its fallback reducing bpp, for instance it could enable
compression already earlier for this.)

For the above the current way of simply decreasing
crtc_state->max_link_bpp_x16 one pipe at a time works I think, even if
for 4:2:0 the encoder will allocate only half of what max_link_bpp would
allow for (the optimal BW usage is still found). In the TODO: I referred
to retrieving and passing back to the encoder the actual link bpp even
in that case, which I suppose would mean instead of the above something
like:

	link_bpp = intel_dp_output_bpp(crtc_state);

This would make things more consistent at least.

> I was also pondering if the respect_downstream_limits stuff could
> also matter here, but I think we use that just for some TMDS link
> stuff so there should be no wider implications from it.

I guess that matters only in how the encoder calculates the min(sink_bw,
link_bw) value for its fallback logic above, so yes it shouldn't matter
for the link BW fallback.

> > +
> > +		if (link_bpp > max_bpp) {
> > +			max_bpp = link_bpp;
> > +			max_bpp_pipe = crtc->pipe;
> > +		}
> > +	}
> > +
> > +	if (max_bpp_pipe == INVALID_PIPE)
> > +		return -ENOSPC;
> > +
> > +	limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
> > +
> > +	return intel_modeset_pipes_in_mask_early(state, reason,
> > +						 BIT(max_bpp_pipe));
> > +}
> > +
> > +/**
> > + * intel_link_bw_set_min_bpp_for_pipe - set link bpp limit for a pipe to its minimum
> > + * @state: atomic state
> > + * @old_limits: link BW limits
> > + * @new_limits: link BW limits
> > + * @pipe: pipe
> > + *
> > + * Set the link bpp limit for @pipe in @new_limits to its value in
> > + * @old_limits and mark this limit as the minimum. This function must be
> > + * called after a pipe's compute config function failed, @old_limits
> > + * containing the bpp limit with which compute config previously passed.
> > + *
> > + * The function will fail if setting a minimum is not possible, either
> > + * because the old and new limits match (and so would lead to a pipe compute
> > + * config failure) or the limit is already at the minimum.
> > + *
> > + * Returns %true in case of success.
> > + */
> > +bool
> > +intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
> > +				   const struct intel_link_bw_limits *old_limits,
> > +				   struct intel_link_bw_limits *new_limits,
> > +				   enum pipe pipe)
> > +{
> > +	if (pipe == INVALID_PIPE)
> > +		return false;
> > +
> > +	if (new_limits->min_bpp_reached_pipes & BIT(pipe))
> > +		return false;
> 
> I suppose this check is a bit redundant and it should also be
> caught by the == check below. But I suppose no harm in having this
> too.

Yes, can move it after the check below as an assert.

> The naming is still bugging me though. The "min_bpp" might end up
> being a bit confusing since we have a min_bpp member in the limits
> but we're setting the max_bpp here. Maybe s/min_bpp/bpp_limit/ or
> something like that would be a bit better?

Ok, will change that.

> > +
> > +	if (new_limits->max_bpp_x16[pipe] ==
> > +	    old_limits->max_bpp_x16[pipe])
> > +		return false;
> > +
> > +	new_limits->max_bpp_x16[pipe] =
> > +		old_limits->max_bpp_x16[pipe];
> > +	new_limits->min_bpp_reached_pipes |= BIT(pipe);
> > +
> > +	return true;
> > +}
> > +
> > +static int check_all_link_config(struct intel_atomic_state *state,
> > +				 struct intel_link_bw_limits *limits)
> > +{
> > +	/* TODO: Check all shared display link configurations like FDI */
> > +	return 0;
> > +}
> > +
> > +static bool
> > +assert_link_limit_change_valid(struct drm_i915_private *i915,
> > +			       const struct intel_link_bw_limits *old_limits,
> > +			       const struct intel_link_bw_limits *new_limits)
> > +{
> > +	bool bpps_changed = false;
> > +	enum pipe pipe;
> > +
> > +	for_each_pipe(i915, pipe) {
> > +		/* The bpp limit can only decrease. */
> > +		if (drm_WARN_ON(&i915->drm,
> > +				new_limits->max_bpp_x16[pipe] >
> > +				old_limits->max_bpp_x16[pipe]))
> > +			return false;
> > +
> > +		if (new_limits->max_bpp_x16[pipe] <
> > +		    old_limits->max_bpp_x16[pipe])
> > +			bpps_changed = true;
> > +	}
> > +
> > +	/* At least one limit must change. */
> > +	if (drm_WARN_ON(&i915->drm,
> > +			!bpps_changed))
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> > +/**
> > + * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
> > + * @state: atomic state
> > + * @new_limits: link BW limits
> > + *
> > + * Check the configuration of all shared display links in @state and set new BW
> > + * limits in @new_limits if there is a BW limitation.
> > + *
> > + * Returns:
> > + *   - 0 if the confugration is valid
> > + *   - %-EAGAIN, if the configuration is invalid and @new_limits got updated
> > + *     with fallback values with which the configuration of all CRTCs
> > + *     in @state must be recomputed
> > + *   - Other negative error, if the configuration is invalid without a
> > + *     fallback possibility, or the check failed for another reason
> > + */
> > +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> > +			       struct intel_link_bw_limits *new_limits)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	struct intel_link_bw_limits old_limits = *new_limits;
> > +	int ret;
> > +
> > +	ret = check_all_link_config(state, new_limits);
> > +	if (ret != -EAGAIN)
> > +		return ret;
> > +
> > +	if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
> > +		return -EINVAL;
> > +
> > +	return -EAGAIN;
> > +}
> > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
> > new file mode 100644
> > index 0000000000000..0f666c9712f3c
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright © 2023 Intel Corporation
> > + */
> > +
> > +#ifndef __INTEL_LINK_BW_H__
> > +#define __INTEL_LINK_BW_H__
> > +
> > +#include <linux/types.h>
> > +
> > +#include "intel_display_limits.h"
> > +
> > +struct drm_i915_private;
> > +
> > +struct intel_atomic_state;
> > +struct intel_crtc_state;
> > +
> > +struct intel_link_bw_limits {
> > +	u8 min_bpp_reached_pipes;
> > +	/* in 1/16 bpp units */
> > +	int max_bpp_x16[I915_MAX_PIPES];
> > +};
> > +
> > +void intel_link_bw_init_limits(struct drm_i915_private *i915,
> > +			       struct intel_link_bw_limits *limits);
> > +bool intel_link_bw_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
> > +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
> > +			     struct intel_link_bw_limits *limits,
> > +			     u8 pipe_mask,
> > +			     const char *reason);
> > +bool intel_link_bw_set_min_bpp_for_pipe(struct intel_atomic_state *state,
> > +					const struct intel_link_bw_limits *old_limits,
> > +					struct intel_link_bw_limits *new_limits,
> > +					enum pipe pipe);
> > +int intel_link_bw_atomic_check(struct intel_atomic_state *state,
> > +			       struct intel_link_bw_limits *new_limits);
> > +
> > +#endif
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C
  2023-09-19 15:35       ` Ville Syrjälä
@ 2023-09-19 17:45         ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-19 17:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Sep 19, 2023 at 06:35:30PM +0300, Ville Syrjälä wrote:
> On Sat, Sep 16, 2023 at 02:13:53AM +0300, Imre Deak wrote:
> > On Fri, Sep 15, 2023 at 10:31:05PM +0300, Ville Syrjälä wrote:
> > > On Thu, Sep 14, 2023 at 10:26:44PM +0300, Imre Deak wrote:
> > > > At the moment modesetting pipe C on IVB will fail if pipe B uses 4 FDI
> > > > lanes. Make the BW sharing more dynamic by trying to reduce pipe B's
> > > > link bpp in this case, until pipe B uses only up to 2 FDI lanes.
> > > > 
> > > > For this instead of the encoder compute config retry loop - which
> > > > reduced link bpp only for the encoder's pipe - reduce the maximum link
> > > > bpp for pipe B/C as required after all CRTC states are computed and
> > > > recompute the CRTC states with the new bpp limit.
> > > > 
> > > > v2:
> > > > - Don't assume that a CRTC is already in the atomic state, while
> > > >   reducing its link bpp.
> > > > - Add DocBook description to intel_fdi_atomic_check_link().
> > > > v3:
> > > > - Enable BW management for FDI links in a separate patch. (Ville)
> > > > 
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/display/g4x_hdmi.c      |  6 +-
> > > >  drivers/gpu/drm/i915/display/intel_crt.c     |  7 ++
> > > >  drivers/gpu/drm/i915/display/intel_display.c | 14 +---
> > > >  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +-
> > > >  drivers/gpu/drm/i915/display/intel_fdi.c     | 87 +++++++++++++++-----
> > > >  drivers/gpu/drm/i915/display/intel_fdi.h     |  4 +
> > > >  drivers/gpu/drm/i915/display/intel_link_bw.c |  7 +-
> > > >  drivers/gpu/drm/i915/display/intel_lvds.c    | 10 ++-
> > > >  drivers/gpu/drm/i915/display/intel_sdvo.c    | 10 ++-
> > > >  9 files changed, 107 insertions(+), 41 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > > index 634b14116d9dd..8b5d26cd3b85e 100644
> > > > --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > > +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
> > > > @@ -19,6 +19,7 @@
> > > >  #include "intel_fifo_underrun.h"
> > > >  #include "intel_hdmi.h"
> > > >  #include "intel_hotplug.h"
> > > > +#include "intel_link_bw.h"
> > > >  #include "intel_sdvo.h"
> > > >  #include "vlv_sideband.h"
> > > >  
> > > > @@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
> > > >  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> > > >  	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > > >  
> > > > -	if (HAS_PCH_SPLIT(i915))
> > > > +	if (HAS_PCH_SPLIT(i915)) {
> > > >  		crtc_state->has_pch_encoder = true;
> > > > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > > > +			return -EINVAL;
> > > > +	}
> > > >  
> > > >  	if (IS_G4X(i915))
> > > >  		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> > > > index f6df6c4fa72ef..7aa89d0fa3d6c 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_crt.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> > > > @@ -49,6 +49,7 @@
> > > >  #include "intel_gmbus.h"
> > > >  #include "intel_hotplug.h"
> > > >  #include "intel_hotplug_irq.h"
> > > > +#include "intel_link_bw.h"
> > > >  #include "intel_load_detect.h"
> > > >  #include "intel_pch_display.h"
> > > >  #include "intel_pch_refclk.h"
> > > > @@ -413,6 +414,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
> > > >  		return -EINVAL;
> > > >  
> > > >  	pipe_config->has_pch_encoder = true;
> > > > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > > +		return -EINVAL;
> > > > +
> > > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > > >  
> > > >  	return 0;
> > > > @@ -435,6 +439,9 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
> > > >  		return -EINVAL;
> > > >  
> > > >  	pipe_config->has_pch_encoder = true;
> > > > +	if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > > +		return -EINVAL;
> > > > +
> > > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > > >  
> > > >  	/* LPT FDI RX only supports 8bpc. */
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > > > index 29816153fdd59..aad16dcceb788 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > > @@ -4607,7 +4607,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > > >  	struct drm_connector_state *connector_state;
> > > >  	int pipe_src_w, pipe_src_h;
> > > >  	int base_bpp, ret, i;
> > > > -	bool retry = true;
> > > >  
> > > >  	crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
> > > >  
> > > > @@ -4637,6 +4636,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > > >  			    "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
> > > >  			    crtc->base.base.id, crtc->base.name,
> > > >  			    BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
> > > > +		crtc_state->bw_constrained = true;
> > > >  	}
> > > >  
> > > >  	base_bpp = crtc_state->pipe_bpp;
> > > > @@ -4680,7 +4680,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > > >  			crtc_state->output_types |= BIT(encoder->type);
> > > >  	}
> > > >  
> > > > -encoder_retry:
> > > >  	/* Ensure the port clock defaults are reset when retrying. */
> > > >  	crtc_state->port_clock = 0;
> > > >  	crtc_state->pixel_multiplier = 1;
> > > > @@ -4720,17 +4719,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
> > > >  	ret = intel_crtc_compute_config(state, crtc);
> > > >  	if (ret == -EDEADLK)
> > > >  		return ret;
> > > > -	if (ret == -EAGAIN) {
> > > > -		if (drm_WARN(&i915->drm, !retry,
> > > > -			     "[CRTC:%d:%s] loop in pipe configuration computation\n",
> > > > -			     crtc->base.base.id, crtc->base.name))
> > > > -			return -EINVAL;
> > > > -
> > > > -		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
> > > > -			    crtc->base.base.id, crtc->base.name);
> > > > -		retry = false;
> > > > -		goto encoder_retry;
> > > > -	}
> > > >  	if (ret < 0) {
> > > >  		drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
> > > >  			    crtc->base.base.id, crtc->base.name, ret);
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > > > index d5e6813d36c8f..03010accc1c7f 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > > @@ -2219,7 +2219,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
> > > >  	const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> > > >  	int max_link_bpp_x16;
> > > >  
> > > > -	max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
> > > > +	max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
> > > > +			       to_bpp_x16(limits->pipe.max_bpp));
> > > >  
> > > >  	if (!dsc) {
> > > >  		max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > > index 4d7d524c68017..ad01915a4a39b 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > > @@ -13,6 +13,7 @@
> > > >  #include "intel_display_types.h"
> > > >  #include "intel_fdi.h"
> > > >  #include "intel_fdi_regs.h"
> > > > +#include "intel_link_bw.h"
> > > >  
> > > >  struct intel_fdi_funcs {
> > > >  	void (*fdi_link_train)(struct intel_crtc *crtc,
> > > > @@ -129,13 +130,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
> > > >  }
> > > >  
> > > >  static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > > > -			       struct intel_crtc_state *pipe_config)
> > > > +			       struct intel_crtc_state *pipe_config,
> > > > +			       enum pipe *pipe_to_reduce)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > > >  	struct drm_atomic_state *state = pipe_config->uapi.state;
> > > >  	struct intel_crtc *other_crtc;
> > > >  	struct intel_crtc_state *other_crtc_state;
> > > >  
> > > > +	*pipe_to_reduce = pipe;
> > > > +
> > > >  	drm_dbg_kms(&dev_priv->drm,
> > > >  		    "checking fdi config on pipe %c, lanes %i\n",
> > > >  		    pipe_name(pipe), pipe_config->fdi_lanes);
> > > > @@ -198,6 +202,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > > >  		if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
> > > >  			drm_dbg_kms(&dev_priv->drm,
> > > >  				    "fdi link B uses too many lanes to enable link C\n");
> > > > +
> > > > +			*pipe_to_reduce = PIPE_B;
> > > > +
> > > >  			return -EINVAL;
> > > >  		}
> > > >  		return 0;
> > > > @@ -238,10 +245,8 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> > > >  	struct drm_device *dev = crtc->base.dev;
> > > >  	struct drm_i915_private *i915 = to_i915(dev);
> > > >  	const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> > > > -	int lane, link_bw, fdi_dotclock, ret;
> > > > -	bool needs_recompute = false;
> > > > +	int lane, link_bw, fdi_dotclock;
> > > >  
> > > > -retry:
> > > >  	/* FDI is a binary signal running at ~2.7GHz, encoding
> > > >  	 * each output octet as 10 bits. The actual frequency
> > > >  	 * is stored as a divider into a 100MHz clock, and the
> > > > @@ -261,25 +266,69 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
> > > >  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
> > > >  			       link_bw, &pipe_config->fdi_m_n, false);
> > > >  
> > > > -	ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
> > > > -	if (ret == -EDEADLK)
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
> > > > +				     struct intel_crtc *crtc,
> > > > +				     struct intel_crtc_state *pipe_config,
> > > > +				     struct intel_link_bw_limits *limits)
> > > > +{
> > > > +	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> > > > +	enum pipe pipe_to_reduce;
> > > > +	int ret;
> > > > +
> > > > +	ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
> > > > +				  &pipe_to_reduce);
> > > > +	if (ret != -EINVAL)
> > > >  		return ret;
> > > >  
> > > > -	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
> > > > -		pipe_config->pipe_bpp -= 2*3;
> > > > -		drm_dbg_kms(&i915->drm,
> > > > -			    "fdi link bw constraint, reducing pipe bpp to %i\n",
> > > > -			    pipe_config->pipe_bpp);
> > > > -		needs_recompute = true;
> > > > -		pipe_config->bw_constrained = true;
> > > > -
> > > > -		goto retry;
> > > > +	ret = intel_link_bw_reduce_bpp(state, limits,
> > > > +				       BIT(pipe_to_reduce),
> > > > +				       "FDI link BW");
> > > > +
> > > > +	return ret ? : -EAGAIN;
> > > > +}
> > > > +
> > > > +/**
> > > > + * intel_fdi_atomic_check_link - check all modeset FDI link configuration
> > > > + * @state: intel atomic state
> > > > + * @limits: link BW limits
> > > > + *
> > > > + * Check the link configuration for all modeset FDI outputs. If the
> > > > + * configuration is invalid @limits will be updated if possible to
> > > > + * reduce the total BW, after which the configuration for all CRTCs in
> > > > + * @state must be recomputed with the updated @limits.
> > > > + *
> > > > + * Returns:
> > > > + *   - 0 if the confugration is valid
> > > > + *   - %-EAGAIN, if the configuration is invalid and @limits got updated
> > > > + *     with fallback values with which the configuration of all CRTCs
> > > > + *     in @state must be recomputed
> > > > + *   - Other negative error, if the configuration is invalid without a
> > > > + *     fallback possibility, or the check failed for another reason
> > > > + */
> > > > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > > > +				struct intel_link_bw_limits *limits)
> > > > +{
> > > > +	struct intel_crtc *crtc;
> > > > +	struct intel_crtc_state *crtc_state;
> > > > +	int i;
> > > > +
> > > > +	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> > > > +		int ret;
> > > > +
> > > > +		if (!crtc_state->has_pch_encoder ||
> > > > +		    !intel_crtc_needs_modeset(crtc_state) ||
> > > > +		    !crtc_state->hw.enable)
> > > > +			continue;
> > > > +
> > > > +		ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
> > > > +		if (ret)
> > > > +			return ret;
> > > >  	}
> > > >  
> > > > -	if (needs_recompute)
> > > > -		return -EAGAIN;
> > > > -
> > > > -	return ret;
> > > > +	return 0;
> > > >  }
> > > >  
> > > >  static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > > index 1cdb86172702f..129444c580f27 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> > > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > > @@ -8,14 +8,18 @@
> > > >  
> > > >  enum pipe;
> > > >  struct drm_i915_private;
> > > > +struct intel_atomic_state;
> > > >  struct intel_crtc;
> > > >  struct intel_crtc_state;
> > > >  struct intel_encoder;
> > > > +struct intel_link_bw_limits;
> > > >  
> > > >  int intel_fdi_link_freq(struct drm_i915_private *i915,
> > > >  			const struct intel_crtc_state *pipe_config);
> > > >  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> > > >  			   struct intel_crtc_state *pipe_config);
> > > > +int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
> > > > +				struct intel_link_bw_limits *limits);
> > > >  void intel_fdi_normal_train(struct intel_crtc *crtc);
> > > >  void ilk_fdi_disable(struct intel_crtc *crtc);
> > > >  void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > > index 22494772b9d59..aacf22bab3135 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> > > > @@ -160,7 +160,12 @@ intel_link_bw_reset_pipe_limit_to_min(struct intel_atomic_state *state,
> > > >  static int check_all_link_config(struct intel_atomic_state *state,
> > > >  				 struct intel_link_bw_limits *limits)
> > > >  {
> > > > -	/* TODO: Check all shared display link configurations like FDI */
> > > > +	int ret;
> > > > +
> > > > +	ret = intel_fdi_atomic_check_link(state, limits);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +
> > > >  	return 0;
> > > >  }
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> > > > index 3ace56979b70e..0366d4cc6b72b 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> > > > @@ -48,6 +48,7 @@
> > > >  #include "intel_dpll.h"
> > > >  #include "intel_fdi.h"
> > > >  #include "intel_gmbus.h"
> > > > +#include "intel_link_bw.h"
> > > >  #include "intel_lvds.h"
> > > >  #include "intel_lvds_regs.h"
> > > >  #include "intel_panel.h"
> > > > @@ -425,6 +426,12 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> > > >  		return -EINVAL;
> > > >  	}
> > > >  
> > > > +	if (HAS_PCH_SPLIT(i915)) {
> > > > +		crtc_state->has_pch_encoder = true;
> > > > +		if (!intel_link_bw_compute_pipe_bpp(crtc_state))
> > > > +			return -EINVAL;
> > > > +	}
> > > > +
> > > >  	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
> > > >  		lvds_bpp = 8*3;
> > > >  	else
> > > > @@ -453,9 +460,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
> > > >  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> > > >  		return -EINVAL;
> > > >  
> > > > -	if (HAS_PCH_SPLIT(i915))
> > > > -		crtc_state->has_pch_encoder = true;
> > > > -
> > > >  	ret = intel_panel_fitting(crtc_state, conn_state);
> > > >  	if (ret)
> > > >  		return ret;
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > > index 135a2527fd1b4..3c912f3bc10ba 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > > > @@ -48,6 +48,7 @@
> > > >  #include "intel_gmbus.h"
> > > >  #include "intel_hdmi.h"
> > > >  #include "intel_hotplug.h"
> > > > +#include "intel_link_bw.h"
> > > >  #include "intel_panel.h"
> > > >  #include "intel_sdvo.h"
> > > >  #include "intel_sdvo_regs.h"
> > > > @@ -1351,14 +1352,17 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
> > > >  	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
> > > >  	struct drm_display_mode *mode = &pipe_config->hw.mode;
> > > >  
> > > > +	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
> > > > +		pipe_config->has_pch_encoder = true;
> > > > +		if (!intel_link_bw_compute_pipe_bpp(pipe_config))
> > > > +			return -EINVAL;
> > > > +	}
> > > > +
> > > >  	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
> > > >  	pipe_config->pipe_bpp = 8*3;
> > > 
> > > This seems borked. I think we want to force this to 8bpc only if we're
> > > higher currently.
> > 
> > This would fail the modeset if pipe_bpp would need to be reduced to 6*3
> > due to a BW limit and that's what happens before this change as well
> > afaics. I agree it's strange to detect that only later in the retry loop
> > and the above should return already error in that case. Are you ok with
> > that (if crtc_state->max_link_bpp < 8*3 -> return -EINVAL) ?
> 
> I don't think forcing to 8bpc makes any real sense, other than as an
> upper limit (since SDVO can only transmit 8bpc data). So I think this
> should just use 'min(pipe_bpp, 8*3)'. But we should do that change
> as a separate patch.

Ok, I'll drop the above check then, handling the pipe_bpp==6*3 case the
current way.

> > If you meant that increasing an EDID (6 bpc) baseline to 8 bpc (if BW
> > allows otherwise) doesn't make sense either here, that would be an issue
> > already before this change. I can add a FIXME: comment for that.
> > 
> > > Same for the LVDS case I think, though that one is a bit more sane atm
> > > since it looks at the bw_constrained flag, though I don't think we
> > > really need that flag anymore, at least for this purpose.
> > 
> > This patch doesn't change the behavior there either, but bw_constrained
> > could be replaced with crtc_state->max_link_bpp < lvds_bpp (as a
> > follow-up imo).
> > 
> > > Hmm, but maybe we do still need it for the LPT FDI case where we do
> > > actually want to increase the bpc to 8 if the EDID baseline is below
> > > that.
> > 
> > I suppose bw_constrained && pipe_bpp < 24 there could be also replaced
> > with crtc_state->max_link_bpp < 24.
> > 
> > > >  	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> > > >  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > > >  
> > > > -	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
> > > > -		pipe_config->has_pch_encoder = true;
> > > > -
> > > >  	/*
> > > >  	 * We need to construct preferred input timings based on our
> > > >  	 * output timings.  To do that, we have to set the output
> > > > -- 
> > > > 2.37.2
> > > 
> > > -- 
> > > Ville Syrjälä
> > > Intel
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links
  2023-09-19 15:44   ` Ville Syrjälä
@ 2023-09-19 18:14     ` Imre Deak
  2023-09-19 18:28       ` Imre Deak
  0 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-19 18:14 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Sep 19, 2023 at 06:44:00PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 14, 2023 at 10:26:45PM +0300, Imre Deak wrote:
> > Recompute the state of all CRTCs on an FDI link during a modeset that
> > may be affected by the modeset of other CRTCs on the same link. This
> > ensures that each CRTC on the link maximizes its BW use (after another
> > CRTC is disabled).
> > 
> > In practice this means recomputing pipe B's config on IVB if pipe C gets
> > disabled.
> > 
> > v2:
> > - Add the change recomputing affected CRTC states in a separate patch.
> >   (Ville)
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_display.c |  4 ++
> >  drivers/gpu/drm/i915/display/intel_fdi.c     | 53 ++++++++++++++++++++
> >  drivers/gpu/drm/i915/display/intel_fdi.h     |  1 +
> >  3 files changed, 58 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index aad16dcceb788..31297a333f50e 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -6210,6 +6210,10 @@ int intel_atomic_check_config(struct intel_atomic_state *state,
> >  	if (ret)
> >  		return ret;
> >  
> > +	ret = intel_fdi_add_affected_crtcs(state);
> > +	if (ret)
> > +		return ret;
> > +
> >  	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> >  		if (!intel_crtc_needs_modeset(new_crtc_state)) {
> >  			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
> > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> > index ad01915a4a39b..d723ae7e10d71 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> > @@ -120,6 +120,59 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
> >  	dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
> >  }
> >  
> > +/**
> > + * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
> > + * @state: intel atomic state
> > + *
> > + * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
> > + * known to affect the available FDI BW for the former CRTC. In practice this
> > + * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
> > + * CRTC C) and CRTC C is getting disabled.
> > + *
> > + * Returns 0 in case of success, or a negative error code otherwise.
> > + */
> > +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > +	struct intel_crtc_state *old_crtc_state;
> > +	struct intel_crtc_state *new_crtc_state;
> 
> Both look like they can be const.

Ok.

> > +	struct intel_crtc *crtc;
> > +
> > +	if (!IS_IVYBRIDGE(i915))
> 
> Should also check num_pipes==3 since pipe C can (at least in theory)
> be fused off.

Yes, but thought that pipe C's new_crtc_state would be NULL then.
Can make the check more explicit in any case.

> > +		return 0;
> > +
> > +	crtc = intel_crtc_for_pipe(i915, PIPE_C);
> > +	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> > +
> > +	if (!new_crtc_state)
> > +		return 0;
> > +
> > +	old_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> 
> old vs. new mixup

Err, yes thanks for catching it.

> > +
> > +	if (!old_crtc_state->fdi_lanes)
> > +		return 0;
> > +
> > +	if (!intel_crtc_needs_modeset(new_crtc_state))
> > +		return 0;
> > +
> > +	if (new_crtc_state->uapi.enable)
> > +		return 0;
> 
> We could be switching pipe C from driving a PCH port to driving
> the CPU eDP port. So this check seems a bit wrong.

Yes, didn't think of that case. I'll change it to:

	encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
	if (new_crtc_state->uapi.enable && encoder->port != PORT_A)
		return 0;

> > +
> > +	crtc = intel_crtc_for_pipe(i915, PIPE_B);
> > +	new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> > +
> > +	if (IS_ERR(new_crtc_state))
> > +		return PTR_ERR(old_crtc_state);
> > +
> > +	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
> > +	if (!old_crtc_state->fdi_lanes)
> > +		return 0;
> > +
> > +	return intel_modeset_pipes_in_mask_early(state,
> > +						 "FDI link BW decrease on pipe C",
> > +						 BIT(PIPE_B));
> > +}
> > +
> >  /* units of 100MHz */
> >  static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
> >  {
> > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> > index 129444c580f27..eb02b967bb440 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> > +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> > @@ -14,6 +14,7 @@ struct intel_crtc_state;
> >  struct intel_encoder;
> >  struct intel_link_bw_limits;
> >  
> > +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
> >  int intel_fdi_link_freq(struct drm_i915_private *i915,
> >  			const struct intel_crtc_state *pipe_config);
> >  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links
  2023-09-19 18:14     ` Imre Deak
@ 2023-09-19 18:28       ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-19 18:28 UTC (permalink / raw)
  To: Ville Syrjälä, intel-gfx

On Tue, Sep 19, 2023 at 09:14:27PM +0300, Imre Deak wrote:
> On Tue, Sep 19, 2023 at 06:44:00PM +0300, Ville Syrjälä wrote:
> > On Thu, Sep 14, 2023 at 10:26:45PM +0300, Imre Deak wrote:
> > > Recompute the state of all CRTCs on an FDI link during a modeset that
> > > may be affected by the modeset of other CRTCs on the same link. This
> > > ensures that each CRTC on the link maximizes its BW use (after another
> > > CRTC is disabled).
> > > 
> > > In practice this means recomputing pipe B's config on IVB if pipe C gets
> > > disabled.
> > > 
> > > v2:
> > > - Add the change recomputing affected CRTC states in a separate patch.
> > >   (Ville)
> > > 
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_display.c |  4 ++
> > >  drivers/gpu/drm/i915/display/intel_fdi.c     | 53 ++++++++++++++++++++
> > >  drivers/gpu/drm/i915/display/intel_fdi.h     |  1 +
> > >  3 files changed, 58 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > > index aad16dcceb788..31297a333f50e 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > > @@ -6210,6 +6210,10 @@ int intel_atomic_check_config(struct intel_atomic_state *state,
> > >  	if (ret)
> > >  		return ret;
> > >  
> > > +	ret = intel_fdi_add_affected_crtcs(state);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > >  	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> > >  		if (!intel_crtc_needs_modeset(new_crtc_state)) {
> > >  			if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > index ad01915a4a39b..d723ae7e10d71 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fdi.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.c
> > > @@ -120,6 +120,59 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
> > >  	dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
> > >  }
> > >  
> > > +/**
> > > + * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
> > > + * @state: intel atomic state
> > > + *
> > > + * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
> > > + * known to affect the available FDI BW for the former CRTC. In practice this
> > > + * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
> > > + * CRTC C) and CRTC C is getting disabled.
> > > + *
> > > + * Returns 0 in case of success, or a negative error code otherwise.
> > > + */
> > > +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
> > > +{
> > > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> > > +	struct intel_crtc_state *old_crtc_state;
> > > +	struct intel_crtc_state *new_crtc_state;
> > 
> > Both look like they can be const.
> 
> Ok.
> 
> > > +	struct intel_crtc *crtc;
> > > +
> > > +	if (!IS_IVYBRIDGE(i915))
> > 
> > Should also check num_pipes==3 since pipe C can (at least in theory)
> > be fused off.
> 
> Yes, but thought that pipe C's new_crtc_state would be NULL then.

Ah, crtc itself would be NULL then :/

> Can make the check more explicit in any case.
> 
> > > +		return 0;
> > > +
> > > +	crtc = intel_crtc_for_pipe(i915, PIPE_C);
> > > +	new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> > > +
> > > +	if (!new_crtc_state)
> > > +		return 0;
> > > +
> > > +	old_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> > 
> > old vs. new mixup
> 
> Err, yes thanks for catching it.
> 
> > > +
> > > +	if (!old_crtc_state->fdi_lanes)
> > > +		return 0;
> > > +
> > > +	if (!intel_crtc_needs_modeset(new_crtc_state))
> > > +		return 0;
> > > +
> > > +	if (new_crtc_state->uapi.enable)
> > > +		return 0;
> > 
> > We could be switching pipe C from driving a PCH port to driving
> > the CPU eDP port. So this check seems a bit wrong.
> 
> Yes, didn't think of that case. I'll change it to:
> 
> 	encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
> 	if (new_crtc_state->uapi.enable && encoder->port != PORT_A)
> 		return 0;
> 
> > > +
> > > +	crtc = intel_crtc_for_pipe(i915, PIPE_B);
> > > +	new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
> > > +
> > > +	if (IS_ERR(new_crtc_state))
> > > +		return PTR_ERR(old_crtc_state);
> > > +
> > > +	old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
> > > +	if (!old_crtc_state->fdi_lanes)
> > > +		return 0;
> > > +
> > > +	return intel_modeset_pipes_in_mask_early(state,
> > > +						 "FDI link BW decrease on pipe C",
> > > +						 BIT(PIPE_B));
> > > +}
> > > +
> > >  /* units of 100MHz */
> > >  static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
> > >  {
> > > diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > index 129444c580f27..eb02b967bb440 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_fdi.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_fdi.h
> > > @@ -14,6 +14,7 @@ struct intel_crtc_state;
> > >  struct intel_encoder;
> > >  struct intel_link_bw_limits;
> > >  
> > > +int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
> > >  int intel_fdi_link_freq(struct drm_i915_private *i915,
> > >  			const struct intel_crtc_state *pipe_config);
> > >  int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
> > > -- 
> > > 2.37.2
> > 
> > -- 
> > Ville Syrjälä
> > Intel

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

* Re: [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead Imre Deak
@ 2023-09-20  9:09   ` Lisovskiy, Stanislav
  2023-09-20 10:58   ` Ville Syrjälä
  1 sibling, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-20  9:09 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:51PM +0300, Imre Deak wrote:
> On 8b/10b MST links the PBN value for DSC streams must be calculated
> accounting for the FEC overhead. The same applies to 8b/10b non-DSC
> streams if there is another DSC stream on the same link. Fix up the PBN
> calculation accordingly.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 01291bbb44693..c1fea894d3774 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -110,7 +110,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
>  
>  		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
>  						       bpp << 4,
> -						       false);
> +						       (dsc || crtc_state->fec_enable) &&
> +							!intel_dp_is_uhbr(crtc_state));
>  
>  		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
>  						      connector->port,
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms Imre Deak
@ 2023-09-20  9:11   ` Lisovskiy, Stanislav
  2023-09-20 10:59     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-20  9:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:52PM +0300, Imre Deak wrote:
> If an MST stream is modeset, its state must be checked along all the
> other streams on the same MST link, for instance to resolve a BW
> overallocation of a non-sink MST port or to make sure that the FEC is
> enabled/disabled the same way for all these streams.
> 
> To prepare for that this patch adds all the stream CRTCs to the atomic
> state and marks them for modeset similarly to tgl+ platforms. (If the
> state computation doesn't change the state the CRTC is switched back to
> fastset mode.)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index c1fea894d3774..832e8b0e87e84 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
>  	struct intel_connector *connector_iter;
>  	int ret = 0;
>  
> -	if (DISPLAY_VER(dev_priv) < 12)
> -		return  0;
> -

I'm just a bit concerned, why this check was initially added?
Probably there was a reason?

Stan

>  	if (!intel_connector_needs_modeset(state, &connector->base))
>  		return 0;
>  
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead Imre Deak
  2023-09-20  9:09   ` Lisovskiy, Stanislav
@ 2023-09-20 10:58   ` Ville Syrjälä
  2023-09-20 11:35     ` Imre Deak
  1 sibling, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-20 10:58 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:51PM +0300, Imre Deak wrote:
> On 8b/10b MST links the PBN value for DSC streams must be calculated
> accounting for the FEC overhead. The same applies to 8b/10b non-DSC
> streams if there is another DSC stream on the same link. Fix up the PBN
> calculation accordingly.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 01291bbb44693..c1fea894d3774 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -110,7 +110,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
>  
>  		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
>  						       bpp << 4,
> -						       false);
> +						       (dsc || crtc_state->fec_enable) &&
> +							!intel_dp_is_uhbr(crtc_state));

Why is this not simply 'fec_enable'?

>  
>  		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
>  						      connector->port,
> -- 
> 2.37.2

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-20  9:11   ` Lisovskiy, Stanislav
@ 2023-09-20 10:59     ` Ville Syrjälä
  2023-09-20 11:25       ` Lisovskiy, Stanislav
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2023-09-20 10:59 UTC (permalink / raw)
  To: Lisovskiy, Stanislav; +Cc: intel-gfx

On Wed, Sep 20, 2023 at 12:11:58PM +0300, Lisovskiy, Stanislav wrote:
> On Thu, Sep 14, 2023 at 10:26:52PM +0300, Imre Deak wrote:
> > If an MST stream is modeset, its state must be checked along all the
> > other streams on the same MST link, for instance to resolve a BW
> > overallocation of a non-sink MST port or to make sure that the FEC is
> > enabled/disabled the same way for all these streams.
> > 
> > To prepare for that this patch adds all the stream CRTCs to the atomic
> > state and marks them for modeset similarly to tgl+ platforms. (If the
> > state computation doesn't change the state the CRTC is switched back to
> > fastset mode.)
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
> >  1 file changed, 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index c1fea894d3774..832e8b0e87e84 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> >  	struct intel_connector *connector_iter;
> >  	int ret = 0;
> >  
> > -	if (DISPLAY_VER(dev_priv) < 12)
> > -		return  0;
> > -
> 
> I'm just a bit concerned, why this check was initially added?
> Probably there was a reason?

It's in the name of the function, which should be renamed if we're
extending it beyond its original purpose.

> 
> Stan
> 
> >  	if (!intel_connector_needs_modeset(state, &connector->base))
> >  		return 0;
> >  
> > -- 
> > 2.37.2
> > 

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-20 10:59     ` Ville Syrjälä
@ 2023-09-20 11:25       ` Lisovskiy, Stanislav
  2023-09-20 12:38         ` Imre Deak
  0 siblings, 1 reply; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-20 11:25 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Sep 20, 2023 at 01:59:53PM +0300, Ville Syrjälä wrote:
> On Wed, Sep 20, 2023 at 12:11:58PM +0300, Lisovskiy, Stanislav wrote:
> > On Thu, Sep 14, 2023 at 10:26:52PM +0300, Imre Deak wrote:
> > > If an MST stream is modeset, its state must be checked along all the
> > > other streams on the same MST link, for instance to resolve a BW
> > > overallocation of a non-sink MST port or to make sure that the FEC is
> > > enabled/disabled the same way for all these streams.
> > > 
> > > To prepare for that this patch adds all the stream CRTCs to the atomic
> > > state and marks them for modeset similarly to tgl+ platforms. (If the
> > > state computation doesn't change the state the CRTC is switched back to
> > > fastset mode.)
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
> > >  1 file changed, 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > index c1fea894d3774..832e8b0e87e84 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > @@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> > >  	struct intel_connector *connector_iter;
> > >  	int ret = 0;
> > >  
> > > -	if (DISPLAY_VER(dev_priv) < 12)
> > > -		return  0;
> > > -
> > 
> > I'm just a bit concerned, why this check was initially added?
> > Probably there was a reason?
> 
> It's in the name of the function, which should be renamed if we're
> extending it beyond its original purpose.

Well, I would say this check could be "a bit" more descriptive.
Still, even if function name gets changed, we just remove the check, for the
function which was initially not even intended to be called for pre-tgl?
Why it became suitable now then? Or was it just wrong check?

Stan

> 
> > 
> > Stan
> > 
> > >  	if (!intel_connector_needs_modeset(state, &connector->base))
> > >  		return 0;
> > >  
> > > -- 
> > > 2.37.2
> > > 
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead
  2023-09-20 10:58   ` Ville Syrjälä
@ 2023-09-20 11:35     ` Imre Deak
  0 siblings, 0 replies; 72+ messages in thread
From: Imre Deak @ 2023-09-20 11:35 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Sep 20, 2023 at 01:58:43PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 14, 2023 at 10:26:51PM +0300, Imre Deak wrote:
> > On 8b/10b MST links the PBN value for DSC streams must be calculated
> > accounting for the FEC overhead. The same applies to 8b/10b non-DSC
> > streams if there is another DSC stream on the same link. Fix up the PBN
> > calculation accordingly.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 01291bbb44693..c1fea894d3774 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -110,7 +110,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
> >  
> >  		crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
> >  						       bpp << 4,
> > -						       false);
> > +						       (dsc || crtc_state->fec_enable) &&
> > +							!intel_dp_is_uhbr(crtc_state));
> 
> Why is this not simply 'fec_enable'?

For DSC it's enabled only after the link configuration is computed. I
can move that enabling from intel_dp_dsc_compute_config() earlier
instead.

> >  
> >  		slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
> >  						      connector->port,
> > -- 
> > 2.37.2
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-20 11:25       ` Lisovskiy, Stanislav
@ 2023-09-20 12:38         ` Imre Deak
  2023-09-20 13:56           ` Lisovskiy, Stanislav
  0 siblings, 1 reply; 72+ messages in thread
From: Imre Deak @ 2023-09-20 12:38 UTC (permalink / raw)
  To: Lisovskiy, Stanislav; +Cc: intel-gfx

On Wed, Sep 20, 2023 at 02:25:14PM +0300, Lisovskiy, Stanislav wrote:
> On Wed, Sep 20, 2023 at 01:59:53PM +0300, Ville Syrjälä wrote:
> > On Wed, Sep 20, 2023 at 12:11:58PM +0300, Lisovskiy, Stanislav wrote:
> > > On Thu, Sep 14, 2023 at 10:26:52PM +0300, Imre Deak wrote:
> > > > If an MST stream is modeset, its state must be checked along all the
> > > > other streams on the same MST link, for instance to resolve a BW
> > > > overallocation of a non-sink MST port or to make sure that the FEC is
> > > > enabled/disabled the same way for all these streams.
> > > > 
> > > > To prepare for that this patch adds all the stream CRTCs to the atomic
> > > > state and marks them for modeset similarly to tgl+ platforms. (If the
> > > > state computation doesn't change the state the CRTC is switched back to
> > > > fastset mode.)
> > > > 
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
> > > >  1 file changed, 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > index c1fea894d3774..832e8b0e87e84 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > @@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> > > >  	struct intel_connector *connector_iter;
> > > >  	int ret = 0;
> > > >  
> > > > -	if (DISPLAY_VER(dev_priv) < 12)
> > > > -		return  0;
> > > > -
> > > 
> > > I'm just a bit concerned, why this check was initially added?
> > > Probably there was a reason?
> > 
> > It's in the name of the function, which should be renamed if we're
> > extending it beyond its original purpose.
> 
> Well, I would say this check could be "a bit" more descriptive.
> Still, even if function name gets changed, we just remove the check, for the
> function which was initially not even intended to be called for pre-tgl?

The change on tgl+ platforms is that all the MST streams go through a
master transcoder, while on old platforms each stream has only its own
transcoder. Hence on tgl+ all streams/CRTCs may need to be modeset, at
least in the case the CRTC owning the master transcoder (for instance
pipe A/transcoder A) is modeset. So on tgl+ here all CRTCs for a given
MST topology is added to the state/marked for modeset.

pre-tgl this wasn't necessary, until the need to recalculate the BW
requirement of each stream came up, as described in the commit log.

I can clarify the above in the commit log and rename the function
accordingly, is that ok?

> Why it became suitable now then? Or was it just wrong check?
> 
> Stan
> 
> > 
> > > 
> > > Stan
> > > 
> > > >  	if (!intel_connector_needs_modeset(state, &connector->base))
> > > >  		return 0;
> > > >  
> > > > -- 
> > > > 2.37.2
> > > > 
> > 
> > -- 
> > Ville Syrjälä
> > Intel

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

* Re: [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms
  2023-09-20 12:38         ` Imre Deak
@ 2023-09-20 13:56           ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-20 13:56 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Wed, Sep 20, 2023 at 03:38:05PM +0300, Imre Deak wrote:
> On Wed, Sep 20, 2023 at 02:25:14PM +0300, Lisovskiy, Stanislav wrote:
> > On Wed, Sep 20, 2023 at 01:59:53PM +0300, Ville Syrjälä wrote:
> > > On Wed, Sep 20, 2023 at 12:11:58PM +0300, Lisovskiy, Stanislav wrote:
> > > > On Thu, Sep 14, 2023 at 10:26:52PM +0300, Imre Deak wrote:
> > > > > If an MST stream is modeset, its state must be checked along all the
> > > > > other streams on the same MST link, for instance to resolve a BW
> > > > > overallocation of a non-sink MST port or to make sure that the FEC is
> > > > > enabled/disabled the same way for all these streams.
> > > > > 
> > > > > To prepare for that this patch adds all the stream CRTCs to the atomic
> > > > > state and marks them for modeset similarly to tgl+ platforms. (If the
> > > > > state computation doesn't change the state the CRTC is switched back to
> > > > > fastset mode.)
> > > > > 
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ---
> > > > >  1 file changed, 3 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > index c1fea894d3774..832e8b0e87e84 100644
> > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > @@ -491,9 +491,6 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> > > > >  	struct intel_connector *connector_iter;
> > > > >  	int ret = 0;
> > > > >  
> > > > > -	if (DISPLAY_VER(dev_priv) < 12)
> > > > > -		return  0;
> > > > > -
> > > > 
> > > > I'm just a bit concerned, why this check was initially added?
> > > > Probably there was a reason?
> > > 
> > > It's in the name of the function, which should be renamed if we're
> > > extending it beyond its original purpose.
> > 
> > Well, I would say this check could be "a bit" more descriptive.
> > Still, even if function name gets changed, we just remove the check, for the
> > function which was initially not even intended to be called for pre-tgl?
> 
> The change on tgl+ platforms is that all the MST streams go through a
> master transcoder, while on old platforms each stream has only its own
> transcoder. Hence on tgl+ all streams/CRTCs may need to be modeset, at
> least in the case the CRTC owning the master transcoder (for instance
> pipe A/transcoder A) is modeset. So on tgl+ here all CRTCs for a given
> MST topology is added to the state/marked for modeset.
> 
> pre-tgl this wasn't necessary, until the need to recalculate the BW
> requirement of each stream came up, as described in the commit log.
> 
> I can clarify the above in the commit log and rename the function
> accordingly, is that ok?

Yes, thank you for good explanation. I would may be also add some note to
actual function also, but up to you really.

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> 
> > Why it became suitable now then? Or was it just wrong check?
> > 
> > Stan
> > 
> > > 
> > > > 
> > > > Stan
> > > > 
> > > > >  	if (!intel_connector_needs_modeset(state, &connector->base))
> > > > >  		return 0;
> > > > >  
> > > > > -- 
> > > > > 2.37.2
> > > > > 
> > > 
> > > -- 
> > > Ville Syrjälä
> > > Intel

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

* Re: [Intel-gfx] [PATCH v5 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams
  2023-09-19 10:52   ` [Intel-gfx] [PATCH v5 " Imre Deak
@ 2023-09-25  7:42     ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-25  7:42 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Sep 19, 2023 at 01:52:11PM +0300, Imre Deak wrote:
> At the moment modesetting a stream CRTC will fail if the stream's BW
> along with the current BW of all the other streams on the same MST link
> is above the total BW of the MST link. Make the BW sharing more dynamic
> by trying to reduce the link bpp of one or more streams on the MST link
> in this case.
> 
> When selecting a stream to reduce the BW for, take into account which
> link segment in the MST topology ran out of BW and which streams go
> through this link segment. For instance with A,B,C streams in the same
> MST topology A and B may share the BW of a link segment downstream of a
> branch device, stream C not downstream of the branch device, hence not
> affecting this BW. If this link segment's BW runs out one or both of
> stream A/B's BW will be reduced until their total BW is within limits.
> 
> While reducing the link bpp for a given stream DSC may need to be
> enabled for it, which requires FEC on the whole MST link. Check for this
> condition and recompute the state for all streams taking the FEC
> overhead into account (on 8b/10b links).
> 
> v2:
> - Rebase on s/min_bpp_pipes/min_bpp_reached_pipes/ change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c |   5 +-
>  drivers/gpu/drm/i915/display/intel_dp.c      |  13 +-
>  drivers/gpu/drm/i915/display/intel_dp.h      |   2 +
>  drivers/gpu/drm/i915/display/intel_dp_mst.c  | 129 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_dp_mst.h  |   3 +
>  drivers/gpu/drm/i915/display/intel_link_bw.c |  15 ++-
>  drivers/gpu/drm/i915/display/intel_link_bw.h |   1 +
>  7 files changed, 159 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 8af22cf9a49de..565a6f20ffbfd 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -4629,6 +4629,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> +	crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe);
>  	crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
>  
>  	if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
> @@ -6435,10 +6436,6 @@ int intel_atomic_check(struct drm_device *dev,
>  		goto fail;
>  	}
>  
> -	ret = drm_dp_mst_atomic_check(&state->base);
> -	if (ret)
> -		goto fail;
> -
>  	ret = intel_atomic_check_planes(state);
>  	if (ret)
>  		goto fail;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 3d2ede31aa4e8..9b5070d8c8984 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1369,8 +1369,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
>  	return false;
>  }
>  
> -static bool intel_dp_supports_fec(struct intel_dp *intel_dp,
> -				  const struct intel_crtc_state *pipe_config)
> +bool intel_dp_supports_fec(struct intel_dp *intel_dp,
> +			   const struct intel_crtc_state *pipe_config)
>  {
>  	return intel_dp_source_supports_fec(intel_dp, pipe_config) &&
>  		drm_dp_sink_supports_fec(intel_dp->fec_capable);
> @@ -2111,8 +2111,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
>  		&pipe_config->hw.adjusted_mode;
>  	int ret;
>  
> -	pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
> -		intel_dp_supports_fec(intel_dp, pipe_config);
> +	pipe_config->fec_enable = pipe_config->fec_enable ||
> +		(!intel_dp_is_edp(intel_dp) &&
> +		 intel_dp_supports_fec(intel_dp, pipe_config));
>  
>  	if (!intel_dp_supports_dsc(intel_dp, pipe_config))
>  		return -EINVAL;
> @@ -2308,6 +2309,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  	bool dsc_needed;
>  	int ret = 0;
>  
> +	if (pipe_config->fec_enable &&
> +	    !intel_dp_supports_fec(intel_dp, pipe_config))
> +		return -EINVAL;

I wonder, could we just check that, when
we are actually setting fec_enable to true, then
we wouldn't have to care about this here.

Otherwise, with this clarified

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> +
>  	if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
>  				    adjusted_mode->crtc_clock))
>  		pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index 2cf3681bac64a..612105a303419 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -135,6 +135,8 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>  	return ~((1 << lane_count) - 1) & 0xf;
>  }
>  
> +bool intel_dp_supports_fec(struct intel_dp *intel_dp,
> +			   const struct intel_crtc_state *pipe_config);
>  u32 intel_dp_mode_to_fec_clock(u32 mode_clock);
>  u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 9681708acaa1a..ce69122fb4e54 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -43,6 +43,7 @@
>  #include "intel_dpio_phy.h"
>  #include "intel_hdcp.h"
>  #include "intel_hotplug.h"
> +#include "intel_link_bw.h"
>  #include "intel_vdsc.h"
>  #include "skl_scaler.h"
>  
> @@ -373,6 +374,10 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  	bool dsc_needed;
>  	int ret = 0;
>  
> +	if (pipe_config->fec_enable &&
> +	    !intel_dp_supports_fec(intel_dp, pipe_config))
> +		return -EINVAL;
> +
>  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
>  		return -EINVAL;
>  
> @@ -492,6 +497,130 @@ intel_dp_mst_transcoder_mask(struct intel_atomic_state *state,
>  	return transcoders;
>  }
>  
> +static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
> +					   struct drm_dp_mst_topology_mgr *mst_mgr,
> +					   struct drm_dp_mst_port *parent_port)
> +{
> +	const struct intel_digital_connector_state *conn_state;
> +	struct intel_connector *connector;
> +	u8 mask = 0;
> +	int i;
> +
> +	for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
> +		if (!conn_state->base.crtc)
> +			continue;
> +
> +		if (&connector->mst_port->mst_mgr != mst_mgr)
> +			continue;
> +
> +		if (connector->port != parent_port &&
> +		    !drm_dp_mst_port_downstream_of_parent(mst_mgr,
> +							  connector->port,
> +							  parent_port))
> +			continue;
> +
> +		mask |= BIT(to_intel_crtc(conn_state->base.crtc)->pipe);
> +	}
> +
> +	return mask;
> +}
> +
> +static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
> +					 struct drm_dp_mst_topology_mgr *mst_mgr,
> +					 struct intel_link_bw_limits *limits)
> +{
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> +	struct intel_crtc *crtc;
> +	u8 mst_pipe_mask;
> +	u8 fec_pipe_mask = 0;
> +	int ret;
> +
> +	mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
> +
> +	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mst_pipe_mask) {
> +		struct intel_crtc_state *crtc_state =
> +			intel_atomic_get_new_crtc_state(state, crtc);
> +
> +		/* Atomic connector check should've added all the MST CRTCs. */
> +		if (drm_WARN_ON(&i915->drm, !crtc_state))
> +			return -EINVAL;
> +
> +		if (crtc_state->fec_enable)
> +			fec_pipe_mask |= BIT(crtc->pipe);
> +	}
> +
> +	if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask)
> +		return 0;
> +
> +	limits->force_fec_pipes |= mst_pipe_mask;
> +
> +	ret = intel_modeset_pipes_in_mask_early(state, "MST FEC",
> +						mst_pipe_mask);
> +
> +	return ret ? : -EAGAIN;
> +}
> +
> +static int intel_dp_mst_check_bw(struct intel_atomic_state *state,
> +				 struct drm_dp_mst_topology_mgr *mst_mgr,
> +				 struct drm_dp_mst_topology_state *mst_state,
> +				 struct intel_link_bw_limits *limits)
> +{
> +	struct drm_dp_mst_port *mst_port;
> +	u8 mst_port_pipes;
> +	int ret;
> +
> +	ret = drm_dp_mst_atomic_check_mgr(&state->base, mst_mgr, mst_state, &mst_port);
> +	if (ret != -ENOSPC)
> +		return ret;
> +
> +	mst_port_pipes = get_pipes_downstream_of_mst_port(state, mst_mgr, mst_port);
> +
> +	ret = intel_link_bw_reduce_bpp(state, limits,
> +				       mst_port_pipes, "MST link BW");
> +
> +	return ret ? : -EAGAIN;
> +}
> +
> +/**
> + * intel_dp_mst_atomic_check_link - check all modeset MST link configuration
> + * @state: intel atomic state
> + * @limits: link BW limits
> + *
> + * Check the link configuration for all modeset MST outputs. If the
> + * configuration is invalid @limits will be updated if possible to
> + * reduce the total BW, after which the configuration for all CRTCs in
> + * @state must be recomputed with the updated @limits.
> + *
> + * Returns:
> + *   - 0 if the confugration is valid
> + *   - %-EAGAIN, if the configuration is invalid and @limits got updated
> + *     with fallback values with which the configuration of all CRTCs in
> + *     @state must be recomputed
> + *   - Other negative error, if the configuration is invalid without a
> + *     fallback possibility, or the check failed for another reason
> + */
> +int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
> +				   struct intel_link_bw_limits *limits)
> +{
> +	struct drm_dp_mst_topology_mgr *mgr;
> +	struct drm_dp_mst_topology_state *mst_state;
> +	int ret;
> +	int i;
> +
> +	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
> +		ret = intel_dp_mst_check_fec_change(state, mgr, limits);
> +		if (ret)
> +			return ret;
> +
> +		ret = intel_dp_mst_check_bw(state, mgr, mst_state,
> +					    limits);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int intel_dp_mst_compute_config_late(struct intel_encoder *encoder,
>  					    struct intel_crtc_state *crtc_state,
>  					    struct drm_connector_state *conn_state)
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> index f1815bb722672..4e836b9ac6061 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> @@ -13,6 +13,7 @@ struct intel_crtc;
>  struct intel_crtc_state;
>  struct intel_digital_port;
>  struct intel_dp;
> +struct intel_link_bw_limits;
>  
>  int intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_id);
>  void intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port);
> @@ -22,5 +23,7 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
>  bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
>  int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
>  					     struct intel_crtc *crtc);
> +int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
> +				   struct intel_link_bw_limits *limits);
>  
>  #endif /* __INTEL_DP_MST_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
> index 9d95e4a8478f7..85ceae2a5aaf1 100644
> --- a/drivers/gpu/drm/i915/display/intel_link_bw.c
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
> @@ -22,6 +22,7 @@ void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_
>  {
>  	enum pipe pipe;
>  
> +	limits->force_fec_pipes = 0;
>  	limits->min_bpp_reached_pipes = 0;
>  	for_each_pipe(i915, pipe)
>  		limits->max_bpp_x16[pipe] = INT_MAX;
> @@ -168,6 +169,10 @@ static int check_all_link_config(struct intel_atomic_state *state,
>  {
>  	int ret;
>  
> +	ret = intel_dp_mst_atomic_check_link(state, limits);
> +	if (ret)
> +		return ret;
> +
>  	ret = intel_fdi_atomic_check_link(state, limits);
>  	if (ret)
>  		return ret;
> @@ -183,6 +188,12 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
>  	bool bpps_changed = false;
>  	enum pipe pipe;
>  
> +	/* FEC can't be forced off after it was forced on. */
> +	if (drm_WARN_ON(&i915->drm,
> +			(old_limits->force_fec_pipes & new_limits->force_fec_pipes) !=
> +			old_limits->force_fec_pipes))
> +		return false;
> +
>  	for_each_pipe(i915, pipe) {
>  		/* The bpp limit can only decrease. */
>  		if (drm_WARN_ON(&i915->drm,
> @@ -197,7 +208,9 @@ assert_link_limit_change_valid(struct drm_i915_private *i915,
>  
>  	/* At least one limit must change. */
>  	if (drm_WARN_ON(&i915->drm,
> -			!bpps_changed))
> +			!bpps_changed &&
> +			new_limits->force_fec_pipes ==
> +			old_limits->force_fec_pipes))
>  		return false;
>  
>  	return true;
> diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
> index 0f666c9712f3c..33b9a338beeb6 100644
> --- a/drivers/gpu/drm/i915/display/intel_link_bw.h
> +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
> @@ -16,6 +16,7 @@ struct intel_atomic_state;
>  struct intel_crtc_state;
>  
>  struct intel_link_bw_limits {
> +	u8 force_fec_pipes;
>  	u8 min_bpp_reached_pipes;
>  	/* in 1/16 bpp units */
>  	int max_bpp_x16[I915_MAX_PIPES];
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device Imre Deak
@ 2023-09-25  7:44   ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-25  7:44 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:57PM +0300, Imre Deak wrote:
> Atm the driver supports DSC on MST links only by enabling it globally in
> the first branch device UFP's physical DPCD (vs. enabling it per-stream
> in the virtual DPCD right upstream the DPRX). This means the branch
> device will decompress any compressed stream (which it recognizes via
> MSA / SDP compression info), but it does this only for streams going to
> an SST output port. Accordingly allow DSC only for streams going to an
> SST output port of the first branch device.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 26 +++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index b2ac29a157fbd..f24f656d6d02a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -335,6 +335,27 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
>  						       limits);
>  }
>  
> +static bool intel_dp_mst_port_supports_dsc(struct intel_dp *intel_dp,
> +					   struct intel_crtc_state *crtc_state,
> +					   struct drm_connector_state *conn_state)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	struct intel_connector *connector =
> +		to_intel_connector(conn_state->connector);
> +	struct intel_crtc *crtc =
> +		to_intel_crtc(crtc_state->uapi.crtc);
> +
> +	if (connector->port->parent != intel_dp->mst_mgr.mst_primary) {
> +		drm_dbg_kms(&i915->drm,
> +			    "[CRTC:%d:%s] DSC only allowed on sink ports of the first branch device\n",
> +			    crtc->base.base.id, crtc->base.name);
> +
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
>  static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  				       struct intel_crtc_state *pipe_config,
>  				       struct drm_connector_state *conn_state)
> @@ -378,6 +399,11 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
>  			    str_yes_no(ret),
>  			    str_yes_no(intel_dp->force_dsc_en));
>  
> +		if (!intel_dp_mst_port_supports_dsc(intel_dp,
> +						    pipe_config,
> +						    conn_state))
> +			return -EINVAL;
> +
>  		if (!intel_dp_mst_compute_config_limits(intel_dp,
>  							pipe_config,
>  							true,
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed Imre Deak
@ 2023-09-25  7:54   ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-25  7:54 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:59PM +0300, Imre Deak wrote:
> After the previous patch the BW limits on the whole MST topology will be
> checked after computing the state for all the streams in the topology.
> Accordingly remove the check during the stream's encoder compute config
> step, to prevent failing an atomic commit due to a BW limit, if this can
> be resolved only by reducing the BW of other streams on the same MST
> link.

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index bcfd5f19d994f..64867289174d9 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -121,15 +121,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
>  		if (slots == -EDEADLK)
>  			return slots;
>  
> -		if (slots >= 0) {
> -			ret = drm_dp_mst_atomic_check(state);
> -			/*
> -			 * If we got slots >= 0 and we can fit those based on check
> -			 * then we can exit the loop. Otherwise keep trying.
> -			 */
> -			if (!ret)
> -				break;
> -		}
> +		if (slots >= 0)
> +			break;
>  	}
>  
>  	/* We failed to find a proper bpp/timeslots, return error */
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled Imre Deak
@ 2023-09-25  7:56   ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-25  7:56 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:54PM +0300, Imre Deak wrote:
> Atm the DSC PPS SDP will stay enabled after enabling and disabling DSC.
> This leaves an output blank after switching off DSC on it. Make sure the
> SDP is disabled for an uncompressed output.
> 
> v2:
> - Disable the SDP already during output disabling. (Ville)

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c     | 5 ++++-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 ++---
>  2 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 03010accc1c7f..e942eb95d688f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4027,7 +4027,10 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder,
>  			 VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK;
>  	u32 val = intel_de_read(dev_priv, reg) & ~dip_enable;
>  
> -	/* TODO: Add DSC case (DIP_ENABLE_PPS) */
> +	/* TODO: Sanitize DSC enabling wrt. intel_dsc_dp_pps_write(). */
> +	if (!enable && HAS_DSC(dev_priv))
> +		val &= ~VDIP_ENABLE_PPS;
> +
>  	/* When PSR is enabled, this routine doesn't disable VSC DIP */
>  	if (!crtc_state->has_psr)
>  		val &= ~VIDEO_DIP_ENABLE_VSC_HSW;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 19548242fa0f2..a38a0e6da01bf 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -662,9 +662,8 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
>  	 * BSpec 4287: disable DIP after the transcoder is disabled and before
>  	 * the transcoder clock select is set to none.
>  	 */
> -	if (last_mst_stream)
> -		intel_dp_set_infoframes(&dig_port->base, false,
> -					old_crtc_state, NULL);
> +	intel_dp_set_infoframes(&dig_port->base, false,
> +				old_crtc_state, NULL);
>  	/*
>  	 * From TGL spec: "If multi-stream slave transcoder: Configure
>  	 * Transcoder Clock Select to direct no clock to the transcoder"
> -- 
> 2.37.2
> 

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

* Re: [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream
  2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream Imre Deak
@ 2023-09-25  8:00   ` Lisovskiy, Stanislav
  0 siblings, 0 replies; 72+ messages in thread
From: Lisovskiy, Stanislav @ 2023-09-25  8:00 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 14, 2023 at 10:26:53PM +0300, Imre Deak wrote:
> Atm the DSC PPS SDP is programmed only if the first stream is compressed
> and then it's programmed only for the first stream. This left all other
> compressed streams blank. Program the SDP for all streams.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c    | 12 +++++++-----
>  drivers/gpu/drm/i915/display/intel_dp_mst.c |  2 ++
>  2 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 45db6349af94f..962c9c7c211ce 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -2505,7 +2505,8 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  	/* 6.o Configure and enable FEC if needed */
>  	intel_ddi_enable_fec(encoder, crtc_state);
>  
> -	intel_dsc_dp_pps_write(encoder, crtc_state);
> +	if (!is_mst)
> +		intel_dsc_dp_pps_write(encoder, crtc_state);
>  }
>  
>  static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
> @@ -2643,7 +2644,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  	/* 7.l Configure and enable FEC if needed */
>  	intel_ddi_enable_fec(encoder, crtc_state);
>  
> -	intel_dsc_dp_pps_write(encoder, crtc_state);
> +	if (!is_mst)
> +		intel_dsc_dp_pps_write(encoder, crtc_state);
>  }
>  
>  static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
> @@ -2705,10 +2707,10 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  
>  	intel_ddi_enable_fec(encoder, crtc_state);
>  
> -	if (!is_mst)
> +	if (!is_mst) {
>  		intel_ddi_enable_transcoder_clock(encoder, crtc_state);
> -
> -	intel_dsc_dp_pps_write(encoder, crtc_state);
> +		intel_dsc_dp_pps_write(encoder, crtc_state);
> +	}
>  }
>  
>  static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 832e8b0e87e84..19548242fa0f2 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -43,6 +43,7 @@
>  #include "intel_dpio_phy.h"
>  #include "intel_hdcp.h"
>  #include "intel_hotplug.h"
> +#include "intel_vdsc.h"
>  #include "skl_scaler.h"
>  
>  static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int bpp,
> @@ -775,6 +776,7 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
>  	if (DISPLAY_VER(dev_priv) < 12 || !first_mst_stream)
>  		intel_ddi_enable_transcoder_clock(encoder, pipe_config);
>  
> +	intel_dsc_dp_pps_write(&dig_port->base, pipe_config);
>  	intel_ddi_set_dp_msa(pipe_config, conn_state);
>  }
>  
> -- 
> 2.37.2
> 

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

end of thread, other threads:[~2023-09-26  5:40 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-14 19:26 [Intel-gfx] [PATCH v3 00/25] drm/i915: Improve BW management on shared display links Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 01/25] drm/i915/dp: Factor out helpers to compute the link limits Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 02/25] drm/i915/dp: Track the pipe and link bpp limits separately Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 03/25] drm/i915/dp: Skip computing a non-DSC link config if DSC is needed Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 04/25] drm/i915/dp: Update the link bpp limits for DSC mode Imre Deak
2023-09-19 14:48   ` Ville Syrjälä
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 05/25] drm/i915/dp: Limit the output link bpp in " Imre Deak
2023-09-19 14:49   ` Ville Syrjälä
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 06/25] drm/i915: Add helper to modeset a set of pipes Imre Deak
2023-09-15 18:34   ` Ville Syrjälä
2023-09-15 20:03     ` Imre Deak
2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
2023-09-19 14:25     ` Ville Syrjälä
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 07/25] drm/i915: During modeset forcing handle inactive but enabled pipes Imre Deak
2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 07/25] drm/i915: Rename intel_modeset_all_pipes() to intel_modeset_all_pipes_late() Imre Deak
2023-09-19 14:26     ` Ville Syrjälä
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 08/25] drm/i915: Factor out a helper to check/compute all the CRTC states Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 09/25] drm/i915: Add helpers for BW management on shared display links Imre Deak
2023-09-15  0:33   ` [Intel-gfx] [PATCH v4 " Imre Deak
2023-09-15 19:11     ` Ville Syrjälä
2023-09-15 21:01       ` Imre Deak
2023-09-18 18:25     ` [Intel-gfx] [PATCH v5 " Imre Deak
2023-09-19 15:21       ` Ville Syrjälä
2023-09-19 17:40         ` Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 10/25] drm/i915/fdi: Improve FDI BW sharing between pipe B and C Imre Deak
2023-09-15 19:31   ` Ville Syrjälä
2023-09-15 23:13     ` Imre Deak
2023-09-19 15:35       ` Ville Syrjälä
2023-09-19 17:45         ` Imre Deak
2023-09-18 18:25   ` [Intel-gfx] [PATCH v5 " Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 11/25] drm/i915/fdi: Recompute state for affected CRTCs on FDI links Imre Deak
2023-09-19 15:44   ` Ville Syrjälä
2023-09-19 18:14     ` Imre Deak
2023-09-19 18:28       ` Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 12/25] drm/dp_mst: Fix fractional DSC bpp handling Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 13/25] drm/dp_mst: Add a way to calculate PBN values with FEC overhead Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 14/25] drm/dp_mst: Add helper to determine if an MST port is downstream of another port Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 15/25] drm/dp_mst: Factor out a helper to check the atomic state of a topology manager Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 16/25] drm/dp_mst: Swap the order of checking root vs. non-root port BW limitations Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 17/25] drm/i915/dp_mst: Fix PBN calculation with FEC overhead Imre Deak
2023-09-20  9:09   ` Lisovskiy, Stanislav
2023-09-20 10:58   ` Ville Syrjälä
2023-09-20 11:35     ` Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 18/25] drm/i915/dp_mst: Add atomic state for all streams on pre-tgl platforms Imre Deak
2023-09-20  9:11   ` Lisovskiy, Stanislav
2023-09-20 10:59     ` Ville Syrjälä
2023-09-20 11:25       ` Lisovskiy, Stanislav
2023-09-20 12:38         ` Imre Deak
2023-09-20 13:56           ` Lisovskiy, Stanislav
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 19/25] drm/i915/dp_mst: Program the DSC PPS SDP for each stream Imre Deak
2023-09-25  8:00   ` Lisovskiy, Stanislav
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 20/25] drm/i915/dp: Make sure the DSC PPS SDP is disabled whenever DSC is disabled Imre Deak
2023-09-25  7:56   ` Lisovskiy, Stanislav
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 21/25] drm/i915/dp_mst: Enable DSC decompression if any stream needs this Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 22/25] drm/i915/dp_mst: Add missing DSC compression disabling Imre Deak
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 23/25] drm/i915/dp_mst: Allow DSC only for sink ports of the first branch device Imre Deak
2023-09-25  7:44   ` Lisovskiy, Stanislav
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 24/25] drm/i915/dp_mst: Improve BW sharing between MST streams Imre Deak
2023-09-19 10:52   ` [Intel-gfx] [PATCH v5 " Imre Deak
2023-09-25  7:42     ` Lisovskiy, Stanislav
2023-09-14 19:26 ` [Intel-gfx] [PATCH v3 25/25] drm/i915/dp_mst: Check BW limitations only after all streams are computed Imre Deak
2023-09-25  7:54   ` Lisovskiy, Stanislav
2023-09-14 23:33 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev4) Patchwork
2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev5) Patchwork
2023-09-15  4:07 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2023-09-15  4:21 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2023-09-15 12:39 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
2023-09-19  1:11 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for drm/i915: Improve BW management on shared display links (rev9) Patchwork
2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Improve BW management on shared display links (rev10) Patchwork
2023-09-19 11:38 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2023-09-19 11:55 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2023-09-19 13:29   ` Imre Deak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox