intel-xe.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD
@ 2025-11-08  0:05 Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
                   ` (16 more replies)
  0 siblings, 17 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Ville Syrjälä,
	Jani Nikula, Suraj Kandpal, Jani Nikula, Sai Teja Pottumuttu

This series adds initial support for Xe3p_LPD, Intel's display
architecture with IP version 35.

This series contains basic enabling patches and does not provide
complete support for the display IP yet. More involved features, like
the new PHY implementation and ALPM are implemented as separate patch
series.

Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
Changes in v4:
- Skipped patches from v3 that were already applied.
- Dropped patch "drm/i915/xe3p_lpd: Enable system caching for FBC" with
  the expectation that its next version will be sent as a standalone
  patch.
- Link to v3: https://patch.msgid.link/20251103-xe3p_lpd-basic-enabling-v3-0-00e87b510ae7@intel.com

Changes in v3:
- Reshuffled patches so that most of the ones already containing a r-b
  are placed at the start.
- Dropped "drm/i915/xe3p_lpd: Wait for AUX channel power status", as a
  similar patch was already applied from a patch series dedicated to LT
  PHY
  (https://lore.kernel.org/all/20251101032513.4171255-25-suraj.kandpal@intel.com/).
- Dropped patches related to UINT16 plane formats, as they were
  incomplete and were not specific to Xe3p_LPD.
- Dropped FBC related patches, as Vinod is handling them as a separated
  series
  (https://lore.kernel.org/intel-gfx/20251027134001.325064-1-vinod.govindapillai@intel.com/)
- Dropped "drm/i915/xe3p_lpd: PSR SU minimum lines is 4", since that
  change is not valid according to Bspec.
- Incorporated review feedback on the other patches. Please check the
  changelog in the individual patches for details.
- Link to v2: https://lore.kernel.org/r/20251021-xe3p_lpd-basic-enabling-v2-0-10eae6d655b8@intel.com

Changes in v2:
- Incorporated review feedback. Please check the changelog in the
  patches for details.
- Link to v1: https://lore.kernel.org/r/20251015-xe3p_lpd-basic-enabling-v1-0-d2d1e26520aa@intel.com

---
Gustavo Sousa (10):
      drm/i915/wm: Do not make latency values monotonic on Xe3 onward
      drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
      drm/i915/power: Use intel_encoder_is_tc()
      drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
      drm/i915/fbc: Add intel_fbc_id_for_pipe()
      drm/i915/xe3p_lpd: Handle underrun debug bits
      drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
      drm/i915/display: Use platform check in HAS_LT_PHY()
      drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h
      drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power

Sai Teja Pottumuttu (1):
      drm/i915/nvls: Add NVL-S display support

 drivers/gpu/drm/i915/display/intel_bios.c          |  54 +++++++-
 drivers/gpu/drm/i915/display/intel_bios.h          |   2 +
 drivers/gpu/drm/i915/display/intel_ddi.c           |  11 ++
 drivers/gpu/drm/i915/display/intel_display.c       |  19 ++-
 .../gpu/drm/i915/display/intel_display_device.c    |   5 +
 .../gpu/drm/i915/display/intel_display_device.h    |   6 +-
 .../drm/i915/display/intel_display_power_well.c    |  42 +++---
 drivers/gpu/drm/i915/display/intel_display_regs.h  |  36 ++++-
 drivers/gpu/drm/i915/display/intel_display_types.h |   1 +
 drivers/gpu/drm/i915/display/intel_fbc.c           |   5 +
 drivers/gpu/drm/i915/display/intel_fbc.h           |   2 +
 drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
 drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++
 drivers/gpu/drm/i915/display/intel_lt_phy.h        |   2 -
 drivers/gpu/drm/i915/display/intel_tc.c            | 151 ++++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_vbt_defs.h      |   3 +-
 drivers/gpu/drm/i915/display/skl_universal_plane.c |   9 +-
 drivers/gpu/drm/i915/display/skl_watermark.c       |  17 ++-
 18 files changed, 462 insertions(+), 33 deletions(-)
---
base-commit: 2bc418aa7efaae562e49d84e8b28f799cf624745
change-id: 20251014-xe3p_lpd-basic-enabling-eb4424698b44

Best regards,
--  
Gustavo Sousa <gustavo.sousa@intel.com>


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

* [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-12  3:46   ` Kandpal, Suraj
  2025-11-08  0:05 ` [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc Gustavo Sousa
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Ville Syrjälä

The Windows driver is rejecting non-monotonic ranges latency values for
Xe3.  Let's make sure that we do not call make_wm_latency_monotonic()
for Xe3 and beyond.

Also, because of that, let's add a check at the end of
adjust_wm_latency() to ensure we raise a warning if the final list of
latency values is not monotonic.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/skl_watermark.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 36a266f882d1..ed55fe84e930 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -3218,6 +3218,18 @@ static void make_wm_latency_monotonic(struct intel_display *display)
 	}
 }
 
+static bool is_wm_latency_monotonic(struct intel_display *display)
+{
+	u16 *wm = display->wm.skl_latency;
+	int level, num_levels = display->wm.num_levels;
+
+	for (level = 1; level < num_levels; level++)
+		if (wm[level] < wm[level - 1])
+			return false;
+
+	return true;
+}
+
 static void
 adjust_wm_latency(struct intel_display *display)
 {
@@ -3228,7 +3240,8 @@ adjust_wm_latency(struct intel_display *display)
 
 	sanitize_wm_latency(display);
 
-	make_wm_latency_monotonic(display);
+	if (DISPLAY_VER(display) < 30)
+		make_wm_latency_monotonic(display);
 
 	/*
 	 * WaWmMemoryReadLatency
@@ -3248,6 +3261,8 @@ adjust_wm_latency(struct intel_display *display)
 	 */
 	if (need_16gb_dimm_wa(display))
 		increase_wm_latency(display, 1);
+
+	drm_WARN_ON(display->drm, !is_wm_latency_monotonic(display));
 }
 
 static void mtl_read_wm_latency(struct intel_display *display)

-- 
2.51.0


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

* [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-11 16:02   ` Imre Deak
  2025-11-08  0:05 ` [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc() Gustavo Sousa
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
configuring SoC for TC ports and PHYs.  Update the code to match the
updates in VBT.

The new field dedicated_external is used to represent TC ports that are
connected to PHYs outside of the Type-C subsystem, meaning that they
behave like dedicated ports and don't require the extra Type-C
programming.  In an upcoming change, we will update the driver to take
this field into consideration when detecting the type of port.

The new field dyn_port_over_tc is used to inform that the TC port can be
dynamically allocated for a legacy connector in the Type-C subsystem,
which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
that field in order to handle the IOM resource management programming
required for that.

Note that, when dedicated_external is set, the fields dp_usb_type_c and
tbt are tagged as "don't care" in the spec, so they should be ignored in
that case, so also add a sanitization function to take care of forcing
them to zero when dedicated_external is true.

v2:
  - Use sanitization function to force dp_usb_type_c and tbt fields to
    be zero instead of adding a
    intel_bios_encoder_is_dedicated_external() check in each of their
    respective accessor functions. (Jani)
  - Print info about dedicated external ports in print_ddi_port().
    (Jani)

Bspec: 20124, 68954, 74304
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
 3 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 852e4d6db8a3..1487d5e5a69d 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
 	return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
 }
 
+static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
+					enum port port)
+{
+	struct intel_display *display = devdata->display;
+
+	if (!intel_bios_encoder_is_dedicated_external(devdata))
+		return;
+
+	/*
+	 * Fields dp_usb_type_c and tbt must be ignored when
+	 * dedicated_external is set.  Since dedicated_external is for
+	 * ports connected to PHYs outside of the Type-C subsystem, it
+	 * is safe to force those fields to zero.
+	 */
+
+	if (devdata->child.dp_usb_type_c) {
+		drm_dbg_kms(display->drm,
+			    "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
+			    port_name(port));
+		devdata->child.dp_usb_type_c = 0;
+	}
+
+	if (devdata->child.tbt) {
+		drm_dbg_kms(display->drm,
+			    "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
+			    port_name(port));
+		devdata->child.tbt = 0;
+	}
+}
+
 static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
 				 enum port port)
 {
@@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
 {
 	struct intel_display *display = devdata->display;
 	const struct child_device_config *child = &devdata->child;
-	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
+	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
+		supports_tbt, dedicated_external;
 	int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
 	enum port port;
 
@@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
 		    supports_typec_usb, supports_tbt,
 		    devdata->dsc != NULL);
 
+	dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
+	if (dedicated_external)
+		drm_dbg_kms(display->drm,
+			    "Port %c is dedicated external\n",
+			    port_name(port));
+
 	hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
 	if (hdmi_level_shift >= 0) {
 		drm_dbg_kms(display->drm,
@@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
 		return;
 	}
 
+	sanitize_dedicated_external(devdata, port);
 	sanitize_device_type(devdata, port);
 	sanitize_hdmi_level_shift(devdata, port);
 }
@@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
 {
 	BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
 
-	if (version > 263)
+	if (version > 264)
 		return -ENOENT;
 	else if (version >= 263)
 		return 44;
@@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
 	return devdata->display->vbt.version >= 209 && devdata->child.tbt;
 }
 
+bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
+{
+	return devdata->display->vbt.version >= 264 &&
+		devdata->child.dedicated_external;
+}
+
+bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
+{
+	return devdata->display->vbt.version >= 264 &&
+		devdata->child.dyn_port_over_tc;
+}
+
 bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
 {
 	return devdata && devdata->child.lane_reversal;
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index f9e438b2787b..75dff27b4228 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
 bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
 bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
 bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
 bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
 bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
 bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index 70e31520c560..57fda5824c9c 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -554,7 +554,8 @@ struct child_device_config {
 	u8 dvo_function;
 	u8 dp_usb_type_c:1;					/* 195+ */
 	u8 tbt:1;						/* 209+ */
-	u8 flags2_reserved:2;					/* 195+ */
+	u8 dedicated_external:1;				/* 264+ */
+	u8 dyn_port_over_tc:1;					/* 264+ */
 	u8 dp_port_trace_length:4;				/* 209+ */
 	u8 dp_gpio_index;					/* 195+ */
 	u16 dp_gpio_pin_num;					/* 195+ */

-- 
2.51.0


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

* [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc()
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-12 16:19   ` Imre Deak
  2025-11-08  0:05 ` [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc() Gustavo Sousa
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

Starting with Xe3p_LPD, when intel_phy_is_tc() returns true, it does
not necessarily mean that the port is connected to a PHY in the Type-C
subsystem.  The reason is that there is now a VBT field called
dedicated_external that will indicate that a Type-C capable port is
connected to a (most likely) combo/dedicated PHY.  When that's the case,
we must not do the extra programming required for Type-C connections.

In an upcoming change, we will modify intel_encoder_is_tc() to take the
VBT field dedicated_external into consideration.  Update
intel_display_power_well.c to use that function instead of
intel_phy_is_tc().

Note that, even though icl_aux_power_well_{enable,disable} are not part
of Xe3p_LPD's display paths, we modify them anyway for uniformity.

Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 .../drm/i915/display/intel_display_power_well.c    | 26 +++++++++++++++-------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index eab7019f2252..1485fc65ab87 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -258,8 +258,9 @@ aux_ch_to_digital_port(struct intel_display *display,
 	return NULL;
 }
 
-static enum phy icl_aux_pw_to_phy(struct intel_display *display,
-				  const struct i915_power_well *power_well)
+static struct intel_encoder *
+icl_aux_pw_to_encoder(struct intel_display *display,
+		      const struct i915_power_well *power_well)
 {
 	enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
 	struct intel_digital_port *dig_port = aux_ch_to_digital_port(display, aux_ch);
@@ -271,7 +272,15 @@ static enum phy icl_aux_pw_to_phy(struct intel_display *display,
 	 * as HDMI-only and routed to a combo PHY, the encoder either won't be
 	 * present at all or it will not have an aux_ch assigned.
 	 */
-	return dig_port ? intel_encoder_to_phy(&dig_port->base) : PHY_NONE;
+	return dig_port ? &dig_port->base : NULL;
+}
+
+static enum phy icl_aux_pw_to_phy(struct intel_display *display,
+				  const struct i915_power_well *power_well)
+{
+	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
+
+	return encoder ? intel_encoder_to_phy(encoder) : PHY_NONE;
 }
 
 static void hsw_wait_for_power_well_enable(struct intel_display *display,
@@ -570,9 +579,9 @@ static void
 icl_aux_power_well_enable(struct intel_display *display,
 			  struct i915_power_well *power_well)
 {
-	enum phy phy = icl_aux_pw_to_phy(display, power_well);
+	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
 
-	if (intel_phy_is_tc(display, phy))
+	if (encoder && intel_encoder_is_tc(encoder))
 		return icl_tc_phy_aux_power_well_enable(display, power_well);
 	else if (display->platform.icelake)
 		return icl_combo_phy_aux_power_well_enable(display,
@@ -585,9 +594,9 @@ static void
 icl_aux_power_well_disable(struct intel_display *display,
 			   struct i915_power_well *power_well)
 {
-	enum phy phy = icl_aux_pw_to_phy(display, power_well);
+	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
 
-	if (intel_phy_is_tc(display, phy))
+	if (encoder && intel_encoder_is_tc(encoder))
 		return hsw_power_well_disable(display, power_well);
 	else if (display->platform.icelake)
 		return icl_combo_phy_aux_power_well_disable(display,
@@ -1849,10 +1858,11 @@ tgl_tc_cold_off_power_well_is_enabled(struct intel_display *display,
 static void xelpdp_aux_power_well_enable(struct intel_display *display,
 					 struct i915_power_well *power_well)
 {
+	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
 	enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
 	enum phy phy = icl_aux_pw_to_phy(display, power_well);
 
-	if (intel_phy_is_tc(display, phy))
+	if (encoder && intel_encoder_is_tc(encoder))
 		icl_tc_port_assert_ref_held(display, power_well,
 					    aux_ch_to_digital_port(display, aux_ch));
 

-- 
2.51.0


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

* [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (2 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc() Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-12 16:24   ` Imre Deak
  2025-11-08  0:05 ` [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe() Gustavo Sousa
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

Starting with Xe3p_LPD, the VBT has a new field, called in the driver
"dedicated_external", which tells that a Type-C capable port is
physically connected to a PHY outside of the Type-C subsystem.  When
that's the case, the driver must not do the extra Type-C programming for
that port.  Update intel_encoder_is_tc() to check for that case.

While at it, add a note to intel_phy_is_tc() to remind us that it is
about whether the respective port is a Type-C capable port rather than
the PHY itself.

(Maybe it would be a nice idea to rename intel_phy_is_tc()?)

Note that this was handled with a new bool member added to struct
intel_digital_port instead of having querying the VBT directly because
VBT memory is freed (intel_bios_driver_remove) before encoder cleanup
(intel_ddi_encoder_destroy), which would cause an oops to happen when
the latter calls intel_encoder_is_tc().  This could be fixed by keeping
VBT data around longer, but that's left for a follow-up work, if deemed
necessary.

v2:
  - Drop printing info about dedicated external, now that we are doing
    it when parsing the VBT. (Jani)
  - Add a FIXME comment on the code explaining why we need to store
    dedicated_external in struct intel_digital_port. (Jani)

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c           | 11 +++++++++++
 drivers/gpu/drm/i915/display/intel_display.c       | 19 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_display_types.h |  1 +
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 733ef4559131..d9aaeafd1570 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -5376,6 +5376,17 @@ void intel_ddi_init(struct intel_display *display,
 			goto err;
 	}
 
+	/*
+	 * FIXME: We currently need to store dedicated_external because devdata
+	 * does not live long enough for when intel_encoder_is_tc() is called on
+	 * the unbind path.  This needs to be fixed by making sure that the VBT
+	 * data is kept long enough, so that
+	 * intel_bios_encoder_is_dedicated_external() can be called directly
+	 * from intel_encoder_is_tc().
+	 */
+	if (intel_bios_encoder_is_dedicated_external(devdata))
+		dig_port->dedicated_external = true;
+
 	if (intel_encoder_is_tc(encoder)) {
 		bool is_legacy =
 			!intel_bios_encoder_supports_typec_usb(devdata) &&
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 25986bd8fbdd..431f7f030a9b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1800,7 +1800,17 @@ bool intel_phy_is_combo(struct intel_display *display, enum phy phy)
 		return false;
 }
 
-/* Prefer intel_encoder_is_tc() */
+/*
+ * This function returns true if the DDI port respective to the PHY enumeration
+ * is a Type-C capable port.
+ *
+ * Depending on the VBT, the port might be configured
+ * as a "dedicated external" port, meaning that actual physical PHY is outside
+ * of the Type-C subsystem and, as such, not really a "Type-C PHY".
+ *
+ * Prefer intel_encoder_is_tc(), especially if you really need to know if we
+ * are dealing with Type-C connections.
+ */
 bool intel_phy_is_tc(struct intel_display *display, enum phy phy)
 {
 	/*
@@ -1885,6 +1895,13 @@ bool intel_encoder_is_tc(struct intel_encoder *encoder)
 {
 	struct intel_display *display = to_intel_display(encoder);
 
+	if (intel_encoder_is_dig_port(encoder)) {
+		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+		if (dig_port->dedicated_external)
+			return false;
+	}
+
 	return intel_phy_is_tc(display, intel_encoder_to_phy(encoder));
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 00600134bda0..8bf392bc0d5d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1937,6 +1937,7 @@ struct intel_digital_port {
 	bool lane_reversal;
 	bool ddi_a_4_lanes;
 	bool release_cl2_override;
+	bool dedicated_external;
 	u8 max_lanes;
 	/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
 	enum aux_ch aux_ch;

-- 
2.51.0


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

* [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe()
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (3 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc() Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-10 16:35   ` Matt Roper
  2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

We will need to know the FBC id respective to the pipe in other parts of
the driver. Let's promote the static function skl_fbc_id_for_pipe() to a
public one named intel_fbc_id_for_pipe().

Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_fbc.c           | 5 +++++
 drivers/gpu/drm/i915/display/intel_fbc.h           | 2 ++
 drivers/gpu/drm/i915/display/skl_universal_plane.c | 9 ++-------
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index a1e3083022ee..435bfd05109c 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -129,6 +129,11 @@ struct intel_fbc {
 	const char *no_fbc_reason;
 };
 
+enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe)
+{
+	return pipe - PIPE_A + INTEL_FBC_A;
+}
+
 /* plane stride in pixels */
 static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
index 91424563206a..3d02f3fe5630 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc.h
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 
 enum fb_op_origin;
+enum pipe;
 struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
@@ -27,6 +28,7 @@ enum intel_fbc_id {
 	I915_MAX_FBCS,
 };
 
+enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe);
 int intel_fbc_atomic_check(struct intel_atomic_state *state);
 int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state);
 bool intel_fbc_pre_update(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index bc55fafe9ce3..275ee2903219 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -439,11 +439,6 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb,
 	return 4096;
 }
 
-static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
-{
-	return pipe - PIPE_A + INTEL_FBC_A;
-}
-
 static bool skl_plane_has_fbc(struct intel_display *display,
 			      enum intel_fbc_id fbc_id, enum plane_id plane_id)
 {
@@ -896,7 +891,7 @@ static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb,
 						  bool enable)
 {
 	struct intel_display *display = to_intel_display(plane);
-	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe);
+	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(plane->pipe);
 	u32 val;
 
 	/* Only HDR planes have pixel normalizer and don't matter if no FBC */
@@ -2442,7 +2437,7 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state,
 static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
 				       enum pipe pipe, enum plane_id plane_id)
 {
-	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
+	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
 
 	if (skl_plane_has_fbc(display, fbc_id, plane_id))
 		return display->fbc[fbc_id];

-- 
2.51.0


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

* [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (4 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe() Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-10 11:45   ` Jani Nikula
  2025-11-10 17:03   ` Ville Syrjälä
  2025-11-08  0:05 ` [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation Gustavo Sousa
                   ` (10 subsequent siblings)
  16 siblings, 2 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula,
	Ville Syrjälä

Xe3p_LPD added several bits containing information that can be relevant
to debugging FIFO underruns.  Add the logic necessary to handle them
when reporting underruns.

This was adapted from the initial patch[1] from Sai Teja Pottumuttu.

[1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/

Bspec: 69111, 69561, 74411, 74412
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
I tested this by adding a change on top of this series that updates
Xe3p_LPD's CDCLK table to use bad values and I got the following
messages:

    [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
    [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
    [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
    [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
    [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
    [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
---
 .../gpu/drm/i915/display/intel_display_device.h    |   1 +
 drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
 drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
 drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
 4 files changed, 147 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index b559ef43d547..91d8cfac5eff 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -197,6 +197,7 @@ struct intel_display_platforms {
 #define HAS_TRANSCODER(__display, trans)	((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
 						  BIT(trans)) != 0)
 #define HAS_UNCOMPRESSED_JOINER(__display)	(DISPLAY_VER(__display) >= 13)
+#define HAS_UNDERRUN_DBG_INFO(__display)	(DISPLAY_VER(__display) >= 35)
 #define HAS_ULTRAJOINER(__display)	(((__display)->platform.dgfx && \
 					  DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
 #define HAS_VRR(__display)		(DISPLAY_VER(__display) >= 11)
diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
index 9d71e26a4fa2..89ea0156ee06 100644
--- a/drivers/gpu/drm/i915/display/intel_display_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
@@ -882,6 +882,21 @@
 #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK		REG_GENMASK(2, 0) /* tgl+ */
 #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)	REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
 
+#define _UNDERRUN_DBG1_A			0x70064
+#define _UNDERRUN_DBG1_B			0x71064
+#define UNDERRUN_DBG1(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
+#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK	REG_GENMASK(29, 24)
+#define   UNDERRUN_DDB_EMPTY_MASK		REG_GENMASK(21, 16)
+#define   UNDERRUN_DBUF_NOT_FILLED_MASK		REG_GENMASK(13, 8)
+#define   UNDERRUN_BELOW_WM0_MASK		REG_GENMASK(5, 0)
+
+#define _UNDERRUN_DBG2_A			0x70068
+#define _UNDERRUN_DBG2_B			0x71068
+#define UNDERRUN_DBG2(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
+#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN	REG_BIT(31)
+#define   UNDERRUN_PIPE_FRAME_COUNT_MASK	REG_GENMASK(30, 20)
+#define   UNDERRUN_LINE_COUNT_MASK		REG_GENMASK(19, 0)
+
 #define DPINVGTT				_MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
 #define   DPINVGTT_EN_MASK_CHV				REG_GENMASK(27, 16)
 #define   DPINVGTT_EN_MASK_VLV				REG_GENMASK(23, 16)
@@ -1416,6 +1431,7 @@
 
 #define GEN12_DCPR_STATUS_1				_MMIO(0x46440)
 #define  XELPDP_PMDEMAND_INFLIGHT_STATUS		REG_BIT(26)
+#define  XE3P_UNDERRUN_PKGC				REG_BIT(21)
 
 #define FUSE_STRAP		_MMIO(0x42014)
 #define   ILK_INTERNAL_GRAPHICS_DISABLE	REG_BIT(31)
diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
index b1d0161a3196..77d8321c4fb3 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
@@ -88,6 +88,8 @@
 #define DPFC_FENCE_YOFF			_MMIO(0x3218)
 #define ILK_DPFC_FENCE_YOFF(fbc_id)	_MMIO_PIPE((fbc_id), 0x43218, 0x43258)
 #define DPFC_CHICKEN			_MMIO(0x3224)
+#define FBC_DEBUG_STATUS(fbc_id)	_MMIO_PIPE((fbc_id), 0x43220, 0x43260)
+#define   FBC_UNDERRUN_DECMPR			REG_BIT(27)
 #define ILK_DPFC_CHICKEN(fbc_id)	_MMIO_PIPE((fbc_id), 0x43224, 0x43264)
 #define   DPFC_HT_MODIFY			REG_BIT(31) /* pre-ivb */
 #define   DPFC_NUKE_ON_ANY_MODIFICATION		REG_BIT(23) /* bdw+ */
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
index c2ce8461ac9e..8a05b5c5fccd 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/seq_buf.h>
+
 #include <drm/drm_print.h>
 
 #include "i915_reg.h"
@@ -34,6 +36,7 @@
 #include "intel_display_trace.h"
 #include "intel_display_types.h"
 #include "intel_fbc.h"
+#include "intel_fbc_regs.h"
 #include "intel_fifo_underrun.h"
 #include "intel_pch_display.h"
 
@@ -57,6 +60,118 @@
  * The code also supports underrun detection on the PCH transcoder.
  */
 
+#define UNDERRUN_DBG1_NUM_PLANES 6
+
+static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
+{
+	u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
+	struct {
+		u32 plane_mask;
+		const char *info;
+	} masks[] = {
+		{ REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
+		{ REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
+		{ REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
+		{ REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
+	};
+	DECLARE_SEQ_BUF(planes_desc, 32);
+
+	if (!val)
+		return;
+
+	intel_de_write(display, UNDERRUN_DBG1(pipe), val);
+
+	if (!log)
+		return;
+
+	for (int i = 0; i < ARRAY_SIZE(masks); i++) {
+		if (!masks[i].plane_mask)
+			continue;
+
+		seq_buf_clear(&planes_desc);
+
+		for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
+			if (!(masks[i].plane_mask & REG_BIT(j)))
+				continue;
+
+			if (j == 0)
+				seq_buf_puts(&planes_desc, "[C]");
+			else
+				seq_buf_printf(&planes_desc, "[%d]", j);
+		}
+
+		drm_err(display->drm,
+			"Pipe %c FIFO underrun info: %s on planes: %s\n",
+			pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
+
+		drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
+	}
+}
+
+static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
+{
+	u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
+
+	if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
+		return;
+
+	intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
+
+	if (log)
+		drm_err(display->drm,
+			"Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
+			pipe_name(pipe),
+			REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
+			REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
+}
+
+static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
+{
+	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
+	u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
+
+	if (!(val & FBC_UNDERRUN_DECMPR))
+		return;
+
+	intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
+
+	if (log)
+		drm_err(display->drm,
+			"Pipe %c FIFO underrun info: FBC decompressing\n",
+			pipe_name(pipe));
+}
+
+static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
+{
+	u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
+
+	if (!(val & XE3P_UNDERRUN_PKGC))
+		return;
+
+	/*
+	 * Note: If there are multiple pipes enabled, only one of them will see
+	 * XE3P_UNDERRUN_PKGC set.
+	 */
+	intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
+
+	if (log)
+		drm_err(display->drm,
+			"General FIFO underrun info: Package C-state blocking memory\n");
+}
+
+static void read_underrun_dbg_info(struct intel_display *display,
+				   enum pipe pipe,
+				   bool log)
+{
+	if (!HAS_UNDERRUN_DBG_INFO(display))
+		return;
+
+	read_underrun_dbg1(display, pipe, log);
+	read_underrun_dbg2(display, pipe, log);
+	read_underrun_dbg_fbc(display, pipe, log);
+	read_underrun_dbg_pkgc(display, log);
+}
+
 static bool ivb_can_enable_err_int(struct intel_display *display)
 {
 	struct intel_crtc *crtc;
@@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
 	old = !crtc->cpu_fifo_underrun_disabled;
 	crtc->cpu_fifo_underrun_disabled = !enable;
 
+	/*
+	 * The debug bits get latched at the time of the FIFO underrun ISR bit
+	 * getting set.  That means that any existing debug bit that is set when
+	 * handling a FIFO underrun interrupt has the potential to belong to
+	 * another underrun event (past or future).  To alleviate this problem,
+	 * let's clear existing bits before enabling the interrupt, so that at
+	 * least we don't get information that is too out-of-date.
+	 */
+	if (enable && !old)
+		read_underrun_dbg_info(display, pipe, false);
+
 	if (HAS_GMCH(display))
 		i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
 	else if (display->platform.ironlake || display->platform.sandybridge)
@@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
 		trace_intel_cpu_fifo_underrun(display, pipe);
 
 		drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
+
+		read_underrun_dbg_info(display, pipe, true);
 	}
 
 	intel_fbc_handle_fifo_underrun_irq(display);

-- 
2.51.0


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

* [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (5 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-12 17:53   ` Imre Deak
  2025-11-08  0:05 ` [PATCH v4 08/11] drm/i915/nvls: Add NVL-S display support Gustavo Sousa
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

Xe3p_LPD has a new feature that allows the driver to allocate at runtime
the DDI (TC ones) port to drive a legacy connection on the Type-C
subsystem.  This allows better resource utilization, because now there
is no need to statically reserve ports for legacy connectors on the
Type-C subsystem.

That said, our driver is not yet ready for the dynamic allocation.
Thus, as an incremental step, let's add the logic containing the
required programming sequence for the allocation, but, instead of
selecting the first available port, we try so use the 1:1 mapping
expected by the driver today.

Bspec: 68954
Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---

NOTE: This patch is still a WIP. There are some opens to resolve here.
Nevertheless, I'm sending it here for early feedback.

For the HIP-index stuff, I have a local refactor started and need to
finish it up and send it.

The other open is about concurrent calls to iom_dp_resource_lock().  It
is likely that we need to have a software lock to prevent concurrent
access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
---
 drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
 drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
 2 files changed, 169 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
index 89ea0156ee06..0cf7d43ce210 100644
--- a/drivers/gpu/drm/i915/display/intel_display_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
@@ -2908,6 +2908,25 @@ enum skl_power_gate {
 #define   DP_PIN_ASSIGNMENT(idx, x)		((x) << ((idx) * 4))
 /* See enum intel_tc_pin_assignment for the pin assignment field values. */
 
+/*
+ * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
+ * We need to consolidate the definitions.
+ */
+#define HIP_INDEX_REG0				_MMIO(0x1010a0)
+#define   HIP_168_INDEX_MASK			REG_GENMASK(3, 0)
+#define   HIP_168_IOM_RES_MGMT			REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
+
+#define IOM_DP_HW_RESOURCE_SEMAPHORE		_MMIO(0x168038)
+#define   IOM_DP_HW_SEMLOCK			REG_BIT(31)
+#define   IOM_REQUESTOR_ID_MASK			REG_GENMASK(3, 0)
+#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE	REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
+
+#define IOM_DP_RESOURCE_MNG			_MMIO(0x16802c)
+#define   IOM_DDI_CONSUMER_SHIFT(tc_port)	((tc_port) * 4)
+#define   IOM_DDI_CONSUMER_MASK(tc_port)	(0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
+#define   IOM_DDI_CONSUMER(tc_port, x)		((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
+#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)	IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
+
 #define _TCSS_DDI_STATUS_1			0x161500
 #define _TCSS_DDI_STATUS_2			0x161504
 #define TCSS_DDI_STATUS(tc)			_MMIO(_PICK_EVEN(tc, \
@@ -2946,5 +2965,4 @@ enum skl_power_gate {
 #define   MTL_TRDPRE_MASK		REG_GENMASK(7, 0)
 
 
-
 #endif /* __INTEL_DISPLAY_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 7e17ca018748..3c333999bbe4 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -9,6 +9,7 @@
 
 #include "i915_reg.h"
 #include "intel_atomic.h"
+#include "intel_bios.h"
 #include "intel_cx0_phy_regs.h"
 #include "intel_ddi.h"
 #include "intel_de.h"
@@ -25,6 +26,9 @@
 #include "intel_modeset_lock.h"
 #include "intel_tc.h"
 
+#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US	10
+#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US	10000
+
 enum tc_port_mode {
 	TC_PORT_DISCONNECTED,
 	TC_PORT_TBT_ALT,
@@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
 	__tc_cold_unblock(tc, domain, tc_cold_wref);
 }
 
+static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
+{
+	/*
+	 * IOM resource management registers live in the 2nd 4KB page of IOM
+	 * address space. So we need to configure HIP_INDEX_REG0 with the
+	 * correct index.
+	 *
+	 * FIXME: We need to have this and dekel PHY implementation using a
+	 * common abstraction to access registers on the HIP-indexed ranges, and
+	 * this function would then be dropped.
+	 */
+	intel_de_rmw(display, HIP_INDEX_REG0,
+		     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
+}
+
+/*
+ * FIXME: This function also needs to avoid concurrent accesses from the driver
+ * itself, possibly via a software lock.
+ */
+static int iom_dp_resource_lock(struct intel_tc_port *tc)
+{
+	struct intel_display *display = to_intel_display(tc->dig_port);
+	u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
+	int ret;
+
+	iom_res_mgmt_prepare_reg_access(display);
+	ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
+			      (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
+			      IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
+			      IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
+
+	if (ret)
+		drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
+			tc->port_name);
+
+	return ret;
+}
+
+static void iom_dp_resource_unlock(struct intel_tc_port *tc)
+{
+	struct intel_display *display = to_intel_display(tc->dig_port);
+
+	iom_res_mgmt_prepare_reg_access(display);
+	intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
+}
+
+static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
+{
+	struct intel_display *display = to_intel_display(tc->dig_port);
+	struct intel_digital_port *dig_port = tc->dig_port;
+	enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
+	u32 val;
+	u32 consumer;
+	u32 expected_consumer;
+	bool ret;
+
+	if (DISPLAY_VER(display) < 35)
+		return true;
+
+	if (tc->mode != TC_PORT_LEGACY)
+		return true;
+
+	if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
+		return true;
+
+	if (iom_dp_resource_lock(tc))
+		return false;
+
+	val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
+
+	consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
+	consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
+
+	/*
+	 * Bspec instructs to select first available DDI, but our driver is not
+	 * ready for such dynamic allocation yet. For now, we force a "static"
+	 * allocation: map the physical port (where HPD happens) to the
+	 * encoder's DDI (logical TC port, represented by tc_port).
+	 */
+	expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
+	expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
+
+	if (allocate) {
+		struct intel_encoder *other_encoder;
+
+		/*
+		 * Check if this encoder's DDI is already allocated for another
+		 * physical port, which could have happened prior to the driver
+		 * taking over (e.g. GOP).
+		 */
+		for_each_intel_encoder(display->drm, other_encoder) {
+			enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
+			u32 other_consumer;
+
+			if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
+				continue;
+
+			other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
+			other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
+			if (other_consumer == expected_consumer) {
+				drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
+					tc->port_name, expected_consumer, val);
+				ret = false;
+				goto out_resource_unlock;
+			}
+		}
+
+		if (consumer == 0) {
+			/* DDI is free to use, let's allocate it. */
+			val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
+			val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
+			intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
+			ret = true;
+		} else if (consumer == expected_consumer) {
+			/*
+			 * Nothing to do, as the expected "static" DDI allocation is
+			 * already in place.
+			 */
+			ret = true;
+		} else {
+			drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
+				tc->port_name, consumer, val);
+			ret = false;
+		}
+	} else {
+		drm_WARN_ON(display->drm, consumer != expected_consumer);
+		val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
+		intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
+		ret = true;
+	}
+
+out_resource_unlock:
+	iom_dp_resource_unlock(tc);
+
+	return ret;
+}
+
 static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
 {
 	tc->lock_wakeref = tc_cold_block(tc);
@@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
 		return true;
 	}
 
-	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
+	if (!xe3p_tc_iom_allocate_ddi(tc, true))
 		goto out_unblock_tccold;
 
+	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
+		goto out_deallocate_ddi;
+
 	xelpdp_tc_phy_take_ownership(tc, true);
 
 	read_pin_configuration(tc);
@@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
 	xelpdp_tc_phy_take_ownership(tc, false);
 	xelpdp_tc_phy_wait_for_tcss_power(tc, false);
 
+out_deallocate_ddi:
+	xe3p_tc_iom_allocate_ddi(tc, false);
+
 out_unblock_tccold:
 	tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
 
@@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
 {
 	switch (tc->mode) {
 	case TC_PORT_LEGACY:
+		xe3p_tc_iom_allocate_ddi(tc, false);
+		fallthrough;
 	case TC_PORT_DP_ALT:
 		xelpdp_tc_phy_take_ownership(tc, false);
 		xelpdp_tc_phy_enable_tcss_power(tc, false);

-- 
2.51.0


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

* [PATCH v4 08/11] drm/i915/nvls: Add NVL-S display support
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (6 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 09/11] drm/i915/display: Use platform check in HAS_LT_PHY() Gustavo Sousa
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Sai Teja Pottumuttu

From: Sai Teja Pottumuttu <sai.teja.pottumuttu@intel.com>

Add platform description and PCI IDs for NVL-S.

BSpec: 74201
Signed-off-by: Sai Teja Pottumuttu <sai.teja.pottumuttu@intel.com>
Reviewed-by: Shekhar Chauhan <shekhar.chauhan@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_device.c | 5 +++++
 drivers/gpu/drm/i915/display/intel_display_device.h | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index 1170afaa8680..471f236c9ddf 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -1420,6 +1420,10 @@ static const struct platform_desc ptl_desc = {
 	}
 };
 
+static const struct platform_desc nvl_desc = {
+	PLATFORM(novalake),
+};
+
 __diag_pop();
 
 /*
@@ -1495,6 +1499,7 @@ static const struct {
 	INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc),
 	INTEL_PTL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc),
 	INTEL_WCL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc),
+	INTEL_NVLS_IDS(INTEL_DISPLAY_DEVICE, &nvl_desc),
 };
 
 static const struct {
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index 91d8cfac5eff..9affb6a53da4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -103,7 +103,9 @@ struct pci_dev;
 	func(battlemage) \
 	/* Display ver 30 (based on GMD ID) */ \
 	func(pantherlake) \
-	func(pantherlake_wildcatlake)
+	func(pantherlake_wildcatlake) \
+	/* Display ver 35 (based on GMD ID) */ \
+	func(novalake)
 
 
 #define __MEMBER(name) unsigned long name:1;

-- 
2.51.0


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

* [PATCH v4 09/11] drm/i915/display: Use platform check in HAS_LT_PHY()
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (7 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 08/11] drm/i915/nvls: Add NVL-S display support Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 10/11] drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h Gustavo Sousa
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

NVL uses the Lake Tahoe PHY for display output and the driver recently
added the macro HAS_LT_PHY() to allow selecting code paths specific for
that type of PHY.

While NVL uses Xe3p_LPD as display IP, the type of PHY is actually
defined at the SoC level, so use a platform check instead of display
version.

Bspec: 74199
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_lt_phy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h
index a538d4c69210..034c20c66baf 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
@@ -39,6 +39,6 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
 			      const struct intel_crtc_state *crtc_state);
 void intel_xe3plpd_pll_disable(struct intel_encoder *encoder);
 
-#define HAS_LT_PHY(display) (DISPLAY_VER(display) >= 35)
+#define HAS_LT_PHY(display) ((display)->platform.novalake)
 
 #endif /* __INTEL_LT_PHY_H__ */

-- 
2.51.0


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

* [PATCH v4 10/11] drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (8 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 09/11] drm/i915/display: Use platform check in HAS_LT_PHY() Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-08  0:05 ` [PATCH v4 11/11] drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power Gustavo Sousa
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

We will need to HAS_LT_PHY() that macro in code outside of LT PHY
implementation. Move its definition to intel_display_device.h.

Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_device.h | 1 +
 drivers/gpu/drm/i915/display/intel_lt_phy.h         | 2 --
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index 9affb6a53da4..2455ec826abe 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -187,6 +187,7 @@ struct intel_display_platforms {
 #define HAS_IPS(__display)		((__display)->platform.haswell_ult || (__display)->platform.broadwell)
 #define HAS_LRR(__display)		(DISPLAY_VER(__display) >= 12)
 #define HAS_LSPCON(__display)		(IS_DISPLAY_VER(__display, 9, 10))
+#define HAS_LT_PHY(__display)		((__display)->platform.novalake)
 #define HAS_MBUS_JOINING(__display)	((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14)
 #define HAS_MSO(__display)		(DISPLAY_VER(__display) >= 12)
 #define HAS_OVERLAY(__display)		(DISPLAY_INFO(__display)->has_overlay)
diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h b/drivers/gpu/drm/i915/display/intel_lt_phy.h
index 034c20c66baf..e52aadfbdf93 100644
--- a/drivers/gpu/drm/i915/display/intel_lt_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
@@ -39,6 +39,4 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
 			      const struct intel_crtc_state *crtc_state);
 void intel_xe3plpd_pll_disable(struct intel_encoder *encoder);
 
-#define HAS_LT_PHY(display) ((display)->platform.novalake)
-
 #endif /* __INTEL_LT_PHY_H__ */

-- 
2.51.0


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

* [PATCH v4 11/11] drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (9 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 10/11] drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h Gustavo Sousa
@ 2025-11-08  0:05 ` Gustavo Sousa
  2025-11-08  0:15 ` [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:05 UTC (permalink / raw)
  To: intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

Bspec states that the new AUX power enable/disable sequences are
associated with the LT PHY.  As such, use HAS_LT_PHY() instead of IP
checks in those paths in the driver code.

While at it, also move the comment that we can't use the power status
flag to the "else" branch, since that comment is not applicable for the
LT PHY.

Bspec: 68967
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
Suggested-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_power_well.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 1485fc65ab87..33c9540a5d73 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -1870,19 +1870,19 @@ static void xelpdp_aux_power_well_enable(struct intel_display *display,
 		     XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
 		     XELPDP_DP_AUX_CH_CTL_POWER_REQUEST);
 
-	/*
-	 * The power status flag cannot be used to determine whether aux
-	 * power wells have finished powering up.  Instead we're
-	 * expected to just wait a fixed 600us after raising the request
-	 * bit.
-	 */
-	if (DISPLAY_VER(display) >= 35) {
+	if (HAS_LT_PHY(display)) {
 		if (intel_de_wait_for_set(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch),
 					  XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 2))
 			drm_warn(display->drm,
 				 "Timeout waiting for PHY %c AUX channel power to be up\n",
 				 phy_name(phy));
 	} else {
+		/*
+		 * The power status flag cannot be used to determine whether aux
+		 * power wells have finished powering up.  Instead we're
+		 * expected to just wait a fixed 600us after raising the request
+		 * bit.
+		 */
 		usleep_range(600, 1200);
 	}
 }
@@ -1897,7 +1897,7 @@ static void xelpdp_aux_power_well_disable(struct intel_display *display,
 		     XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
 		     0);
 
-	if (DISPLAY_VER(display) >= 35) {
+	if (HAS_LT_PHY(display)) {
 		if (intel_de_wait_for_clear(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch),
 					    XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 1))
 			drm_warn(display->drm,

-- 
2.51.0


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

* Re: [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (10 preceding siblings ...)
  2025-11-08  0:05 ` [PATCH v4 11/11] drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power Gustavo Sousa
@ 2025-11-08  0:15 ` Gustavo Sousa
  2025-11-08  1:52 ` ✗ CI.checkpatch: warning for drm/i915/display: Add initial support for Xe3p_LPD (rev4) Patchwork
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-08  0:15 UTC (permalink / raw)
  To: intel-gfx, intel-xe
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Jouni Högander,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, Ville Syrjälä, Jani Nikula,
	Suraj Kandpal, Jani Nikula

Quoting Gustavo Sousa (2025-11-07 21:05:33-03:00)
>This series adds initial support for Xe3p_LPD, Intel's display
>architecture with IP version 35.
>
>This series contains basic enabling patches and does not provide
>complete support for the display IP yet. More involved features, like
>the new PHY implementation and ALPM are implemented as separate patch
>series.
>
>Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>---
>Changes in v4:
>- Skipped patches from v3 that were already applied.
>- Dropped patch "drm/i915/xe3p_lpd: Enable system caching for FBC" with
>  the expectation that its next version will be sent as a standalone
>  patch.
>- Link to v3: https://patch.msgid.link/20251103-xe3p_lpd-basic-enabling-v3-0-00e87b510ae7@intel.com

I decided to post v4 even though there is still some ongoing discussion
for "drm/i915/wm: Do not make latency values monotonic on Xe3 onward" in
v3.  The reason is that I will soon become unavailable for a few days
and wanted to keep the series up-to-date with what I have locally.

--
Gustavo Sousa

>
>Changes in v3:
>- Reshuffled patches so that most of the ones already containing a r-b
>  are placed at the start.
>- Dropped "drm/i915/xe3p_lpd: Wait for AUX channel power status", as a
>  similar patch was already applied from a patch series dedicated to LT
>  PHY
>  (https://lore.kernel.org/all/20251101032513.4171255-25-suraj.kandpal@intel.com/).
>- Dropped patches related to UINT16 plane formats, as they were
>  incomplete and were not specific to Xe3p_LPD.
>- Dropped FBC related patches, as Vinod is handling them as a separated
>  series
>  (https://lore.kernel.org/intel-gfx/20251027134001.325064-1-vinod.govindapillai@intel.com/)
>- Dropped "drm/i915/xe3p_lpd: PSR SU minimum lines is 4", since that
>  change is not valid according to Bspec.
>- Incorporated review feedback on the other patches. Please check the
>  changelog in the individual patches for details.
>- Link to v2: https://lore.kernel.org/r/20251021-xe3p_lpd-basic-enabling-v2-0-10eae6d655b8@intel.com
>
>Changes in v2:
>- Incorporated review feedback. Please check the changelog in the
>  patches for details.
>- Link to v1: https://lore.kernel.org/r/20251015-xe3p_lpd-basic-enabling-v1-0-d2d1e26520aa@intel.com
>
>---
>Gustavo Sousa (10):
>      drm/i915/wm: Do not make latency values monotonic on Xe3 onward
>      drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
>      drm/i915/power: Use intel_encoder_is_tc()
>      drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
>      drm/i915/fbc: Add intel_fbc_id_for_pipe()
>      drm/i915/xe3p_lpd: Handle underrun debug bits
>      drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
>      drm/i915/display: Use platform check in HAS_LT_PHY()
>      drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h
>      drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power
>
>Sai Teja Pottumuttu (1):
>      drm/i915/nvls: Add NVL-S display support
>
> drivers/gpu/drm/i915/display/intel_bios.c          |  54 +++++++-
> drivers/gpu/drm/i915/display/intel_bios.h          |   2 +
> drivers/gpu/drm/i915/display/intel_ddi.c           |  11 ++
> drivers/gpu/drm/i915/display/intel_display.c       |  19 ++-
> .../gpu/drm/i915/display/intel_display_device.c    |   5 +
> .../gpu/drm/i915/display/intel_display_device.h    |   6 +-
> .../drm/i915/display/intel_display_power_well.c    |  42 +++---
> drivers/gpu/drm/i915/display/intel_display_regs.h  |  36 ++++-
> drivers/gpu/drm/i915/display/intel_display_types.h |   1 +
> drivers/gpu/drm/i915/display/intel_fbc.c           |   5 +
> drivers/gpu/drm/i915/display/intel_fbc.h           |   2 +
> drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
> drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++
> drivers/gpu/drm/i915/display/intel_lt_phy.h        |   2 -
> drivers/gpu/drm/i915/display/intel_tc.c            | 151 ++++++++++++++++++++-
> drivers/gpu/drm/i915/display/intel_vbt_defs.h      |   3 +-
> drivers/gpu/drm/i915/display/skl_universal_plane.c |   9 +-
> drivers/gpu/drm/i915/display/skl_watermark.c       |  17 ++-
> 18 files changed, 462 insertions(+), 33 deletions(-)
>---
>base-commit: 2bc418aa7efaae562e49d84e8b28f799cf624745
>change-id: 20251014-xe3p_lpd-basic-enabling-eb4424698b44
>
>Best regards,
>--  
>Gustavo Sousa <gustavo.sousa@intel.com>
>

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

* ✗ CI.checkpatch: warning for drm/i915/display: Add initial support for Xe3p_LPD (rev4)
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (11 preceding siblings ...)
  2025-11-08  0:15 ` [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
@ 2025-11-08  1:52 ` Patchwork
  2025-11-08  1:54 ` ✓ CI.KUnit: success " Patchwork
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Patchwork @ 2025-11-08  1:52 UTC (permalink / raw)
  To: Gustavo Sousa; +Cc: intel-xe

== Series Details ==

Series: drm/i915/display: Add initial support for Xe3p_LPD (rev4)
URL   : https://patchwork.freedesktop.org/series/155951/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
d9120d4d84745cf011b4b3efb338747e69179dfb
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 8975da4a18ed8f2b3185357ac5b8c6a4ea4c94b5
Author: Gustavo Sousa <gustavo.sousa@intel.com>
Date:   Fri Nov 7 21:05:44 2025 -0300

    drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power
    
    Bspec states that the new AUX power enable/disable sequences are
    associated with the LT PHY.  As such, use HAS_LT_PHY() instead of IP
    checks in those paths in the driver code.
    
    While at it, also move the comment that we can't use the power status
    flag to the "else" branch, since that comment is not applicable for the
    LT PHY.
    
    Bspec: 68967
    Cc: Matt Roper <matthew.d.roper@intel.com>
    Cc: Suraj Kandpal <suraj.kandpal@intel.com>
    Suggested-by: Matt Roper <matthew.d.roper@intel.com>
    Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
    Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
+ /mt/dim checkpatch 2bc418aa7efaae562e49d84e8b28f799cf624745 drm-intel
838858cf34e0 drm/i915/wm: Do not make latency values monotonic on Xe3 onward
fcd9b615992e drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
ec551d2110d1 drm/i915/power: Use intel_encoder_is_tc()
abb83f6d3cb3 drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
aa19ee63ea65 drm/i915/fbc: Add intel_fbc_id_for_pipe()
9d40f63f7004 drm/i915/xe3p_lpd: Handle underrun debug bits
-:15: WARNING:COMMIT_LOG_LONG_LINE: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#15: 
[1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/

total: 0 errors, 1 warnings, 0 checks, 201 lines checked
2057c8655f70 drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
-:49: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'tc_port' - possible side-effects?
#49: FILE: drivers/gpu/drm/i915/display/intel_display_regs.h:2928:
+#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)	IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))

total: 0 errors, 0 warnings, 1 checks, 219 lines checked
92774145328a drm/i915/nvls: Add NVL-S display support
1392c6a263cc drm/i915/display: Use platform check in HAS_LT_PHY()
7ce295f55fad drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h
8975da4a18ed drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power



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

* ✓ CI.KUnit: success for drm/i915/display: Add initial support for Xe3p_LPD (rev4)
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (12 preceding siblings ...)
  2025-11-08  1:52 ` ✗ CI.checkpatch: warning for drm/i915/display: Add initial support for Xe3p_LPD (rev4) Patchwork
@ 2025-11-08  1:54 ` Patchwork
  2025-11-08  2:09 ` ✗ CI.checksparse: warning " Patchwork
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Patchwork @ 2025-11-08  1:54 UTC (permalink / raw)
  To: Gustavo Sousa; +Cc: intel-xe

== Series Details ==

Series: drm/i915/display: Add initial support for Xe3p_LPD (rev4)
URL   : https://patchwork.freedesktop.org/series/155951/
State : success

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[01:52:59] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[01:53:03] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[01:53:33] Starting KUnit Kernel (1/1)...
[01:53:33] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[01:53:33] ================== guc_buf (11 subtests) ===================
[01:53:33] [PASSED] test_smallest
[01:53:33] [PASSED] test_largest
[01:53:33] [PASSED] test_granular
[01:53:33] [PASSED] test_unique
[01:53:33] [PASSED] test_overlap
[01:53:33] [PASSED] test_reusable
[01:53:33] [PASSED] test_too_big
[01:53:33] [PASSED] test_flush
[01:53:33] [PASSED] test_lookup
[01:53:33] [PASSED] test_data
[01:53:33] [PASSED] test_class
[01:53:33] ===================== [PASSED] guc_buf =====================
[01:53:33] =================== guc_dbm (7 subtests) ===================
[01:53:33] [PASSED] test_empty
[01:53:33] [PASSED] test_default
[01:53:33] ======================== test_size  ========================
[01:53:33] [PASSED] 4
[01:53:33] [PASSED] 8
[01:53:33] [PASSED] 32
[01:53:33] [PASSED] 256
[01:53:33] ==================== [PASSED] test_size ====================
[01:53:33] ======================= test_reuse  ========================
[01:53:33] [PASSED] 4
[01:53:33] [PASSED] 8
[01:53:33] [PASSED] 32
[01:53:33] [PASSED] 256
[01:53:33] =================== [PASSED] test_reuse ====================
[01:53:33] =================== test_range_overlap  ====================
[01:53:33] [PASSED] 4
[01:53:33] [PASSED] 8
[01:53:33] [PASSED] 32
[01:53:33] [PASSED] 256
[01:53:33] =============== [PASSED] test_range_overlap ================
[01:53:33] =================== test_range_compact  ====================
[01:53:33] [PASSED] 4
[01:53:33] [PASSED] 8
[01:53:33] [PASSED] 32
[01:53:33] [PASSED] 256
[01:53:33] =============== [PASSED] test_range_compact ================
[01:53:33] ==================== test_range_spare  =====================
[01:53:33] [PASSED] 4
[01:53:33] [PASSED] 8
[01:53:33] [PASSED] 32
[01:53:33] [PASSED] 256
[01:53:33] ================ [PASSED] test_range_spare =================
[01:53:33] ===================== [PASSED] guc_dbm =====================
[01:53:33] =================== guc_idm (6 subtests) ===================
[01:53:33] [PASSED] bad_init
[01:53:33] [PASSED] no_init
[01:53:33] [PASSED] init_fini
[01:53:33] [PASSED] check_used
[01:53:33] [PASSED] check_quota
[01:53:33] [PASSED] check_all
[01:53:33] ===================== [PASSED] guc_idm =====================
[01:53:33] ================== no_relay (3 subtests) ===================
[01:53:33] [PASSED] xe_drops_guc2pf_if_not_ready
[01:53:33] [PASSED] xe_drops_guc2vf_if_not_ready
[01:53:33] [PASSED] xe_rejects_send_if_not_ready
[01:53:33] ==================== [PASSED] no_relay =====================
[01:53:33] ================== pf_relay (14 subtests) ==================
[01:53:33] [PASSED] pf_rejects_guc2pf_too_short
[01:53:33] [PASSED] pf_rejects_guc2pf_too_long
[01:53:33] [PASSED] pf_rejects_guc2pf_no_payload
[01:53:33] [PASSED] pf_fails_no_payload
[01:53:33] [PASSED] pf_fails_bad_origin
[01:53:33] [PASSED] pf_fails_bad_type
[01:53:33] [PASSED] pf_txn_reports_error
[01:53:33] [PASSED] pf_txn_sends_pf2guc
[01:53:33] [PASSED] pf_sends_pf2guc
[01:53:33] [SKIPPED] pf_loopback_nop
[01:53:33] [SKIPPED] pf_loopback_echo
[01:53:33] [SKIPPED] pf_loopback_fail
[01:53:33] [SKIPPED] pf_loopback_busy
[01:53:33] [SKIPPED] pf_loopback_retry
[01:53:33] ==================== [PASSED] pf_relay =====================
[01:53:33] ================== vf_relay (3 subtests) ===================
[01:53:33] [PASSED] vf_rejects_guc2vf_too_short
[01:53:33] [PASSED] vf_rejects_guc2vf_too_long
[01:53:33] [PASSED] vf_rejects_guc2vf_no_payload
[01:53:33] ==================== [PASSED] vf_relay =====================
[01:53:33] ================ pf_gt_config (4 subtests) =================
[01:53:33] [PASSED] fair_contexts_1vf
[01:53:33] [PASSED] fair_doorbells_1vf
[01:53:33] ====================== fair_contexts  ======================
[01:53:33] [PASSED] 1 VF
[01:53:33] [PASSED] 2 VFs
[01:53:33] [PASSED] 3 VFs
[01:53:33] [PASSED] 4 VFs
[01:53:33] [PASSED] 5 VFs
[01:53:33] [PASSED] 6 VFs
[01:53:33] [PASSED] 7 VFs
[01:53:33] [PASSED] 8 VFs
[01:53:33] [PASSED] 9 VFs
[01:53:33] [PASSED] 10 VFs
[01:53:33] [PASSED] 11 VFs
[01:53:33] [PASSED] 12 VFs
[01:53:33] [PASSED] 13 VFs
[01:53:33] [PASSED] 14 VFs
[01:53:33] [PASSED] 15 VFs
[01:53:33] [PASSED] 16 VFs
[01:53:33] [PASSED] 17 VFs
[01:53:33] [PASSED] 18 VFs
[01:53:33] [PASSED] 19 VFs
[01:53:33] [PASSED] 20 VFs
[01:53:33] [PASSED] 21 VFs
[01:53:33] [PASSED] 22 VFs
[01:53:33] [PASSED] 23 VFs
[01:53:33] [PASSED] 24 VFs
[01:53:33] [PASSED] 25 VFs
[01:53:33] [PASSED] 26 VFs
[01:53:33] [PASSED] 27 VFs
[01:53:33] [PASSED] 28 VFs
[01:53:33] [PASSED] 29 VFs
[01:53:33] [PASSED] 30 VFs
[01:53:33] [PASSED] 31 VFs
[01:53:33] [PASSED] 32 VFs
[01:53:33] [PASSED] 33 VFs
[01:53:33] [PASSED] 34 VFs
[01:53:33] [PASSED] 35 VFs
[01:53:33] [PASSED] 36 VFs
[01:53:33] [PASSED] 37 VFs
[01:53:33] [PASSED] 38 VFs
[01:53:33] [PASSED] 39 VFs
[01:53:33] [PASSED] 40 VFs
[01:53:33] [PASSED] 41 VFs
[01:53:33] [PASSED] 42 VFs
[01:53:33] [PASSED] 43 VFs
[01:53:33] [PASSED] 44 VFs
[01:53:33] [PASSED] 45 VFs
[01:53:33] [PASSED] 46 VFs
[01:53:33] [PASSED] 47 VFs
[01:53:33] [PASSED] 48 VFs
[01:53:33] [PASSED] 49 VFs
[01:53:33] [PASSED] 50 VFs
[01:53:33] [PASSED] 51 VFs
[01:53:33] [PASSED] 52 VFs
[01:53:33] [PASSED] 53 VFs
[01:53:33] [PASSED] 54 VFs
[01:53:33] [PASSED] 55 VFs
[01:53:33] [PASSED] 56 VFs
[01:53:33] [PASSED] 57 VFs
[01:53:33] [PASSED] 58 VFs
[01:53:33] [PASSED] 59 VFs
[01:53:33] [PASSED] 60 VFs
[01:53:33] [PASSED] 61 VFs
[01:53:33] [PASSED] 62 VFs
[01:53:33] [PASSED] 63 VFs
[01:53:33] ================== [PASSED] fair_contexts ==================
[01:53:33] ===================== fair_doorbells  ======================
[01:53:33] [PASSED] 1 VF
[01:53:33] [PASSED] 2 VFs
[01:53:33] [PASSED] 3 VFs
[01:53:33] [PASSED] 4 VFs
[01:53:33] [PASSED] 5 VFs
[01:53:33] [PASSED] 6 VFs
[01:53:33] [PASSED] 7 VFs
[01:53:33] [PASSED] 8 VFs
[01:53:33] [PASSED] 9 VFs
[01:53:33] [PASSED] 10 VFs
[01:53:33] [PASSED] 11 VFs
[01:53:33] [PASSED] 12 VFs
[01:53:33] [PASSED] 13 VFs
[01:53:33] [PASSED] 14 VFs
[01:53:33] [PASSED] 15 VFs
[01:53:33] [PASSED] 16 VFs
[01:53:33] [PASSED] 17 VFs
[01:53:33] [PASSED] 18 VFs
[01:53:33] [PASSED] 19 VFs
[01:53:33] [PASSED] 20 VFs
[01:53:33] [PASSED] 21 VFs
[01:53:33] [PASSED] 22 VFs
[01:53:33] [PASSED] 23 VFs
[01:53:33] [PASSED] 24 VFs
[01:53:33] [PASSED] 25 VFs
[01:53:33] [PASSED] 26 VFs
[01:53:33] [PASSED] 27 VFs
[01:53:33] [PASSED] 28 VFs
[01:53:33] [PASSED] 29 VFs
[01:53:33] [PASSED] 30 VFs
[01:53:33] [PASSED] 31 VFs
[01:53:33] [PASSED] 32 VFs
[01:53:33] [PASSED] 33 VFs
[01:53:33] [PASSED] 34 VFs
[01:53:33] [PASSED] 35 VFs
[01:53:33] [PASSED] 36 VFs
[01:53:33] [PASSED] 37 VFs
[01:53:33] [PASSED] 38 VFs
[01:53:33] [PASSED] 39 VFs
[01:53:33] [PASSED] 40 VFs
[01:53:33] [PASSED] 41 VFs
[01:53:33] [PASSED] 42 VFs
[01:53:33] [PASSED] 43 VFs
[01:53:33] [PASSED] 44 VFs
[01:53:33] [PASSED] 45 VFs
[01:53:33] [PASSED] 46 VFs
[01:53:33] [PASSED] 47 VFs
[01:53:33] [PASSED] 48 VFs
[01:53:33] [PASSED] 49 VFs
[01:53:33] [PASSED] 50 VFs
[01:53:33] [PASSED] 51 VFs
[01:53:33] [PASSED] 52 VFs
[01:53:33] [PASSED] 53 VFs
[01:53:33] [PASSED] 54 VFs
[01:53:33] [PASSED] 55 VFs
[01:53:33] [PASSED] 56 VFs
[01:53:33] [PASSED] 57 VFs
[01:53:33] [PASSED] 58 VFs
[01:53:33] [PASSED] 59 VFs
[01:53:33] [PASSED] 60 VFs
[01:53:33] [PASSED] 61 VFs
[01:53:33] [PASSED] 62 VFs
[01:53:33] [PASSED] 63 VFs
[01:53:33] ================= [PASSED] fair_doorbells ==================
[01:53:33] ================== [PASSED] pf_gt_config ===================
[01:53:33] ===================== lmtt (1 subtest) =====================
[01:53:33] ======================== test_ops  =========================
[01:53:33] [PASSED] 2-level
[01:53:33] [PASSED] multi-level
[01:53:33] ==================== [PASSED] test_ops =====================
[01:53:33] ====================== [PASSED] lmtt =======================
[01:53:33] ================= pf_service (11 subtests) =================
[01:53:33] [PASSED] pf_negotiate_any
[01:53:33] [PASSED] pf_negotiate_base_match
[01:53:33] [PASSED] pf_negotiate_base_newer
[01:53:33] [PASSED] pf_negotiate_base_next
[01:53:33] [SKIPPED] pf_negotiate_base_older
[01:53:33] [PASSED] pf_negotiate_base_prev
[01:53:33] [PASSED] pf_negotiate_latest_match
[01:53:33] [PASSED] pf_negotiate_latest_newer
[01:53:33] [PASSED] pf_negotiate_latest_next
[01:53:33] [SKIPPED] pf_negotiate_latest_older
[01:53:33] [SKIPPED] pf_negotiate_latest_prev
[01:53:33] =================== [PASSED] pf_service ====================
[01:53:33] ================= xe_guc_g2g (2 subtests) ==================
[01:53:33] ============== xe_live_guc_g2g_kunit_default  ==============
[01:53:33] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[01:53:33] ============== xe_live_guc_g2g_kunit_allmem  ===============
[01:53:33] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[01:53:33] =================== [SKIPPED] xe_guc_g2g ===================
[01:53:33] =================== xe_mocs (2 subtests) ===================
[01:53:33] ================ xe_live_mocs_kernel_kunit  ================
[01:53:33] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[01:53:33] ================ xe_live_mocs_reset_kunit  =================
[01:53:33] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[01:53:33] ==================== [SKIPPED] xe_mocs =====================
[01:53:33] ================= xe_migrate (2 subtests) ==================
[01:53:33] ================= xe_migrate_sanity_kunit  =================
[01:53:33] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[01:53:33] ================== xe_validate_ccs_kunit  ==================
[01:53:33] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[01:53:33] =================== [SKIPPED] xe_migrate ===================
[01:53:33] ================== xe_dma_buf (1 subtest) ==================
[01:53:33] ==================== xe_dma_buf_kunit  =====================
[01:53:33] ================ [SKIPPED] xe_dma_buf_kunit ================
[01:53:33] =================== [SKIPPED] xe_dma_buf ===================
[01:53:33] ================= xe_bo_shrink (1 subtest) =================
[01:53:33] =================== xe_bo_shrink_kunit  ====================
[01:53:33] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[01:53:33] ================== [SKIPPED] xe_bo_shrink ==================
[01:53:33] ==================== xe_bo (2 subtests) ====================
[01:53:33] ================== xe_ccs_migrate_kunit  ===================
[01:53:33] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[01:53:33] ==================== xe_bo_evict_kunit  ====================
[01:53:33] =============== [SKIPPED] xe_bo_evict_kunit ================
[01:53:33] ===================== [SKIPPED] xe_bo ======================
[01:53:33] ==================== args (11 subtests) ====================
[01:53:33] [PASSED] count_args_test
[01:53:33] [PASSED] call_args_example
[01:53:33] [PASSED] call_args_test
[01:53:33] [PASSED] drop_first_arg_example
[01:53:33] [PASSED] drop_first_arg_test
[01:53:33] [PASSED] first_arg_example
[01:53:33] [PASSED] first_arg_test
[01:53:33] [PASSED] last_arg_example
[01:53:33] [PASSED] last_arg_test
[01:53:33] [PASSED] pick_arg_example
[01:53:33] [PASSED] sep_comma_example
[01:53:33] ====================== [PASSED] args =======================
[01:53:33] =================== xe_pci (3 subtests) ====================
[01:53:33] ==================== check_graphics_ip  ====================
[01:53:33] [PASSED] 12.00 Xe_LP
[01:53:33] [PASSED] 12.10 Xe_LP+
[01:53:33] [PASSED] 12.55 Xe_HPG
[01:53:33] [PASSED] 12.60 Xe_HPC
[01:53:33] [PASSED] 12.70 Xe_LPG
[01:53:33] [PASSED] 12.71 Xe_LPG
[01:53:33] [PASSED] 12.74 Xe_LPG+
[01:53:33] [PASSED] 20.01 Xe2_HPG
[01:53:33] [PASSED] 20.02 Xe2_HPG
[01:53:33] [PASSED] 20.04 Xe2_LPG
[01:53:33] [PASSED] 30.00 Xe3_LPG
[01:53:33] [PASSED] 30.01 Xe3_LPG
[01:53:33] [PASSED] 30.03 Xe3_LPG
[01:53:33] [PASSED] 30.04 Xe3_LPG
[01:53:33] [PASSED] 30.05 Xe3_LPG
[01:53:33] [PASSED] 35.11 Xe3p_XPC
[01:53:33] ================ [PASSED] check_graphics_ip ================
[01:53:33] ===================== check_media_ip  ======================
[01:53:33] [PASSED] 12.00 Xe_M
[01:53:33] [PASSED] 12.55 Xe_HPM
[01:53:33] [PASSED] 13.00 Xe_LPM+
[01:53:33] [PASSED] 13.01 Xe2_HPM
[01:53:33] [PASSED] 20.00 Xe2_LPM
[01:53:33] [PASSED] 30.00 Xe3_LPM
[01:53:33] [PASSED] 30.02 Xe3_LPM
[01:53:33] [PASSED] 35.00 Xe3p_LPM
[01:53:33] [PASSED] 35.03 Xe3p_HPM
[01:53:33] ================= [PASSED] check_media_ip ==================
[01:53:33] =================== check_platform_desc  ===================
[01:53:33] [PASSED] 0x9A60 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A68 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A70 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A40 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A49 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A59 (TIGERLAKE)
[01:53:33] [PASSED] 0x9A78 (TIGERLAKE)
[01:53:33] [PASSED] 0x9AC0 (TIGERLAKE)
[01:53:33] [PASSED] 0x9AC9 (TIGERLAKE)
[01:53:33] [PASSED] 0x9AD9 (TIGERLAKE)
[01:53:33] [PASSED] 0x9AF8 (TIGERLAKE)
[01:53:33] [PASSED] 0x4C80 (ROCKETLAKE)
[01:53:33] [PASSED] 0x4C8A (ROCKETLAKE)
[01:53:33] [PASSED] 0x4C8B (ROCKETLAKE)
[01:53:33] [PASSED] 0x4C8C (ROCKETLAKE)
[01:53:33] [PASSED] 0x4C90 (ROCKETLAKE)
[01:53:33] [PASSED] 0x4C9A (ROCKETLAKE)
[01:53:33] [PASSED] 0x4680 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4682 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4688 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x468A (ALDERLAKE_S)
[01:53:33] [PASSED] 0x468B (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4690 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4692 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4693 (ALDERLAKE_S)
[01:53:33] [PASSED] 0x46A0 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46A1 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46A2 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46A3 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46A6 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46A8 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46AA (ALDERLAKE_P)
[01:53:33] [PASSED] 0x462A (ALDERLAKE_P)
[01:53:33] [PASSED] 0x4626 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x4628 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46B0 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46B1 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46B2 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46B3 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46C0 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46C1 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46C2 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46C3 (ALDERLAKE_P)
[01:53:33] [PASSED] 0x46D0 (ALDERLAKE_N)
[01:53:33] [PASSED] 0x46D1 (ALDERLAKE_N)
[01:53:33] [PASSED] 0x46D2 (ALDERLAKE_N)
[01:53:33] [PASSED] 0x46D3 (ALDERLAKE_N)
[01:53:33] [PASSED] 0x46D4 (ALDERLAKE_N)
[01:53:33] [PASSED] 0xA721 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7A1 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7A9 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7AC (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7AD (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA720 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7A0 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7A8 (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7AA (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA7AB (ALDERLAKE_P)
[01:53:33] [PASSED] 0xA780 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA781 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA782 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA783 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA788 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA789 (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA78A (ALDERLAKE_S)
[01:53:33] [PASSED] 0xA78B (ALDERLAKE_S)
[01:53:33] [PASSED] 0x4905 (DG1)
[01:53:33] [PASSED] 0x4906 (DG1)
[01:53:33] [PASSED] 0x4907 (DG1)
[01:53:33] [PASSED] 0x4908 (DG1)
[01:53:33] [PASSED] 0x4909 (DG1)
[01:53:33] [PASSED] 0x56C0 (DG2)
[01:53:33] [PASSED] 0x56C2 (DG2)
[01:53:33] [PASSED] 0x56C1 (DG2)
[01:53:33] [PASSED] 0x7D51 (METEORLAKE)
[01:53:33] [PASSED] 0x7DD1 (METEORLAKE)
[01:53:33] [PASSED] 0x7D41 (METEORLAKE)
[01:53:33] [PASSED] 0x7D67 (METEORLAKE)
[01:53:33] [PASSED] 0xB640 (METEORLAKE)
[01:53:33] [PASSED] 0x56A0 (DG2)
[01:53:33] [PASSED] 0x56A1 (DG2)
[01:53:33] [PASSED] 0x56A2 (DG2)
[01:53:33] [PASSED] 0x56BE (DG2)
[01:53:33] [PASSED] 0x56BF (DG2)
[01:53:33] [PASSED] 0x5690 (DG2)
stty: 'standard input': Inappropriate ioctl for device
[01:53:33] [PASSED] 0x5691 (DG2)
[01:53:33] [PASSED] 0x5692 (DG2)
[01:53:33] [PASSED] 0x56A5 (DG2)
[01:53:33] [PASSED] 0x56A6 (DG2)
[01:53:33] [PASSED] 0x56B0 (DG2)
[01:53:33] [PASSED] 0x56B1 (DG2)
[01:53:33] [PASSED] 0x56BA (DG2)
[01:53:33] [PASSED] 0x56BB (DG2)
[01:53:33] [PASSED] 0x56BC (DG2)
[01:53:33] [PASSED] 0x56BD (DG2)
[01:53:33] [PASSED] 0x5693 (DG2)
[01:53:33] [PASSED] 0x5694 (DG2)
[01:53:33] [PASSED] 0x5695 (DG2)
[01:53:33] [PASSED] 0x56A3 (DG2)
[01:53:33] [PASSED] 0x56A4 (DG2)
[01:53:33] [PASSED] 0x56B2 (DG2)
[01:53:33] [PASSED] 0x56B3 (DG2)
[01:53:33] [PASSED] 0x5696 (DG2)
[01:53:33] [PASSED] 0x5697 (DG2)
[01:53:33] [PASSED] 0xB69 (PVC)
[01:53:33] [PASSED] 0xB6E (PVC)
[01:53:33] [PASSED] 0xBD4 (PVC)
[01:53:33] [PASSED] 0xBD5 (PVC)
[01:53:33] [PASSED] 0xBD6 (PVC)
[01:53:33] [PASSED] 0xBD7 (PVC)
[01:53:33] [PASSED] 0xBD8 (PVC)
[01:53:33] [PASSED] 0xBD9 (PVC)
[01:53:33] [PASSED] 0xBDA (PVC)
[01:53:33] [PASSED] 0xBDB (PVC)
[01:53:33] [PASSED] 0xBE0 (PVC)
[01:53:33] [PASSED] 0xBE1 (PVC)
[01:53:33] [PASSED] 0xBE5 (PVC)
[01:53:33] [PASSED] 0x7D40 (METEORLAKE)
[01:53:33] [PASSED] 0x7D45 (METEORLAKE)
[01:53:33] [PASSED] 0x7D55 (METEORLAKE)
[01:53:33] [PASSED] 0x7D60 (METEORLAKE)
[01:53:33] [PASSED] 0x7DD5 (METEORLAKE)
[01:53:33] [PASSED] 0x6420 (LUNARLAKE)
[01:53:33] [PASSED] 0x64A0 (LUNARLAKE)
[01:53:33] [PASSED] 0x64B0 (LUNARLAKE)
[01:53:33] [PASSED] 0xE202 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE209 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE20B (BATTLEMAGE)
[01:53:33] [PASSED] 0xE20C (BATTLEMAGE)
[01:53:33] [PASSED] 0xE20D (BATTLEMAGE)
[01:53:33] [PASSED] 0xE210 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE211 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE212 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE216 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE220 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE221 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE222 (BATTLEMAGE)
[01:53:33] [PASSED] 0xE223 (BATTLEMAGE)
[01:53:33] [PASSED] 0xB080 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB081 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB082 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB083 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB084 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB085 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB086 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB087 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB08F (PANTHERLAKE)
[01:53:33] [PASSED] 0xB090 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB0A0 (PANTHERLAKE)
[01:53:33] [PASSED] 0xB0B0 (PANTHERLAKE)
[01:53:33] [PASSED] 0xD740 (NOVALAKE_S)
[01:53:33] [PASSED] 0xD741 (NOVALAKE_S)
[01:53:33] [PASSED] 0xD742 (NOVALAKE_S)
[01:53:33] [PASSED] 0xD743 (NOVALAKE_S)
[01:53:33] [PASSED] 0xD744 (NOVALAKE_S)
[01:53:33] [PASSED] 0xD745 (NOVALAKE_S)
[01:53:33] [PASSED] 0x674C (CRESCENTISLAND)
[01:53:33] [PASSED] 0xFD80 (PANTHERLAKE)
[01:53:33] [PASSED] 0xFD81 (PANTHERLAKE)
[01:53:33] =============== [PASSED] check_platform_desc ===============
[01:53:33] ===================== [PASSED] xe_pci ======================
[01:53:33] =================== xe_rtp (2 subtests) ====================
[01:53:33] =============== xe_rtp_process_to_sr_tests  ================
[01:53:33] [PASSED] coalesce-same-reg
[01:53:33] [PASSED] no-match-no-add
[01:53:33] [PASSED] match-or
[01:53:33] [PASSED] match-or-xfail
[01:53:33] [PASSED] no-match-no-add-multiple-rules
[01:53:33] [PASSED] two-regs-two-entries
[01:53:33] [PASSED] clr-one-set-other
[01:53:33] [PASSED] set-field
[01:53:33] [PASSED] conflict-duplicate
[01:53:33] [PASSED] conflict-not-disjoint
[01:53:33] [PASSED] conflict-reg-type
[01:53:33] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[01:53:33] ================== xe_rtp_process_tests  ===================
[01:53:33] [PASSED] active1
[01:53:33] [PASSED] active2
[01:53:33] [PASSED] active-inactive
[01:53:33] [PASSED] inactive-active
[01:53:33] [PASSED] inactive-1st_or_active-inactive
[01:53:33] [PASSED] inactive-2nd_or_active-inactive
[01:53:33] [PASSED] inactive-last_or_active-inactive
[01:53:33] [PASSED] inactive-no_or_active-inactive
[01:53:33] ============== [PASSED] xe_rtp_process_tests ===============
[01:53:33] ===================== [PASSED] xe_rtp ======================
[01:53:33] ==================== xe_wa (1 subtest) =====================
[01:53:33] ======================== xe_wa_gt  =========================
[01:53:33] [PASSED] TIGERLAKE B0
[01:53:33] [PASSED] DG1 A0
[01:53:33] [PASSED] DG1 B0
[01:53:33] [PASSED] ALDERLAKE_S A0
[01:53:33] [PASSED] ALDERLAKE_S B0
[01:53:33] [PASSED] ALDERLAKE_S C0
[01:53:33] [PASSED] ALDERLAKE_S D0
[01:53:33] [PASSED] ALDERLAKE_P A0
[01:53:33] [PASSED] ALDERLAKE_P B0
[01:53:33] [PASSED] ALDERLAKE_P C0
[01:53:33] [PASSED] ALDERLAKE_S RPLS D0
[01:53:33] [PASSED] ALDERLAKE_P RPLU E0
[01:53:33] [PASSED] DG2 G10 C0
[01:53:33] [PASSED] DG2 G11 B1
[01:53:33] [PASSED] DG2 G12 A1
[01:53:33] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[01:53:33] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[01:53:33] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[01:53:33] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[01:53:33] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[01:53:33] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[01:53:33] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[01:53:33] ==================== [PASSED] xe_wa_gt =====================
[01:53:33] ====================== [PASSED] xe_wa ======================
[01:53:33] ============================================================
[01:53:33] Testing complete. Ran 446 tests: passed: 428, skipped: 18
[01:53:33] Elapsed time: 34.802s total, 4.163s configuring, 30.173s building, 0.429s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[01:53:33] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[01:53:35] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[01:54:00] Starting KUnit Kernel (1/1)...
[01:54:00] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[01:54:00] ============ drm_test_pick_cmdline (2 subtests) ============
[01:54:00] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[01:54:00] =============== drm_test_pick_cmdline_named  ===============
[01:54:00] [PASSED] NTSC
[01:54:00] [PASSED] NTSC-J
[01:54:00] [PASSED] PAL
[01:54:00] [PASSED] PAL-M
[01:54:00] =========== [PASSED] drm_test_pick_cmdline_named ===========
[01:54:00] ============== [PASSED] drm_test_pick_cmdline ==============
[01:54:00] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[01:54:00] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[01:54:00] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[01:54:00] =========== drm_validate_clone_mode (2 subtests) ===========
[01:54:00] ============== drm_test_check_in_clone_mode  ===============
[01:54:00] [PASSED] in_clone_mode
[01:54:00] [PASSED] not_in_clone_mode
[01:54:00] ========== [PASSED] drm_test_check_in_clone_mode ===========
[01:54:00] =============== drm_test_check_valid_clones  ===============
[01:54:00] [PASSED] not_in_clone_mode
[01:54:00] [PASSED] valid_clone
[01:54:00] [PASSED] invalid_clone
[01:54:00] =========== [PASSED] drm_test_check_valid_clones ===========
[01:54:00] ============= [PASSED] drm_validate_clone_mode =============
[01:54:00] ============= drm_validate_modeset (1 subtest) =============
[01:54:00] [PASSED] drm_test_check_connector_changed_modeset
[01:54:00] ============== [PASSED] drm_validate_modeset ===============
[01:54:00] ====== drm_test_bridge_get_current_state (2 subtests) ======
[01:54:00] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[01:54:00] [PASSED] drm_test_drm_bridge_get_current_state_legacy
[01:54:00] ======== [PASSED] drm_test_bridge_get_current_state ========
[01:54:00] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[01:54:00] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[01:54:00] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[01:54:00] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy
[01:54:00] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[01:54:00] ============== drm_bridge_alloc (2 subtests) ===============
[01:54:00] [PASSED] drm_test_drm_bridge_alloc_basic
[01:54:00] [PASSED] drm_test_drm_bridge_alloc_get_put
[01:54:00] ================ [PASSED] drm_bridge_alloc =================
[01:54:00] ================== drm_buddy (8 subtests) ==================
[01:54:00] [PASSED] drm_test_buddy_alloc_limit
[01:54:00] [PASSED] drm_test_buddy_alloc_optimistic
[01:54:00] [PASSED] drm_test_buddy_alloc_pessimistic
[01:54:00] [PASSED] drm_test_buddy_alloc_pathological
[01:54:00] [PASSED] drm_test_buddy_alloc_contiguous
[01:54:00] [PASSED] drm_test_buddy_alloc_clear
[01:54:00] [PASSED] drm_test_buddy_alloc_range_bias
[01:54:00] [PASSED] drm_test_buddy_fragmentation_performance
[01:54:00] ==================== [PASSED] drm_buddy ====================
[01:54:00] ============= drm_cmdline_parser (40 subtests) =============
[01:54:00] [PASSED] drm_test_cmdline_force_d_only
[01:54:00] [PASSED] drm_test_cmdline_force_D_only_dvi
[01:54:00] [PASSED] drm_test_cmdline_force_D_only_hdmi
[01:54:00] [PASSED] drm_test_cmdline_force_D_only_not_digital
[01:54:00] [PASSED] drm_test_cmdline_force_e_only
[01:54:00] [PASSED] drm_test_cmdline_res
[01:54:00] [PASSED] drm_test_cmdline_res_vesa
[01:54:00] [PASSED] drm_test_cmdline_res_vesa_rblank
[01:54:00] [PASSED] drm_test_cmdline_res_rblank
[01:54:00] [PASSED] drm_test_cmdline_res_bpp
[01:54:00] [PASSED] drm_test_cmdline_res_refresh
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[01:54:00] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[01:54:00] [PASSED] drm_test_cmdline_res_margins_force_on
[01:54:00] [PASSED] drm_test_cmdline_res_vesa_margins
[01:54:00] [PASSED] drm_test_cmdline_name
[01:54:00] [PASSED] drm_test_cmdline_name_bpp
[01:54:00] [PASSED] drm_test_cmdline_name_option
[01:54:00] [PASSED] drm_test_cmdline_name_bpp_option
[01:54:00] [PASSED] drm_test_cmdline_rotate_0
[01:54:00] [PASSED] drm_test_cmdline_rotate_90
[01:54:00] [PASSED] drm_test_cmdline_rotate_180
[01:54:00] [PASSED] drm_test_cmdline_rotate_270
[01:54:00] [PASSED] drm_test_cmdline_hmirror
[01:54:00] [PASSED] drm_test_cmdline_vmirror
[01:54:00] [PASSED] drm_test_cmdline_margin_options
[01:54:00] [PASSED] drm_test_cmdline_multiple_options
[01:54:00] [PASSED] drm_test_cmdline_bpp_extra_and_option
[01:54:00] [PASSED] drm_test_cmdline_extra_and_option
[01:54:00] [PASSED] drm_test_cmdline_freestanding_options
[01:54:00] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[01:54:00] [PASSED] drm_test_cmdline_panel_orientation
[01:54:00] ================ drm_test_cmdline_invalid  =================
[01:54:00] [PASSED] margin_only
[01:54:00] [PASSED] interlace_only
[01:54:00] [PASSED] res_missing_x
[01:54:00] [PASSED] res_missing_y
[01:54:00] [PASSED] res_bad_y
[01:54:00] [PASSED] res_missing_y_bpp
[01:54:00] [PASSED] res_bad_bpp
[01:54:00] [PASSED] res_bad_refresh
[01:54:00] [PASSED] res_bpp_refresh_force_on_off
[01:54:00] [PASSED] res_invalid_mode
[01:54:00] [PASSED] res_bpp_wrong_place_mode
[01:54:00] [PASSED] name_bpp_refresh
[01:54:00] [PASSED] name_refresh
[01:54:00] [PASSED] name_refresh_wrong_mode
[01:54:00] [PASSED] name_refresh_invalid_mode
[01:54:00] [PASSED] rotate_multiple
[01:54:00] [PASSED] rotate_invalid_val
[01:54:00] [PASSED] rotate_truncated
[01:54:00] [PASSED] invalid_option
[01:54:00] [PASSED] invalid_tv_option
[01:54:00] [PASSED] truncated_tv_option
[01:54:00] ============ [PASSED] drm_test_cmdline_invalid =============
[01:54:00] =============== drm_test_cmdline_tv_options  ===============
[01:54:00] [PASSED] NTSC
[01:54:00] [PASSED] NTSC_443
[01:54:00] [PASSED] NTSC_J
[01:54:00] [PASSED] PAL
[01:54:00] [PASSED] PAL_M
[01:54:00] [PASSED] PAL_N
[01:54:00] [PASSED] SECAM
[01:54:00] [PASSED] MONO_525
[01:54:00] [PASSED] MONO_625
[01:54:00] =========== [PASSED] drm_test_cmdline_tv_options ===========
[01:54:00] =============== [PASSED] drm_cmdline_parser ================
[01:54:00] ========== drmm_connector_hdmi_init (20 subtests) ==========
[01:54:00] [PASSED] drm_test_connector_hdmi_init_valid
[01:54:00] [PASSED] drm_test_connector_hdmi_init_bpc_8
[01:54:00] [PASSED] drm_test_connector_hdmi_init_bpc_10
[01:54:00] [PASSED] drm_test_connector_hdmi_init_bpc_12
[01:54:00] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[01:54:00] [PASSED] drm_test_connector_hdmi_init_bpc_null
[01:54:00] [PASSED] drm_test_connector_hdmi_init_formats_empty
[01:54:00] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[01:54:00] === drm_test_connector_hdmi_init_formats_yuv420_allowed  ===
[01:54:00] [PASSED] supported_formats=0x9 yuv420_allowed=1
[01:54:00] [PASSED] supported_formats=0x9 yuv420_allowed=0
[01:54:00] [PASSED] supported_formats=0x3 yuv420_allowed=1
[01:54:00] [PASSED] supported_formats=0x3 yuv420_allowed=0
[01:54:00] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[01:54:00] [PASSED] drm_test_connector_hdmi_init_null_ddc
[01:54:00] [PASSED] drm_test_connector_hdmi_init_null_product
[01:54:00] [PASSED] drm_test_connector_hdmi_init_null_vendor
[01:54:00] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[01:54:00] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[01:54:00] [PASSED] drm_test_connector_hdmi_init_product_valid
[01:54:00] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[01:54:00] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[01:54:00] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[01:54:00] ========= drm_test_connector_hdmi_init_type_valid  =========
[01:54:00] [PASSED] HDMI-A
[01:54:00] [PASSED] HDMI-B
[01:54:00] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[01:54:00] ======== drm_test_connector_hdmi_init_type_invalid  ========
[01:54:00] [PASSED] Unknown
[01:54:00] [PASSED] VGA
[01:54:00] [PASSED] DVI-I
[01:54:00] [PASSED] DVI-D
[01:54:00] [PASSED] DVI-A
[01:54:00] [PASSED] Composite
[01:54:00] [PASSED] SVIDEO
[01:54:00] [PASSED] LVDS
[01:54:00] [PASSED] Component
[01:54:00] [PASSED] DIN
[01:54:00] [PASSED] DP
[01:54:00] [PASSED] TV
[01:54:00] [PASSED] eDP
[01:54:00] [PASSED] Virtual
[01:54:00] [PASSED] DSI
[01:54:00] [PASSED] DPI
[01:54:00] [PASSED] Writeback
[01:54:00] [PASSED] SPI
[01:54:00] [PASSED] USB
[01:54:00] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[01:54:00] ============ [PASSED] drmm_connector_hdmi_init =============
[01:54:00] ============= drmm_connector_init (3 subtests) =============
[01:54:00] [PASSED] drm_test_drmm_connector_init
[01:54:00] [PASSED] drm_test_drmm_connector_init_null_ddc
[01:54:00] ========= drm_test_drmm_connector_init_type_valid  =========
[01:54:00] [PASSED] Unknown
[01:54:00] [PASSED] VGA
[01:54:00] [PASSED] DVI-I
[01:54:00] [PASSED] DVI-D
[01:54:00] [PASSED] DVI-A
[01:54:00] [PASSED] Composite
[01:54:00] [PASSED] SVIDEO
[01:54:00] [PASSED] LVDS
[01:54:00] [PASSED] Component
[01:54:00] [PASSED] DIN
[01:54:00] [PASSED] DP
[01:54:00] [PASSED] HDMI-A
[01:54:00] [PASSED] HDMI-B
[01:54:00] [PASSED] TV
[01:54:00] [PASSED] eDP
[01:54:00] [PASSED] Virtual
[01:54:00] [PASSED] DSI
[01:54:00] [PASSED] DPI
[01:54:00] [PASSED] Writeback
[01:54:00] [PASSED] SPI
[01:54:00] [PASSED] USB
[01:54:00] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[01:54:00] =============== [PASSED] drmm_connector_init ===============
[01:54:00] ========= drm_connector_dynamic_init (6 subtests) ==========
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_init
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_init_properties
[01:54:00] ===== drm_test_drm_connector_dynamic_init_type_valid  ======
[01:54:00] [PASSED] Unknown
[01:54:00] [PASSED] VGA
[01:54:00] [PASSED] DVI-I
[01:54:00] [PASSED] DVI-D
[01:54:00] [PASSED] DVI-A
[01:54:00] [PASSED] Composite
[01:54:00] [PASSED] SVIDEO
[01:54:00] [PASSED] LVDS
[01:54:00] [PASSED] Component
[01:54:00] [PASSED] DIN
[01:54:00] [PASSED] DP
[01:54:00] [PASSED] HDMI-A
[01:54:00] [PASSED] HDMI-B
[01:54:00] [PASSED] TV
[01:54:00] [PASSED] eDP
[01:54:00] [PASSED] Virtual
[01:54:00] [PASSED] DSI
[01:54:00] [PASSED] DPI
[01:54:00] [PASSED] Writeback
[01:54:00] [PASSED] SPI
[01:54:00] [PASSED] USB
[01:54:00] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[01:54:00] ======== drm_test_drm_connector_dynamic_init_name  =========
[01:54:00] [PASSED] Unknown
[01:54:00] [PASSED] VGA
[01:54:00] [PASSED] DVI-I
[01:54:00] [PASSED] DVI-D
[01:54:00] [PASSED] DVI-A
[01:54:00] [PASSED] Composite
[01:54:00] [PASSED] SVIDEO
[01:54:00] [PASSED] LVDS
[01:54:00] [PASSED] Component
[01:54:00] [PASSED] DIN
[01:54:00] [PASSED] DP
[01:54:00] [PASSED] HDMI-A
[01:54:00] [PASSED] HDMI-B
[01:54:00] [PASSED] TV
[01:54:00] [PASSED] eDP
[01:54:00] [PASSED] Virtual
[01:54:00] [PASSED] DSI
[01:54:00] [PASSED] DPI
[01:54:00] [PASSED] Writeback
[01:54:00] [PASSED] SPI
[01:54:00] [PASSED] USB
[01:54:00] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[01:54:00] =========== [PASSED] drm_connector_dynamic_init ============
[01:54:00] ==== drm_connector_dynamic_register_early (4 subtests) =====
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[01:54:00] ====== [PASSED] drm_connector_dynamic_register_early =======
[01:54:00] ======= drm_connector_dynamic_register (7 subtests) ========
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[01:54:00] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[01:54:00] ========= [PASSED] drm_connector_dynamic_register ==========
[01:54:00] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[01:54:00] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[01:54:00] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[01:54:00] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[01:54:00] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[01:54:00] ========== drm_test_get_tv_mode_from_name_valid  ===========
[01:54:00] [PASSED] NTSC
[01:54:00] [PASSED] NTSC-443
[01:54:00] [PASSED] NTSC-J
[01:54:00] [PASSED] PAL
[01:54:00] [PASSED] PAL-M
[01:54:00] [PASSED] PAL-N
[01:54:00] [PASSED] SECAM
[01:54:00] [PASSED] Mono
[01:54:00] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[01:54:00] [PASSED] drm_test_get_tv_mode_from_name_truncated
[01:54:00] ============ [PASSED] drm_get_tv_mode_from_name ============
[01:54:00] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[01:54:00] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[01:54:00] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid  =
[01:54:00] [PASSED] VIC 96
[01:54:00] [PASSED] VIC 97
[01:54:00] [PASSED] VIC 101
[01:54:00] [PASSED] VIC 102
[01:54:00] [PASSED] VIC 106
[01:54:00] [PASSED] VIC 107
[01:54:00] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[01:54:00] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[01:54:00] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[01:54:00] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[01:54:00] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[01:54:00] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[01:54:00] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[01:54:00] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[01:54:00] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name  ====
[01:54:00] [PASSED] Automatic
[01:54:00] [PASSED] Full
[01:54:00] [PASSED] Limited 16:235
[01:54:00] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[01:54:00] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[01:54:00] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[01:54:00] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[01:54:00] === drm_test_drm_hdmi_connector_get_output_format_name  ====
[01:54:00] [PASSED] RGB
[01:54:00] [PASSED] YUV 4:2:0
[01:54:00] [PASSED] YUV 4:2:2
[01:54:00] [PASSED] YUV 4:4:4
[01:54:00] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[01:54:00] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[01:54:00] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[01:54:00] ============= drm_damage_helper (21 subtests) ==============
[01:54:00] [PASSED] drm_test_damage_iter_no_damage
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_src_moved
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_not_visible
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[01:54:00] [PASSED] drm_test_damage_iter_no_damage_no_fb
[01:54:00] [PASSED] drm_test_damage_iter_simple_damage
[01:54:00] [PASSED] drm_test_damage_iter_single_damage
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_outside_src
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_src_moved
[01:54:00] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[01:54:00] [PASSED] drm_test_damage_iter_damage
[01:54:00] [PASSED] drm_test_damage_iter_damage_one_intersect
[01:54:00] [PASSED] drm_test_damage_iter_damage_one_outside
[01:54:00] [PASSED] drm_test_damage_iter_damage_src_moved
[01:54:00] [PASSED] drm_test_damage_iter_damage_not_visible
[01:54:00] ================ [PASSED] drm_damage_helper ================
[01:54:00] ============== drm_dp_mst_helper (3 subtests) ==============
[01:54:00] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[01:54:00] [PASSED] Clock 154000 BPP 30 DSC disabled
[01:54:00] [PASSED] Clock 234000 BPP 30 DSC disabled
[01:54:00] [PASSED] Clock 297000 BPP 24 DSC disabled
[01:54:00] [PASSED] Clock 332880 BPP 24 DSC enabled
[01:54:00] [PASSED] Clock 324540 BPP 24 DSC enabled
[01:54:00] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[01:54:00] ============== drm_test_dp_mst_calc_pbn_div  ===============
[01:54:00] [PASSED] Link rate 2000000 lane count 4
[01:54:00] [PASSED] Link rate 2000000 lane count 2
[01:54:00] [PASSED] Link rate 2000000 lane count 1
[01:54:00] [PASSED] Link rate 1350000 lane count 4
[01:54:00] [PASSED] Link rate 1350000 lane count 2
[01:54:00] [PASSED] Link rate 1350000 lane count 1
[01:54:00] [PASSED] Link rate 1000000 lane count 4
[01:54:00] [PASSED] Link rate 1000000 lane count 2
[01:54:00] [PASSED] Link rate 1000000 lane count 1
[01:54:00] [PASSED] Link rate 810000 lane count 4
[01:54:00] [PASSED] Link rate 810000 lane count 2
[01:54:00] [PASSED] Link rate 810000 lane count 1
[01:54:00] [PASSED] Link rate 540000 lane count 4
[01:54:00] [PASSED] Link rate 540000 lane count 2
[01:54:00] [PASSED] Link rate 540000 lane count 1
[01:54:00] [PASSED] Link rate 270000 lane count 4
[01:54:00] [PASSED] Link rate 270000 lane count 2
[01:54:00] [PASSED] Link rate 270000 lane count 1
[01:54:00] [PASSED] Link rate 162000 lane count 4
[01:54:00] [PASSED] Link rate 162000 lane count 2
[01:54:00] [PASSED] Link rate 162000 lane count 1
[01:54:00] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[01:54:00] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[01:54:00] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[01:54:00] [PASSED] DP_POWER_UP_PHY with port number
[01:54:00] [PASSED] DP_POWER_DOWN_PHY with port number
[01:54:00] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[01:54:00] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[01:54:00] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[01:54:00] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[01:54:00] [PASSED] DP_QUERY_PAYLOAD with port number
[01:54:00] [PASSED] DP_QUERY_PAYLOAD with VCPI
[01:54:00] [PASSED] DP_REMOTE_DPCD_READ with port number
[01:54:00] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[01:54:00] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[01:54:00] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[01:54:00] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[01:54:00] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[01:54:00] [PASSED] DP_REMOTE_I2C_READ with port number
[01:54:00] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[01:54:00] [PASSED] DP_REMOTE_I2C_READ with transactions array
[01:54:00] [PASSED] DP_REMOTE_I2C_WRITE with port number
[01:54:00] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[01:54:00] [PASSED] DP_REMOTE_I2C_WRITE with data array
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[01:54:00] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[01:54:00] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[01:54:00] ================ [PASSED] drm_dp_mst_helper ================
[01:54:00] ================== drm_exec (7 subtests) ===================
[01:54:00] [PASSED] sanitycheck
[01:54:00] [PASSED] test_lock
[01:54:00] [PASSED] test_lock_unlock
[01:54:00] [PASSED] test_duplicates
[01:54:00] [PASSED] test_prepare
[01:54:00] [PASSED] test_prepare_array
[01:54:00] [PASSED] test_multiple_loops
[01:54:00] ==================== [PASSED] drm_exec =====================
[01:54:00] =========== drm_format_helper_test (17 subtests) ===========
[01:54:00] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[01:54:00] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[01:54:00] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[01:54:00] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[01:54:00] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[01:54:00] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[01:54:00] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[01:54:00] ============= drm_test_fb_xrgb8888_to_bgr888  ==============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[01:54:00] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[01:54:00] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[01:54:00] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[01:54:00] ============== drm_test_fb_xrgb8888_to_mono  ===============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[01:54:00] ==================== drm_test_fb_swab  =====================
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ================ [PASSED] drm_test_fb_swab =================
[01:54:00] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[01:54:00] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[01:54:00] [PASSED] single_pixel_source_buffer
[01:54:00] [PASSED] single_pixel_clip_rectangle
[01:54:00] [PASSED] well_known_colors
[01:54:00] [PASSED] destination_pitch
[01:54:00] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[01:54:00] ================= drm_test_fb_clip_offset  =================
[01:54:00] [PASSED] pass through
[01:54:00] [PASSED] horizontal offset
[01:54:00] [PASSED] vertical offset
[01:54:00] [PASSED] horizontal and vertical offset
[01:54:00] [PASSED] horizontal offset (custom pitch)
[01:54:00] [PASSED] vertical offset (custom pitch)
[01:54:00] [PASSED] horizontal and vertical offset (custom pitch)
[01:54:00] ============= [PASSED] drm_test_fb_clip_offset =============
[01:54:00] =================== drm_test_fb_memcpy  ====================
[01:54:00] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[01:54:00] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[01:54:00] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[01:54:00] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[01:54:00] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[01:54:00] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[01:54:00] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[01:54:00] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[01:54:00] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[01:54:00] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[01:54:00] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[01:54:00] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[01:54:00] =============== [PASSED] drm_test_fb_memcpy ================
[01:54:00] ============= [PASSED] drm_format_helper_test ==============
[01:54:00] ================= drm_format (18 subtests) =================
[01:54:00] [PASSED] drm_test_format_block_width_invalid
[01:54:00] [PASSED] drm_test_format_block_width_one_plane
[01:54:00] [PASSED] drm_test_format_block_width_two_plane
[01:54:00] [PASSED] drm_test_format_block_width_three_plane
[01:54:00] [PASSED] drm_test_format_block_width_tiled
[01:54:00] [PASSED] drm_test_format_block_height_invalid
[01:54:00] [PASSED] drm_test_format_block_height_one_plane
[01:54:00] [PASSED] drm_test_format_block_height_two_plane
[01:54:00] [PASSED] drm_test_format_block_height_three_plane
[01:54:00] [PASSED] drm_test_format_block_height_tiled
[01:54:00] [PASSED] drm_test_format_min_pitch_invalid
[01:54:00] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[01:54:00] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[01:54:00] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[01:54:00] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[01:54:00] [PASSED] drm_test_format_min_pitch_two_plane
[01:54:00] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[01:54:00] [PASSED] drm_test_format_min_pitch_tiled
[01:54:00] =================== [PASSED] drm_format ====================
[01:54:00] ============== drm_framebuffer (10 subtests) ===============
[01:54:00] ========== drm_test_framebuffer_check_src_coords  ==========
[01:54:00] [PASSED] Success: source fits into fb
[01:54:00] [PASSED] Fail: overflowing fb with x-axis coordinate
[01:54:00] [PASSED] Fail: overflowing fb with y-axis coordinate
[01:54:00] [PASSED] Fail: overflowing fb with source width
[01:54:00] [PASSED] Fail: overflowing fb with source height
[01:54:00] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[01:54:00] [PASSED] drm_test_framebuffer_cleanup
[01:54:00] =============== drm_test_framebuffer_create  ===============
[01:54:00] [PASSED] ABGR8888 normal sizes
[01:54:00] [PASSED] ABGR8888 max sizes
[01:54:00] [PASSED] ABGR8888 pitch greater than min required
[01:54:00] [PASSED] ABGR8888 pitch less than min required
[01:54:00] [PASSED] ABGR8888 Invalid width
[01:54:00] [PASSED] ABGR8888 Invalid buffer handle
[01:54:00] [PASSED] No pixel format
[01:54:00] [PASSED] ABGR8888 Width 0
[01:54:00] [PASSED] ABGR8888 Height 0
[01:54:00] [PASSED] ABGR8888 Out of bound height * pitch combination
[01:54:00] [PASSED] ABGR8888 Large buffer offset
[01:54:00] [PASSED] ABGR8888 Buffer offset for inexistent plane
[01:54:00] [PASSED] ABGR8888 Invalid flag
[01:54:00] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[01:54:00] [PASSED] ABGR8888 Valid buffer modifier
[01:54:00] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[01:54:00] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] NV12 Normal sizes
[01:54:00] [PASSED] NV12 Max sizes
[01:54:00] [PASSED] NV12 Invalid pitch
[01:54:00] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[01:54:00] [PASSED] NV12 different  modifier per-plane
[01:54:00] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[01:54:00] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] NV12 Modifier for inexistent plane
[01:54:00] [PASSED] NV12 Handle for inexistent plane
[01:54:00] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[01:54:00] [PASSED] YVU420 Normal sizes
[01:54:00] [PASSED] YVU420 Max sizes
[01:54:00] [PASSED] YVU420 Invalid pitch
[01:54:00] [PASSED] YVU420 Different pitches
[01:54:00] [PASSED] YVU420 Different buffer offsets/pitches
[01:54:00] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[01:54:00] [PASSED] YVU420 Valid modifier
[01:54:00] [PASSED] YVU420 Different modifiers per plane
[01:54:00] [PASSED] YVU420 Modifier for inexistent plane
[01:54:00] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[01:54:00] [PASSED] X0L2 Normal sizes
[01:54:00] [PASSED] X0L2 Max sizes
[01:54:00] [PASSED] X0L2 Invalid pitch
[01:54:00] [PASSED] X0L2 Pitch greater than minimum required
[01:54:00] [PASSED] X0L2 Handle for inexistent plane
[01:54:00] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[01:54:00] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[01:54:00] [PASSED] X0L2 Valid modifier
[01:54:00] [PASSED] X0L2 Modifier for inexistent plane
[01:54:00] =========== [PASSED] drm_test_framebuffer_create ===========
[01:54:00] [PASSED] drm_test_framebuffer_free
[01:54:00] [PASSED] drm_test_framebuffer_init
[01:54:00] [PASSED] drm_test_framebuffer_init_bad_format
[01:54:00] [PASSED] drm_test_framebuffer_init_dev_mismatch
[01:54:00] [PASSED] drm_test_framebuffer_lookup
[01:54:00] [PASSED] drm_test_framebuffer_lookup_inexistent
[01:54:00] [PASSED] drm_test_framebuffer_modifiers_not_supported
[01:54:00] ================= [PASSED] drm_framebuffer =================
[01:54:00] ================ drm_gem_shmem (8 subtests) ================
[01:54:00] [PASSED] drm_gem_shmem_test_obj_create
[01:54:00] [PASSED] drm_gem_shmem_test_obj_create_private
[01:54:00] [PASSED] drm_gem_shmem_test_pin_pages
[01:54:00] [PASSED] drm_gem_shmem_test_vmap
[01:54:00] [PASSED] drm_gem_shmem_test_get_pages_sgt
[01:54:00] [PASSED] drm_gem_shmem_test_get_sg_table
[01:54:00] [PASSED] drm_gem_shmem_test_madvise
[01:54:00] [PASSED] drm_gem_shmem_test_purge
[01:54:00] ================== [PASSED] drm_gem_shmem ==================
[01:54:00] === drm_atomic_helper_connector_hdmi_check (27 subtests) ===
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[01:54:00] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420  =======
[01:54:00] [PASSED] Automatic
[01:54:00] [PASSED] Full
[01:54:00] [PASSED] Limited 16:235
[01:54:00] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[01:54:00] [PASSED] drm_test_check_disable_connector
[01:54:00] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[01:54:00] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[01:54:00] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[01:54:00] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[01:54:00] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[01:54:00] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[01:54:00] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[01:54:00] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[01:54:00] [PASSED] drm_test_check_output_bpc_dvi
[01:54:00] [PASSED] drm_test_check_output_bpc_format_vic_1
[01:54:00] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[01:54:00] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[01:54:00] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[01:54:00] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[01:54:00] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[01:54:00] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[01:54:00] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[01:54:00] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[01:54:00] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[01:54:00] [PASSED] drm_test_check_broadcast_rgb_value
[01:54:00] [PASSED] drm_test_check_bpc_8_value
[01:54:00] [PASSED] drm_test_check_bpc_10_value
[01:54:00] [PASSED] drm_test_check_bpc_12_value
[01:54:00] [PASSED] drm_test_check_format_value
[01:54:00] [PASSED] drm_test_check_tmds_char_value
[01:54:00] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[01:54:00] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) =
[01:54:00] [PASSED] drm_test_check_mode_valid
[01:54:00] [PASSED] drm_test_check_mode_valid_reject
[01:54:00] [PASSED] drm_test_check_mode_valid_reject_rate
[01:54:00] [PASSED] drm_test_check_mode_valid_reject_max_clock
[01:54:00] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[01:54:00] ================= drm_managed (2 subtests) =================
[01:54:00] [PASSED] drm_test_managed_release_action
[01:54:00] [PASSED] drm_test_managed_run_action
[01:54:00] =================== [PASSED] drm_managed ===================
[01:54:00] =================== drm_mm (6 subtests) ====================
[01:54:00] [PASSED] drm_test_mm_init
[01:54:00] [PASSED] drm_test_mm_debug
[01:54:00] [PASSED] drm_test_mm_align32
[01:54:00] [PASSED] drm_test_mm_align64
[01:54:00] [PASSED] drm_test_mm_lowest
[01:54:00] [PASSED] drm_test_mm_highest
[01:54:00] ===================== [PASSED] drm_mm ======================
[01:54:00] ============= drm_modes_analog_tv (5 subtests) =============
[01:54:00] [PASSED] drm_test_modes_analog_tv_mono_576i
[01:54:00] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[01:54:00] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[01:54:00] [PASSED] drm_test_modes_analog_tv_pal_576i
[01:54:00] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[01:54:00] =============== [PASSED] drm_modes_analog_tv ===============
[01:54:00] ============== drm_plane_helper (2 subtests) ===============
[01:54:00] =============== drm_test_check_plane_state  ================
[01:54:00] [PASSED] clipping_simple
[01:54:00] [PASSED] clipping_rotate_reflect
[01:54:00] [PASSED] positioning_simple
[01:54:00] [PASSED] upscaling
[01:54:00] [PASSED] downscaling
[01:54:00] [PASSED] rounding1
[01:54:00] [PASSED] rounding2
[01:54:00] [PASSED] rounding3
[01:54:00] [PASSED] rounding4
[01:54:00] =========== [PASSED] drm_test_check_plane_state ============
[01:54:00] =========== drm_test_check_invalid_plane_state  ============
[01:54:00] [PASSED] positioning_invalid
[01:54:00] [PASSED] upscaling_invalid
[01:54:00] [PASSED] downscaling_invalid
[01:54:00] ======= [PASSED] drm_test_check_invalid_plane_state ========
[01:54:00] ================ [PASSED] drm_plane_helper =================
[01:54:00] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[01:54:00] ====== drm_test_connector_helper_tv_get_modes_check  =======
[01:54:00] [PASSED] None
[01:54:00] [PASSED] PAL
[01:54:00] [PASSED] NTSC
[01:54:00] [PASSED] Both, NTSC Default
[01:54:00] [PASSED] Both, PAL Default
[01:54:00] [PASSED] Both, NTSC Default, with PAL on command-line
[01:54:00] [PASSED] Both, PAL Default, with NTSC on command-line
[01:54:00] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[01:54:00] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[01:54:00] ================== drm_rect (9 subtests) ===================
[01:54:00] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[01:54:00] [PASSED] drm_test_rect_clip_scaled_not_clipped
[01:54:00] [PASSED] drm_test_rect_clip_scaled_clipped
[01:54:00] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[01:54:00] ================= drm_test_rect_intersect  =================
[01:54:00] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[01:54:00] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[01:54:00] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[01:54:00] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[01:54:00] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[01:54:00] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[01:54:00] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[01:54:00] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[01:54:00] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[01:54:00] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[01:54:00] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[01:54:00] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[01:54:00] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[01:54:00] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[01:54:00] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[01:54:00] ============= [PASSED] drm_test_rect_intersect =============
[01:54:00] ================ drm_test_rect_calc_hscale  ================
[01:54:00] [PASSED] normal use
[01:54:00] [PASSED] out of max range
[01:54:00] [PASSED] out of min range
[01:54:00] [PASSED] zero dst
[01:54:00] [PASSED] negative src
[01:54:00] [PASSED] negative dst
[01:54:00] ============ [PASSED] drm_test_rect_calc_hscale ============
[01:54:00] ================ drm_test_rect_calc_vscale  ================
[01:54:00] [PASSED] normal use
stty: 'standard input': Inappropriate ioctl for device
[01:54:00] [PASSED] out of max range
[01:54:00] [PASSED] out of min range
[01:54:00] [PASSED] zero dst
[01:54:00] [PASSED] negative src
[01:54:00] [PASSED] negative dst
[01:54:00] ============ [PASSED] drm_test_rect_calc_vscale ============
[01:54:00] ================== drm_test_rect_rotate  ===================
[01:54:00] [PASSED] reflect-x
[01:54:00] [PASSED] reflect-y
[01:54:00] [PASSED] rotate-0
[01:54:00] [PASSED] rotate-90
[01:54:00] [PASSED] rotate-180
[01:54:00] [PASSED] rotate-270
[01:54:00] ============== [PASSED] drm_test_rect_rotate ===============
[01:54:00] ================ drm_test_rect_rotate_inv  =================
[01:54:00] [PASSED] reflect-x
[01:54:00] [PASSED] reflect-y
[01:54:00] [PASSED] rotate-0
[01:54:00] [PASSED] rotate-90
[01:54:00] [PASSED] rotate-180
[01:54:00] [PASSED] rotate-270
[01:54:00] ============ [PASSED] drm_test_rect_rotate_inv =============
[01:54:00] ==================== [PASSED] drm_rect =====================
[01:54:00] ============ drm_sysfb_modeset_test (1 subtest) ============
[01:54:00] ============ drm_test_sysfb_build_fourcc_list  =============
[01:54:00] [PASSED] no native formats
[01:54:00] [PASSED] XRGB8888 as native format
[01:54:00] [PASSED] remove duplicates
[01:54:00] [PASSED] convert alpha formats
[01:54:00] [PASSED] random formats
[01:54:00] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[01:54:00] ============= [PASSED] drm_sysfb_modeset_test ==============
[01:54:00] ============================================================
[01:54:00] Testing complete. Ran 622 tests: passed: 622
[01:54:00] Elapsed time: 26.775s total, 1.726s configuring, 24.622s building, 0.424s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[01:54:00] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[01:54:02] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[01:54:11] Starting KUnit Kernel (1/1)...
[01:54:11] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[01:54:11] ================= ttm_device (5 subtests) ==================
[01:54:11] [PASSED] ttm_device_init_basic
[01:54:11] [PASSED] ttm_device_init_multiple
[01:54:11] [PASSED] ttm_device_fini_basic
[01:54:11] [PASSED] ttm_device_init_no_vma_man
[01:54:11] ================== ttm_device_init_pools  ==================
[01:54:11] [PASSED] No DMA allocations, no DMA32 required
[01:54:11] [PASSED] DMA allocations, DMA32 required
[01:54:11] [PASSED] No DMA allocations, DMA32 required
[01:54:11] [PASSED] DMA allocations, no DMA32 required
[01:54:11] ============== [PASSED] ttm_device_init_pools ==============
[01:54:11] =================== [PASSED] ttm_device ====================
[01:54:11] ================== ttm_pool (8 subtests) ===================
[01:54:11] ================== ttm_pool_alloc_basic  ===================
[01:54:11] [PASSED] One page
[01:54:11] [PASSED] More than one page
[01:54:11] [PASSED] Above the allocation limit
[01:54:11] [PASSED] One page, with coherent DMA mappings enabled
[01:54:11] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[01:54:11] ============== [PASSED] ttm_pool_alloc_basic ===============
[01:54:11] ============== ttm_pool_alloc_basic_dma_addr  ==============
[01:54:11] [PASSED] One page
[01:54:11] [PASSED] More than one page
[01:54:11] [PASSED] Above the allocation limit
[01:54:11] [PASSED] One page, with coherent DMA mappings enabled
[01:54:11] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[01:54:11] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[01:54:11] [PASSED] ttm_pool_alloc_order_caching_match
[01:54:11] [PASSED] ttm_pool_alloc_caching_mismatch
[01:54:11] [PASSED] ttm_pool_alloc_order_mismatch
[01:54:11] [PASSED] ttm_pool_free_dma_alloc
[01:54:11] [PASSED] ttm_pool_free_no_dma_alloc
[01:54:11] [PASSED] ttm_pool_fini_basic
[01:54:11] ==================== [PASSED] ttm_pool =====================
[01:54:11] ================ ttm_resource (8 subtests) =================
[01:54:11] ================= ttm_resource_init_basic  =================
[01:54:11] [PASSED] Init resource in TTM_PL_SYSTEM
[01:54:11] [PASSED] Init resource in TTM_PL_VRAM
[01:54:11] [PASSED] Init resource in a private placement
[01:54:11] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[01:54:11] ============= [PASSED] ttm_resource_init_basic =============
[01:54:11] [PASSED] ttm_resource_init_pinned
[01:54:11] [PASSED] ttm_resource_fini_basic
[01:54:11] [PASSED] ttm_resource_manager_init_basic
[01:54:11] [PASSED] ttm_resource_manager_usage_basic
[01:54:11] [PASSED] ttm_resource_manager_set_used_basic
[01:54:11] [PASSED] ttm_sys_man_alloc_basic
[01:54:11] [PASSED] ttm_sys_man_free_basic
[01:54:11] ================== [PASSED] ttm_resource ===================
[01:54:11] =================== ttm_tt (15 subtests) ===================
[01:54:11] ==================== ttm_tt_init_basic  ====================
[01:54:11] [PASSED] Page-aligned size
[01:54:11] [PASSED] Extra pages requested
[01:54:11] ================ [PASSED] ttm_tt_init_basic ================
[01:54:11] [PASSED] ttm_tt_init_misaligned
[01:54:11] [PASSED] ttm_tt_fini_basic
[01:54:11] [PASSED] ttm_tt_fini_sg
[01:54:11] [PASSED] ttm_tt_fini_shmem
[01:54:11] [PASSED] ttm_tt_create_basic
[01:54:11] [PASSED] ttm_tt_create_invalid_bo_type
[01:54:11] [PASSED] ttm_tt_create_ttm_exists
[01:54:11] [PASSED] ttm_tt_create_failed
[01:54:11] [PASSED] ttm_tt_destroy_basic
[01:54:11] [PASSED] ttm_tt_populate_null_ttm
[01:54:11] [PASSED] ttm_tt_populate_populated_ttm
[01:54:11] [PASSED] ttm_tt_unpopulate_basic
[01:54:11] [PASSED] ttm_tt_unpopulate_empty_ttm
[01:54:11] [PASSED] ttm_tt_swapin_basic
[01:54:11] ===================== [PASSED] ttm_tt ======================
[01:54:11] =================== ttm_bo (14 subtests) ===================
[01:54:11] =========== ttm_bo_reserve_optimistic_no_ticket  ===========
[01:54:11] [PASSED] Cannot be interrupted and sleeps
[01:54:11] [PASSED] Cannot be interrupted, locks straight away
[01:54:11] [PASSED] Can be interrupted, sleeps
[01:54:11] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[01:54:11] [PASSED] ttm_bo_reserve_locked_no_sleep
[01:54:11] [PASSED] ttm_bo_reserve_no_wait_ticket
[01:54:11] [PASSED] ttm_bo_reserve_double_resv
[01:54:11] [PASSED] ttm_bo_reserve_interrupted
[01:54:11] [PASSED] ttm_bo_reserve_deadlock
[01:54:11] [PASSED] ttm_bo_unreserve_basic
[01:54:11] [PASSED] ttm_bo_unreserve_pinned
[01:54:11] [PASSED] ttm_bo_unreserve_bulk
[01:54:11] [PASSED] ttm_bo_fini_basic
[01:54:11] [PASSED] ttm_bo_fini_shared_resv
[01:54:11] [PASSED] ttm_bo_pin_basic
[01:54:11] [PASSED] ttm_bo_pin_unpin_resource
[01:54:11] [PASSED] ttm_bo_multiple_pin_one_unpin
[01:54:11] ===================== [PASSED] ttm_bo ======================
[01:54:11] ============== ttm_bo_validate (21 subtests) ===============
[01:54:11] ============== ttm_bo_init_reserved_sys_man  ===============
[01:54:11] [PASSED] Buffer object for userspace
[01:54:11] [PASSED] Kernel buffer object
[01:54:11] [PASSED] Shared buffer object
[01:54:11] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[01:54:11] ============== ttm_bo_init_reserved_mock_man  ==============
[01:54:11] [PASSED] Buffer object for userspace
[01:54:11] [PASSED] Kernel buffer object
[01:54:11] [PASSED] Shared buffer object
[01:54:11] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[01:54:11] [PASSED] ttm_bo_init_reserved_resv
[01:54:11] ================== ttm_bo_validate_basic  ==================
[01:54:11] [PASSED] Buffer object for userspace
[01:54:11] [PASSED] Kernel buffer object
[01:54:11] [PASSED] Shared buffer object
[01:54:11] ============== [PASSED] ttm_bo_validate_basic ==============
[01:54:11] [PASSED] ttm_bo_validate_invalid_placement
[01:54:11] ============= ttm_bo_validate_same_placement  ==============
[01:54:11] [PASSED] System manager
[01:54:11] [PASSED] VRAM manager
[01:54:11] ========= [PASSED] ttm_bo_validate_same_placement ==========
[01:54:11] [PASSED] ttm_bo_validate_failed_alloc
[01:54:11] [PASSED] ttm_bo_validate_pinned
[01:54:11] [PASSED] ttm_bo_validate_busy_placement
[01:54:11] ================ ttm_bo_validate_multihop  =================
[01:54:11] [PASSED] Buffer object for userspace
[01:54:11] [PASSED] Kernel buffer object
[01:54:11] [PASSED] Shared buffer object
[01:54:11] ============ [PASSED] ttm_bo_validate_multihop =============
[01:54:11] ========== ttm_bo_validate_no_placement_signaled  ==========
[01:54:11] [PASSED] Buffer object in system domain, no page vector
[01:54:11] [PASSED] Buffer object in system domain with an existing page vector
[01:54:11] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[01:54:11] ======== ttm_bo_validate_no_placement_not_signaled  ========
[01:54:11] [PASSED] Buffer object for userspace
[01:54:11] [PASSED] Kernel buffer object
[01:54:11] [PASSED] Shared buffer object
[01:54:11] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[01:54:11] [PASSED] ttm_bo_validate_move_fence_signaled
[01:54:12] ========= ttm_bo_validate_move_fence_not_signaled  =========
[01:54:12] [PASSED] Waits for GPU
[01:54:12] [PASSED] Tries to lock straight away
[01:54:12] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[01:54:12] [PASSED] ttm_bo_validate_happy_evict
[01:54:12] [PASSED] ttm_bo_validate_all_pinned_evict
[01:54:12] [PASSED] ttm_bo_validate_allowed_only_evict
[01:54:12] [PASSED] ttm_bo_validate_deleted_evict
[01:54:12] [PASSED] ttm_bo_validate_busy_domain_evict
[01:54:12] [PASSED] ttm_bo_validate_evict_gutting
[01:54:12] [PASSED] ttm_bo_validate_recrusive_evict
stty: 'standard input': Inappropriate ioctl for device
[01:54:12] ================= [PASSED] ttm_bo_validate =================
[01:54:12] ============================================================
[01:54:12] Testing complete. Ran 101 tests: passed: 101
[01:54:12] Elapsed time: 11.234s total, 1.714s configuring, 9.304s building, 0.184s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



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

* ✗ CI.checksparse: warning for drm/i915/display: Add initial support for Xe3p_LPD (rev4)
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (13 preceding siblings ...)
  2025-11-08  1:54 ` ✓ CI.KUnit: success " Patchwork
@ 2025-11-08  2:09 ` Patchwork
  2025-11-08  2:31 ` ✗ Xe.CI.BAT: failure " Patchwork
  2025-11-09  8:10 ` ✗ Xe.CI.Full: " Patchwork
  16 siblings, 0 replies; 48+ messages in thread
From: Patchwork @ 2025-11-08  2:09 UTC (permalink / raw)
  To: Gustavo Sousa; +Cc: intel-xe

== Series Details ==

Series: drm/i915/display: Add initial support for Xe3p_LPD (rev4)
URL   : https://patchwork.freedesktop.org/series/155951/
State : warning

== Summary ==

+ trap cleanup EXIT
+ KERNEL=/kernel
+ MT=/root/linux/maintainer-tools
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools /root/linux/maintainer-tools
Cloning into '/root/linux/maintainer-tools'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ make -C /root/linux/maintainer-tools
make: Entering directory '/root/linux/maintainer-tools'
cc -O2 -g -Wextra -o remap-log remap-log.c
make: Leaving directory '/root/linux/maintainer-tools'
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ /root/linux/maintainer-tools/dim sparse --fast 2bc418aa7efaae562e49d84e8b28f799cf624745
Sparse version: 0.6.4 (Ubuntu: 0.6.4-4ubuntu3)
Fast mode used, each commit won't be checked separately.
-
+drivers/gpu/drm/i915/display/intel_alpm.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_casf.c:147:21: error: too long token expansion
+drivers/gpu/drm/i915/display/intel_cdclk.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_ddi.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2074:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2087:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2087:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_display_types.h:2087:24: warning: unreplaced symbol '<noident>'
+drivers/gpu/drm/i915/display/intel_hdcp.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_hotplug.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_lt_phy.c:1603:35: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/i915/display/intel_pps.c: note: in included file:
+drivers/gpu/drm/i915/display/intel_psr.c: note: in included file:
+drivers/gpu/drm/i915/intel_uncore.c:1930:1: warning: context imbalance in 'fwtable_read8' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:1931:1: warning: context imbalance in 'fwtable_read16' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:1932:1: warning: context imbalance in 'fwtable_read32' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:1933:1: warning: context imbalance in 'fwtable_read64' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:1998:1: warning: context imbalance in 'gen6_write8' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:1999:1: warning: context imbalance in 'gen6_write16' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:2000:1: warning: context imbalance in 'gen6_write32' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:2020:1: warning: context imbalance in 'fwtable_write8' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:2021:1: warning: context imbalance in 'fwtable_write16' - unexpected unlock
+drivers/gpu/drm/i915/intel_uncore.c:2022:1: warning: context imbalance in 'fwtable_write32' - unexpected unlock

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



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

* ✗ Xe.CI.BAT: failure for drm/i915/display: Add initial support for Xe3p_LPD (rev4)
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (14 preceding siblings ...)
  2025-11-08  2:09 ` ✗ CI.checksparse: warning " Patchwork
@ 2025-11-08  2:31 ` Patchwork
  2025-11-09  8:10 ` ✗ Xe.CI.Full: " Patchwork
  16 siblings, 0 replies; 48+ messages in thread
From: Patchwork @ 2025-11-08  2:31 UTC (permalink / raw)
  To: Gustavo Sousa; +Cc: intel-xe

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

== Series Details ==

Series: drm/i915/display: Add initial support for Xe3p_LPD (rev4)
URL   : https://patchwork.freedesktop.org/series/155951/
State : failure

== Summary ==

CI Bug Log - changes from xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745_BAT -> xe-pw-155951v4_BAT
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-155951v4_BAT absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-155951v4_BAT, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (13 -> 13)
------------------------------

  No changes in participating hosts

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

  Here are the unknown changes that may have been introduced in xe-pw-155951v4_BAT:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_module_load@load:
    - bat-bmg-2:          [PASS][1] -> [ABORT][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/bat-bmg-2/igt@xe_module_load@load.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/bat-bmg-2/igt@xe_module_load@load.html
    - bat-bmg-3:          [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/bat-bmg-3/igt@xe_module_load@load.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/bat-bmg-3/igt@xe_module_load@load.html
    - bat-bmg-1:          [PASS][5] -> [ABORT][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/bat-bmg-1/igt@xe_module_load@load.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/bat-bmg-1/igt@xe_module_load@load.html

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

  Here are the changes found in xe-pw-155951v4_BAT that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@kms_flip@basic-flip-vs-modeset@d-edp1:
    - bat-adlp-7:         [DMESG-WARN][7] ([Intel XE#4543]) -> [PASS][8] +1 other test pass
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/bat-adlp-7/igt@kms_flip@basic-flip-vs-modeset@d-edp1.html
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/bat-adlp-7/igt@kms_flip@basic-flip-vs-modeset@d-edp1.html

  
  [Intel XE#4543]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4543


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

  * Linux: xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745 -> xe-pw-155951v4

  IGT_8614: 8614
  xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745: 2bc418aa7efaae562e49d84e8b28f799cf624745
  xe-pw-155951v4: 155951v4

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/index.html

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

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

* ✗ Xe.CI.Full: failure for drm/i915/display: Add initial support for Xe3p_LPD (rev4)
  2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
                   ` (15 preceding siblings ...)
  2025-11-08  2:31 ` ✗ Xe.CI.BAT: failure " Patchwork
@ 2025-11-09  8:10 ` Patchwork
  16 siblings, 0 replies; 48+ messages in thread
From: Patchwork @ 2025-11-09  8:10 UTC (permalink / raw)
  To: Gustavo Sousa; +Cc: intel-xe

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

== Series Details ==

Series: drm/i915/display: Add initial support for Xe3p_LPD (rev4)
URL   : https://patchwork.freedesktop.org/series/155951/
State : failure

== Summary ==

CI Bug Log - changes from xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745_FULL -> xe-pw-155951v4_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-155951v4_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-155951v4_FULL, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (4 -> 4)
------------------------------

  No changes in participating hosts

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

  Here are the unknown changes that may have been introduced in xe-pw-155951v4_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_module_load@load:
    - shard-bmg:          ([PASS][1], [PASS][2], [PASS][3], [PASS][4], [PASS][5], [PASS][6], [PASS][7], [PASS][8], [PASS][9], [PASS][10], [PASS][11], [PASS][12], [PASS][13], [PASS][14], [PASS][15], [PASS][16], [PASS][17], [PASS][18], [PASS][19]) -> ([DMESG-WARN][20], [DMESG-WARN][21], [DMESG-WARN][22], [DMESG-WARN][23], [DMESG-WARN][24], [DMESG-WARN][25], [DMESG-WARN][26], [DMESG-WARN][27], [DMESG-WARN][28], [DMESG-WARN][29], [DMESG-WARN][30], [DMESG-WARN][31], [DMESG-WARN][32], [DMESG-WARN][33], [DMESG-WARN][34], [DMESG-WARN][35], [DMESG-WARN][36], [DMESG-WARN][37], [DMESG-WARN][38], [DMESG-WARN][39], [DMESG-WARN][40], [DMESG-WARN][41], [DMESG-WARN][42])
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-6/igt@xe_module_load@load.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-2/igt@xe_module_load@load.html
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-6/igt@xe_module_load@load.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-4/igt@xe_module_load@load.html
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-4/igt@xe_module_load@load.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-4/igt@xe_module_load@load.html
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-8/igt@xe_module_load@load.html
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-8/igt@xe_module_load@load.html
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-1/igt@xe_module_load@load.html
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-1/igt@xe_module_load@load.html
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-1/igt@xe_module_load@load.html
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-7/igt@xe_module_load@load.html
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-7/igt@xe_module_load@load.html
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-2/igt@xe_module_load@load.html
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-5/igt@xe_module_load@load.html
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-1/igt@xe_module_load@load.html
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-5/igt@xe_module_load@load.html
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-6/igt@xe_module_load@load.html
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-bmg-8/igt@xe_module_load@load.html
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-4/igt@xe_module_load@load.html
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-4/igt@xe_module_load@load.html
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-4/igt@xe_module_load@load.html
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-6/igt@xe_module_load@load.html
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-6/igt@xe_module_load@load.html
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-6/igt@xe_module_load@load.html
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-6/igt@xe_module_load@load.html
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-5/igt@xe_module_load@load.html
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-8/igt@xe_module_load@load.html
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-8/igt@xe_module_load@load.html
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-7/igt@xe_module_load@load.html
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-7/igt@xe_module_load@load.html
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-7/igt@xe_module_load@load.html
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-7/igt@xe_module_load@load.html
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-8/igt@xe_module_load@load.html
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-1/igt@xe_module_load@load.html
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-1/igt@xe_module_load@load.html
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-1/igt@xe_module_load@load.html
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-1/igt@xe_module_load@load.html
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-2/igt@xe_module_load@load.html
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-2/igt@xe_module_load@load.html
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-2/igt@xe_module_load@load.html
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-bmg-5/igt@xe_module_load@load.html

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

  Here are the changes found in xe-pw-155951v4_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_async_flips@async-flip-dpms@pipe-a-hdmi-a-1:
    - shard-adlp:         [PASS][43] -> [DMESG-WARN][44] ([Intel XE#2953] / [Intel XE#4173]) +2 other tests dmesg-warn
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-adlp-1/igt@kms_async_flips@async-flip-dpms@pipe-a-hdmi-a-1.html
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-adlp-1/igt@kms_async_flips@async-flip-dpms@pipe-a-hdmi-a-1.html

  * igt@kms_big_fb@x-tiled-16bpp-rotate-270:
    - shard-dg2-set2:     NOTRUN -> [SKIP][45] ([Intel XE#316]) +2 other tests skip
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_big_fb@x-tiled-16bpp-rotate-270.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip:
    - shard-adlp:         [PASS][46] -> [DMESG-FAIL][47] ([Intel XE#4543]) +1 other test dmesg-fail
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-adlp-6/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip.html
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-adlp-1/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@yf-tiled-addfb:
    - shard-dg2-set2:     NOTRUN -> [SKIP][48] ([Intel XE#619])
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_big_fb@yf-tiled-addfb.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip:
    - shard-dg2-set2:     NOTRUN -> [SKIP][49] ([Intel XE#1124]) +7 other tests skip
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180-hflip-async-flip.html

  * igt@kms_bw@linear-tiling-1-displays-2560x1440p:
    - shard-dg2-set2:     NOTRUN -> [SKIP][50] ([Intel XE#367]) +1 other test skip
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_bw@linear-tiling-1-displays-2560x1440p.html

  * igt@kms_ccs@bad-pixel-format-yf-tiled-ccs:
    - shard-dg2-set2:     NOTRUN -> [SKIP][51] ([Intel XE#455] / [Intel XE#787]) +27 other tests skip
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@kms_ccs@bad-pixel-format-yf-tiled-ccs.html

  * igt@kms_ccs@bad-rotation-90-4-tiled-lnl-ccs:
    - shard-dg2-set2:     NOTRUN -> [SKIP][52] ([Intel XE#2907])
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_ccs@bad-rotation-90-4-tiled-lnl-ccs.html

  * igt@kms_ccs@random-ccs-data-yf-tiled-ccs@pipe-b-dp-4:
    - shard-dg2-set2:     NOTRUN -> [SKIP][53] ([Intel XE#787]) +90 other tests skip
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@kms_ccs@random-ccs-data-yf-tiled-ccs@pipe-b-dp-4.html

  * igt@kms_chamelium_color@ctm-blue-to-red:
    - shard-dg2-set2:     NOTRUN -> [SKIP][54] ([Intel XE#306])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_chamelium_color@ctm-blue-to-red.html

  * igt@kms_chamelium_hpd@vga-hpd-without-ddc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][55] ([Intel XE#373]) +9 other tests skip
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_chamelium_hpd@vga-hpd-without-ddc.html

  * igt@kms_chamelium_sharpness_filter@filter-basic:
    - shard-dg2-set2:     NOTRUN -> [SKIP][56] ([Intel XE#6507])
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_chamelium_sharpness_filter@filter-basic.html

  * igt@kms_content_protection@atomic:
    - shard-dg2-set2:     NOTRUN -> [FAIL][57] ([Intel XE#1178]) +1 other test fail
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@dp-mst-type-0:
    - shard-dg2-set2:     NOTRUN -> [SKIP][58] ([Intel XE#307])
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_content_protection@dp-mst-type-0.html

  * igt@kms_cursor_crc@cursor-sliding-512x512:
    - shard-dg2-set2:     NOTRUN -> [SKIP][59] ([Intel XE#308]) +2 other tests skip
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_cursor_crc@cursor-sliding-512x512.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions:
    - shard-dg2-set2:     NOTRUN -> [SKIP][60] ([Intel XE#323])
   [60]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions.html

  * igt@kms_dp_link_training@non-uhbr-mst:
    - shard-dg2-set2:     NOTRUN -> [SKIP][61] ([Intel XE#4354])
   [61]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_dp_link_training@non-uhbr-mst.html

  * igt@kms_dp_linktrain_fallback@dsc-fallback:
    - shard-dg2-set2:     NOTRUN -> [SKIP][62] ([Intel XE#4331])
   [62]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@kms_dp_linktrain_fallback@dsc-fallback.html

  * igt@kms_dsc@dsc-with-output-formats-with-bpc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][63] ([Intel XE#455]) +17 other tests skip
   [63]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@kms_dsc@dsc-with-output-formats-with-bpc.html

  * igt@kms_feature_discovery@psr2:
    - shard-dg2-set2:     NOTRUN -> [SKIP][64] ([Intel XE#1135])
   [64]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_feature_discovery@psr2.html

  * igt@kms_flip@flip-vs-expired-vblank@c-edp1:
    - shard-lnl:          [PASS][65] -> [FAIL][66] ([Intel XE#301] / [Intel XE#3149]) +1 other test fail
   [65]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-1/igt@kms_flip@flip-vs-expired-vblank@c-edp1.html
   [66]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-7/igt@kms_flip@flip-vs-expired-vblank@c-edp1.html

  * igt@kms_flip@plain-flip-ts-check@b-hdmi-a1:
    - shard-adlp:         [PASS][67] -> [DMESG-WARN][68] ([Intel XE#4543])
   [67]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-adlp-8/igt@kms_flip@plain-flip-ts-check@b-hdmi-a1.html
   [68]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-adlp-4/igt@kms_flip@plain-flip-ts-check@b-hdmi-a1.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-1p-offscreen-pri-indfb-draw-mmap-wc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][69] ([Intel XE#6312]) +8 other tests skip
   [69]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_frontbuffer_tracking@fbcdrrs-1p-offscreen-pri-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-1p-rte:
    - shard-dg2-set2:     NOTRUN -> [SKIP][70] ([Intel XE#651]) +28 other tests skip
   [70]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_frontbuffer_tracking@fbcdrrs-1p-rte.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-tiling-y:
    - shard-dg2-set2:     NOTRUN -> [SKIP][71] ([Intel XE#658])
   [71]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_frontbuffer_tracking@fbcdrrs-tiling-y.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][72] ([Intel XE#653]) +26 other tests skip
   [72]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-indfb-draw-blt.html

  * igt@kms_hdr@invalid-hdr:
    - shard-dg2-set2:     [PASS][73] -> [SKIP][74] ([Intel XE#455])
   [73]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-463/igt@kms_hdr@invalid-hdr.html
   [74]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-436/igt@kms_hdr@invalid-hdr.html

  * igt@kms_joiner@basic-ultra-joiner:
    - shard-dg2-set2:     NOTRUN -> [SKIP][75] ([Intel XE#2927])
   [75]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_joiner@basic-ultra-joiner.html

  * igt@kms_pipe_stress@stress-xrgb8888-yftiled:
    - shard-dg2-set2:     NOTRUN -> [SKIP][76] ([Intel XE#5624])
   [76]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_pipe_stress@stress-xrgb8888-yftiled.html

  * igt@kms_pm_backlight@fade-with-suspend:
    - shard-dg2-set2:     NOTRUN -> [SKIP][77] ([Intel XE#870]) +1 other test skip
   [77]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_pm_backlight@fade-with-suspend.html

  * igt@kms_psr2_sf@fbc-pr-plane-move-sf-dmg-area:
    - shard-dg2-set2:     NOTRUN -> [SKIP][78] ([Intel XE#1406] / [Intel XE#1489]) +9 other tests skip
   [78]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_psr2_sf@fbc-pr-plane-move-sf-dmg-area.html

  * igt@kms_psr@fbc-pr-dpms:
    - shard-dg2-set2:     NOTRUN -> [SKIP][79] ([Intel XE#1406] / [Intel XE#2850] / [Intel XE#929]) +17 other tests skip
   [79]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-432/igt@kms_psr@fbc-pr-dpms.html

  * igt@kms_rotation_crc@bad-tiling:
    - shard-dg2-set2:     NOTRUN -> [SKIP][80] ([Intel XE#3414]) +2 other tests skip
   [80]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_rotation_crc@bad-tiling.html

  * igt@kms_tiled_display@basic-test-pattern:
    - shard-dg2-set2:     NOTRUN -> [FAIL][81] ([Intel XE#1729])
   [81]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_tiled_display@basic-test-pattern.html

  * igt@kms_tv_load_detect@load-detect:
    - shard-dg2-set2:     NOTRUN -> [SKIP][82] ([Intel XE#330])
   [82]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@kms_tv_load_detect@load-detect.html

  * igt@kms_vrr@cmrr:
    - shard-dg2-set2:     NOTRUN -> [SKIP][83] ([Intel XE#2168])
   [83]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_vrr@cmrr.html

  * igt@xe_copy_basic@mem-set-linear-0x369:
    - shard-dg2-set2:     NOTRUN -> [SKIP][84] ([Intel XE#1126])
   [84]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_copy_basic@mem-set-linear-0x369.html

  * igt@xe_copy_basic@mem-set-linear-0x8fffe:
    - shard-dg2-set2:     NOTRUN -> [SKIP][85] ([Intel XE#5503])
   [85]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_copy_basic@mem-set-linear-0x8fffe.html

  * igt@xe_eu_stall@invalid-event-report-count:
    - shard-dg2-set2:     NOTRUN -> [SKIP][86] ([Intel XE#5626])
   [86]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_eu_stall@invalid-event-report-count.html

  * igt@xe_eudebug@vm-bind-clear-faultable:
    - shard-dg2-set2:     NOTRUN -> [SKIP][87] ([Intel XE#4837]) +17 other tests skip
   [87]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-463/igt@xe_eudebug@vm-bind-clear-faultable.html

  * igt@xe_exec_fault_mode@once-invalid-userptr-fault:
    - shard-dg2-set2:     NOTRUN -> [SKIP][88] ([Intel XE#288]) +28 other tests skip
   [88]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_exec_fault_mode@once-invalid-userptr-fault.html

  * igt@xe_exec_mix_modes@exec-spinner-interrupted-dma-fence:
    - shard-dg2-set2:     NOTRUN -> [SKIP][89] ([Intel XE#2360]) +1 other test skip
   [89]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_exec_mix_modes@exec-spinner-interrupted-dma-fence.html

  * igt@xe_exec_system_allocator@threads-many-large-mmap-shared-remap-dontunmap-eocheck:
    - shard-dg2-set2:     NOTRUN -> [SKIP][90] ([Intel XE#4915]) +344 other tests skip
   [90]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_exec_system_allocator@threads-many-large-mmap-shared-remap-dontunmap-eocheck.html

  * igt@xe_live_ktest@xe_migrate@xe_validate_ccs_kunit:
    - shard-dg2-set2:     NOTRUN -> [SKIP][91] ([Intel XE#2229])
   [91]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_live_ktest@xe_migrate@xe_validate_ccs_kunit.html

  * igt@xe_module_load@force-load:
    - shard-dg2-set2:     NOTRUN -> [SKIP][92] ([Intel XE#378])
   [92]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_module_load@force-load.html

  * igt@xe_oa@syncs-userptr-wait-cfg:
    - shard-dg2-set2:     NOTRUN -> [SKIP][93] ([Intel XE#3573]) +6 other tests skip
   [93]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_oa@syncs-userptr-wait-cfg.html

  * igt@xe_pat@display-vs-wb-transient:
    - shard-dg2-set2:     NOTRUN -> [SKIP][94] ([Intel XE#1337])
   [94]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@xe_pat@display-vs-wb-transient.html

  * igt@xe_pat@pat-index-xelpg:
    - shard-dg2-set2:     NOTRUN -> [SKIP][95] ([Intel XE#979])
   [95]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_pat@pat-index-xelpg.html

  * igt@xe_pm@s2idle-d3cold-basic-exec:
    - shard-dg2-set2:     NOTRUN -> [SKIP][96] ([Intel XE#2284] / [Intel XE#366])
   [96]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@xe_pm@s2idle-d3cold-basic-exec.html

  * igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_decode0:
    - shard-lnl:          [PASS][97] -> [FAIL][98] ([Intel XE#6251]) +2 other tests fail
   [97]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-2/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_decode0.html
   [98]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-2/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_decode0.html

  * igt@xe_pmu@fn-engine-activity-load:
    - shard-dg2-set2:     NOTRUN -> [SKIP][99] ([Intel XE#4650])
   [99]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@xe_pmu@fn-engine-activity-load.html

  * igt@xe_pmu@gt-c6-idle:
    - shard-dg2-set2:     NOTRUN -> [FAIL][100] ([Intel XE#6366])
   [100]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_pmu@gt-c6-idle.html

  * igt@xe_pmu@gt-frequency:
    - shard-dg2-set2:     [PASS][101] -> [FAIL][102] ([Intel XE#4819]) +1 other test fail
   [101]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-464/igt@xe_pmu@gt-frequency.html
   [102]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-434/igt@xe_pmu@gt-frequency.html

  * igt@xe_pxp@pxp-stale-bo-bind-post-rpm:
    - shard-dg2-set2:     NOTRUN -> [SKIP][103] ([Intel XE#4733]) +2 other tests skip
   [103]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_pxp@pxp-stale-bo-bind-post-rpm.html

  * igt@xe_query@multigpu-query-cs-cycles:
    - shard-dg2-set2:     NOTRUN -> [SKIP][104] ([Intel XE#944]) +1 other test skip
   [104]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@xe_query@multigpu-query-cs-cycles.html

  * igt@xe_render_copy@render-stress-2-copies:
    - shard-dg2-set2:     NOTRUN -> [SKIP][105] ([Intel XE#4814])
   [105]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_render_copy@render-stress-2-copies.html

  * igt@xe_sriov_flr@flr-each-isolation:
    - shard-dg2-set2:     NOTRUN -> [SKIP][106] ([Intel XE#3342])
   [106]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@xe_sriov_flr@flr-each-isolation.html

  * igt@xe_sriov_flr@flr-vfs-parallel:
    - shard-dg2-set2:     NOTRUN -> [SKIP][107] ([Intel XE#4273])
   [107]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_sriov_flr@flr-vfs-parallel.html

  * igt@xe_sriov_vram@vf-access-after-resize-down:
    - shard-dg2-set2:     NOTRUN -> [SKIP][108] ([Intel XE#6318])
   [108]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@xe_sriov_vram@vf-access-after-resize-down.html

  * igt@xe_survivability@runtime-survivability:
    - shard-dg2-set2:     NOTRUN -> [SKIP][109] ([Intel XE#6529])
   [109]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-464/igt@xe_survivability@runtime-survivability.html

  
#### Possible fixes ####

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-dp-4:
    - shard-dg2-set2:     [INCOMPLETE][110] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4212] / [Intel XE#4345] / [Intel XE#4522]) -> [PASS][111] +1 other test pass
   [110]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-464/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-dp-4.html
   [111]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-mc-ccs@pipe-b-dp-4.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs:
    - shard-dg2-set2:     [INCOMPLETE][112] ([Intel XE#2705] / [Intel XE#4212] / [Intel XE#4345]) -> [PASS][113]
   [112]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-433/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs.html
   [113]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-432/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc:
    - shard-dg2-set2:     [INCOMPLETE][114] ([Intel XE#1727] / [Intel XE#3113] / [Intel XE#4345]) -> [PASS][115]
   [114]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html
   [115]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-c-hdmi-a-6:
    - shard-dg2-set2:     [INCOMPLETE][116] ([Intel XE#1727] / [Intel XE#3113]) -> [PASS][117]
   [116]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-435/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-c-hdmi-a-6.html
   [117]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-466/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs-cc@pipe-c-hdmi-a-6.html

  * igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-c-dp-4:
    - shard-dg2-set2:     [INCOMPLETE][118] ([Intel XE#2705] / [Intel XE#4212]) -> [PASS][119]
   [118]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-433/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-c-dp-4.html
   [119]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-432/igt@kms_ccs@random-ccs-data-4-tiled-dg2-rc-ccs@pipe-c-dp-4.html

  * igt@kms_cursor_crc@cursor-suspend@pipe-a-hdmi-a-1:
    - shard-adlp:         [DMESG-WARN][120] ([Intel XE#2953] / [Intel XE#4173]) -> [PASS][121] +3 other tests pass
   [120]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-adlp-8/igt@kms_cursor_crc@cursor-suspend@pipe-a-hdmi-a-1.html
   [121]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-adlp-4/igt@kms_cursor_crc@cursor-suspend@pipe-a-hdmi-a-1.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible:
    - shard-dg2-set2:     [FAIL][122] ([Intel XE#301]) -> [PASS][123] +1 other test pass
   [122]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-436/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [123]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-463/igt@kms_flip@flip-vs-expired-vblank-interruptible.html

  * igt@kms_flip@flip-vs-expired-vblank@b-hdmi-a1:
    - shard-adlp:         [DMESG-WARN][124] ([Intel XE#4543]) -> [PASS][125]
   [124]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-adlp-8/igt@kms_flip@flip-vs-expired-vblank@b-hdmi-a1.html
   [125]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-adlp-8/igt@kms_flip@flip-vs-expired-vblank@b-hdmi-a1.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-rebind:
    - shard-dg2-set2:     [INCOMPLETE][126] ([Intel XE#4842]) -> [PASS][127]
   [126]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-466/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-rebind.html
   [127]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-bindexecqueue-rebind.html

  * igt@xe_exec_system_allocator@pat-index-madvise-pat-idx-uc-single-vma:
    - shard-lnl:          [FAIL][128] ([Intel XE#5625]) -> [PASS][129]
   [128]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-4/igt@xe_exec_system_allocator@pat-index-madvise-pat-idx-uc-single-vma.html
   [129]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-3/igt@xe_exec_system_allocator@pat-index-madvise-pat-idx-uc-single-vma.html

  * igt@xe_fault_injection@probe-fail-guc-xe_guc_mmio_send_recv:
    - shard-dg2-set2:     [DMESG-WARN][130] ([Intel XE#5893]) -> [PASS][131] +1 other test pass
   [130]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-466/igt@xe_fault_injection@probe-fail-guc-xe_guc_mmio_send_recv.html
   [131]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-433/igt@xe_fault_injection@probe-fail-guc-xe_guc_mmio_send_recv.html

  * igt@xe_pm@s4-multiple-execs:
    - shard-dg2-set2:     [ABORT][132] -> [PASS][133]
   [132]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-dg2-434/igt@xe_pm@s4-multiple-execs.html
   [133]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-dg2-463/igt@xe_pm@s4-multiple-execs.html

  * igt@xe_pmu@engine-activity-accuracy-50@engine-drm_xe_engine_class_video_decode0:
    - shard-lnl:          [FAIL][134] -> [PASS][135]
   [134]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-3/igt@xe_pmu@engine-activity-accuracy-50@engine-drm_xe_engine_class_video_decode0.html
   [135]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-8/igt@xe_pmu@engine-activity-accuracy-50@engine-drm_xe_engine_class_video_decode0.html

  * igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_enhance0:
    - shard-lnl:          [FAIL][136] ([Intel XE#6251]) -> [PASS][137] +1 other test pass
   [136]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-2/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_enhance0.html
   [137]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-2/igt@xe_pmu@engine-activity-accuracy-90@engine-drm_xe_engine_class_video_enhance0.html

  
#### Warnings ####

  * igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1:
    - shard-lnl:          [FAIL][138] ([Intel XE#5862]) -> [FAIL][139] ([Intel XE#5862] / [Intel XE#6554]) +1 other test fail
   [138]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745/shard-lnl-8/igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1.html
   [139]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/shard-lnl-5/igt@kms_vrr@seamless-rr-switch-virtual@pipe-a-edp-1.html

  
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1126]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1126
  [Intel XE#1135]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1135
  [Intel XE#1178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1178
  [Intel XE#1337]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1337
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1727]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1727
  [Intel XE#1729]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1729
  [Intel XE#2168]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2168
  [Intel XE#2229]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2229
  [Intel XE#2284]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2284
  [Intel XE#2360]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2360
  [Intel XE#2705]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2705
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#288]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/288
  [Intel XE#2907]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2907
  [Intel XE#2927]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2927
  [Intel XE#2953]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2953
  [Intel XE#301]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/301
  [Intel XE#306]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/306
  [Intel XE#307]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/307
  [Intel XE#308]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/308
  [Intel XE#3113]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3113
  [Intel XE#3149]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3149
  [Intel XE#316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/316
  [Intel XE#323]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/323
  [Intel XE#330]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/330
  [Intel XE#3342]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3342
  [Intel XE#3414]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3414
  [Intel XE#3573]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3573
  [Intel XE#366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/366
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#378]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/378
  [Intel XE#4173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4173
  [Intel XE#4212]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4212
  [Intel XE#4273]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4273
  [Intel XE#4331]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4331
  [Intel XE#4345]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4345
  [Intel XE#4354]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4354
  [Intel XE#4522]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4522
  [Intel XE#4543]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4543
  [Intel XE#455]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/455
  [Intel XE#4650]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4650
  [Intel XE#4733]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4733
  [Intel XE#4814]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4814
  [Intel XE#4819]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4819
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#4842]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4842
  [Intel XE#4915]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4915
  [Intel XE#5503]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5503
  [Intel XE#5624]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5624
  [Intel XE#5625]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5625
  [Intel XE#5626]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5626
  [Intel XE#5862]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5862
  [Intel XE#5893]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5893
  [Intel XE#619]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/619
  [Intel XE#6251]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6251
  [Intel XE#6312]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6312
  [Intel XE#6318]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6318
  [Intel XE#6366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6366
  [Intel XE#6507]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6507
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#6529]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6529
  [Intel XE#653]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/653
  [Intel XE#6554]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6554
  [Intel XE#658]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/658
  [Intel XE#787]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/787
  [Intel XE#870]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/870
  [Intel XE#929]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/929
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944
  [Intel XE#979]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/979


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

  * Linux: xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745 -> xe-pw-155951v4

  IGT_8614: 8614
  xe-4074-2bc418aa7efaae562e49d84e8b28f799cf624745: 2bc418aa7efaae562e49d84e8b28f799cf624745
  xe-pw-155951v4: 155951v4

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-155951v4/index.html

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

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
@ 2025-11-10 11:45   ` Jani Nikula
  2025-11-11  0:23     ` Gustavo Sousa
  2025-11-10 17:03   ` Ville Syrjälä
  1 sibling, 1 reply; 48+ messages in thread
From: Jani Nikula @ 2025-11-10 11:45 UTC (permalink / raw)
  To: Gustavo Sousa, intel-xe, intel-gfx
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Gustavo Sousa,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Ville Syrjälä

On Fri, 07 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
> Xe3p_LPD added several bits containing information that can be relevant
> to debugging FIFO underruns.  Add the logic necessary to handle them
> when reporting underruns.
>
> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
>
> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
>
> Bspec: 69111, 69561, 74411, 74412
> Cc: Jani Nikula <jani.nikula@intel.com>
> Cc: Matt Roper <matthew.d.roper@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
> I tested this by adding a change on top of this series that updates
> Xe3p_LPD's CDCLK table to use bad values and I got the following
> messages:
>
>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
> ---
>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>  4 files changed, 147 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
> index b559ef43d547..91d8cfac5eff 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>  #define HAS_TRANSCODER(__display, trans)	((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>  						  BIT(trans)) != 0)
>  #define HAS_UNCOMPRESSED_JOINER(__display)	(DISPLAY_VER(__display) >= 13)
> +#define HAS_UNDERRUN_DBG_INFO(__display)	(DISPLAY_VER(__display) >= 35)
>  #define HAS_ULTRAJOINER(__display)	(((__display)->platform.dgfx && \
>  					  DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>  #define HAS_VRR(__display)		(DISPLAY_VER(__display) >= 11)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 9d71e26a4fa2..89ea0156ee06 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -882,6 +882,21 @@
>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK		REG_GENMASK(2, 0) /* tgl+ */
>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)	REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>  
> +#define _UNDERRUN_DBG1_A			0x70064
> +#define _UNDERRUN_DBG1_B			0x71064
> +#define UNDERRUN_DBG1(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK	REG_GENMASK(29, 24)
> +#define   UNDERRUN_DDB_EMPTY_MASK		REG_GENMASK(21, 16)
> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK		REG_GENMASK(13, 8)
> +#define   UNDERRUN_BELOW_WM0_MASK		REG_GENMASK(5, 0)
> +
> +#define _UNDERRUN_DBG2_A			0x70068
> +#define _UNDERRUN_DBG2_B			0x71068
> +#define UNDERRUN_DBG2(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN	REG_BIT(31)
> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK	REG_GENMASK(30, 20)
> +#define   UNDERRUN_LINE_COUNT_MASK		REG_GENMASK(19, 0)
> +
>  #define DPINVGTT				_MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>  #define   DPINVGTT_EN_MASK_CHV				REG_GENMASK(27, 16)
>  #define   DPINVGTT_EN_MASK_VLV				REG_GENMASK(23, 16)
> @@ -1416,6 +1431,7 @@
>  
>  #define GEN12_DCPR_STATUS_1				_MMIO(0x46440)
>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS		REG_BIT(26)
> +#define  XE3P_UNDERRUN_PKGC				REG_BIT(21)
>  
>  #define FUSE_STRAP		_MMIO(0x42014)
>  #define   ILK_INTERNAL_GRAPHICS_DISABLE	REG_BIT(31)
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> index b1d0161a3196..77d8321c4fb3 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> @@ -88,6 +88,8 @@
>  #define DPFC_FENCE_YOFF			_MMIO(0x3218)
>  #define ILK_DPFC_FENCE_YOFF(fbc_id)	_MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>  #define DPFC_CHICKEN			_MMIO(0x3224)
> +#define FBC_DEBUG_STATUS(fbc_id)	_MMIO_PIPE((fbc_id), 0x43220, 0x43260)
> +#define   FBC_UNDERRUN_DECMPR			REG_BIT(27)
>  #define ILK_DPFC_CHICKEN(fbc_id)	_MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>  #define   DPFC_HT_MODIFY			REG_BIT(31) /* pre-ivb */
>  #define   DPFC_NUKE_ON_ANY_MODIFICATION		REG_BIT(23) /* bdw+ */
> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> index c2ce8461ac9e..8a05b5c5fccd 100644
> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> @@ -25,6 +25,8 @@
>   *
>   */
>  
> +#include <linux/seq_buf.h>
> +
>  #include <drm/drm_print.h>
>  
>  #include "i915_reg.h"
> @@ -34,6 +36,7 @@
>  #include "intel_display_trace.h"
>  #include "intel_display_types.h"
>  #include "intel_fbc.h"
> +#include "intel_fbc_regs.h"
>  #include "intel_fifo_underrun.h"
>  #include "intel_pch_display.h"
>  
> @@ -57,6 +60,118 @@
>   * The code also supports underrun detection on the PCH transcoder.
>   */
>  
> +#define UNDERRUN_DBG1_NUM_PLANES 6
> +
> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));

Nitpick, I really don't like the style of using "functional" (for want
of a better word) initializers. Complicated is fine, like below for
masks[], but doing something with the hardware or something that can
fail, feels iffy.

> +	struct {
> +		u32 plane_mask;
> +		const char *info;
> +	} masks[] = {
> +		{ REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
> +		{ REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
> +		{ REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
> +		{ REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
> +	};
> +	DECLARE_SEQ_BUF(planes_desc, 32);
> +

IMO there's also a lot more clarity in having the assignment and the
check back to back here:

	val = intel_de_read(display, UNDERRUN_DBG1(pipe));
	if (!val)
		return;

Ditto below.

BR,
Jani.


> +	if (!val)
> +		return;
> +
> +	intel_de_write(display, UNDERRUN_DBG1(pipe), val);
> +
> +	if (!log)
> +		return;
> +
> +	for (int i = 0; i < ARRAY_SIZE(masks); i++) {
> +		if (!masks[i].plane_mask)
> +			continue;
> +
> +		seq_buf_clear(&planes_desc);
> +
> +		for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
> +			if (!(masks[i].plane_mask & REG_BIT(j)))
> +				continue;
> +
> +			if (j == 0)
> +				seq_buf_puts(&planes_desc, "[C]");
> +			else
> +				seq_buf_printf(&planes_desc, "[%d]", j);
> +		}
> +
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: %s on planes: %s\n",
> +			pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
> +
> +		drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
> +	}
> +}
> +
> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
> +
> +	if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
> +		return;
> +
> +	intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
> +			pipe_name(pipe),
> +			REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
> +			REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
> +}
> +
> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
> +	u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
> +
> +	if (!(val & FBC_UNDERRUN_DECMPR))
> +		return;
> +
> +	intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: FBC decompressing\n",
> +			pipe_name(pipe));
> +}
> +
> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
> +{
> +	u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
> +
> +	if (!(val & XE3P_UNDERRUN_PKGC))
> +		return;
> +
> +	/*
> +	 * Note: If there are multiple pipes enabled, only one of them will see
> +	 * XE3P_UNDERRUN_PKGC set.
> +	 */
> +	intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"General FIFO underrun info: Package C-state blocking memory\n");
> +}
> +
> +static void read_underrun_dbg_info(struct intel_display *display,
> +				   enum pipe pipe,
> +				   bool log)
> +{
> +	if (!HAS_UNDERRUN_DBG_INFO(display))
> +		return;
> +
> +	read_underrun_dbg1(display, pipe, log);
> +	read_underrun_dbg2(display, pipe, log);
> +	read_underrun_dbg_fbc(display, pipe, log);
> +	read_underrun_dbg_pkgc(display, log);
> +}
> +
>  static bool ivb_can_enable_err_int(struct intel_display *display)
>  {
>  	struct intel_crtc *crtc;
> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>  	old = !crtc->cpu_fifo_underrun_disabled;
>  	crtc->cpu_fifo_underrun_disabled = !enable;
>  
> +	/*
> +	 * The debug bits get latched at the time of the FIFO underrun ISR bit
> +	 * getting set.  That means that any existing debug bit that is set when
> +	 * handling a FIFO underrun interrupt has the potential to belong to
> +	 * another underrun event (past or future).  To alleviate this problem,
> +	 * let's clear existing bits before enabling the interrupt, so that at
> +	 * least we don't get information that is too out-of-date.
> +	 */
> +	if (enable && !old)
> +		read_underrun_dbg_info(display, pipe, false);
> +
>  	if (HAS_GMCH(display))
>  		i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>  	else if (display->platform.ironlake || display->platform.sandybridge)
> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>  		trace_intel_cpu_fifo_underrun(display, pipe);
>  
>  		drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
> +
> +		read_underrun_dbg_info(display, pipe, true);
>  	}
>  
>  	intel_fbc_handle_fifo_underrun_irq(display);

-- 
Jani Nikula, Intel

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

* Re: [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe()
  2025-11-08  0:05 ` [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe() Gustavo Sousa
@ 2025-11-10 16:35   ` Matt Roper
  2025-11-10 17:03     ` Ville Syrjälä
  0 siblings, 1 reply; 48+ messages in thread
From: Matt Roper @ 2025-11-10 16:35 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

On Fri, Nov 07, 2025 at 09:05:38PM -0300, Gustavo Sousa wrote:
> We will need to know the FBC id respective to the pipe in other parts of
> the driver. Let's promote the static function skl_fbc_id_for_pipe() to a
> public one named intel_fbc_id_for_pipe().
> 
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_fbc.c           | 5 +++++
>  drivers/gpu/drm/i915/display/intel_fbc.h           | 2 ++
>  drivers/gpu/drm/i915/display/skl_universal_plane.c | 9 ++-------
>  3 files changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
> index a1e3083022ee..435bfd05109c 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/display/intel_fbc.c
> @@ -129,6 +129,11 @@ struct intel_fbc {
>  	const char *no_fbc_reason;
>  };
>  
> +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe)
> +{
> +	return pipe - PIPE_A + INTEL_FBC_A;

The existing usage of skl_fbc_id_for_pipe() was to call this function to
receive a (possibly bogus) FBC ID, and then follow up with a call to
skl_plane_has_fbc() which had checks to make sure the returned FBC ID
actually existed on the platform.  So, for example, calling
skl_fbc_id_for_pipe(PIPE_B) on something like an ICL would return
INTEL_FBC_B here, but then the subsequent call to skl_plane_has_fbc()
would realize that there is no FBC_B on that platform and bail out.
It's only relatively recently (MTL and beyond I think?) that FBC has
become usable on pipes other than A.

Now that we're promoting this function to be more general, should we
also adjust the logic so that this function either returns a *valid* FBC
ID or and error?  Otherwise it may not be apparent to people writing new
code that the result returned here can't be immediately trusted without
additional checking.


Matt

> +}
> +
>  /* plane stride in pixels */
>  static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
>  {
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
> index 91424563206a..3d02f3fe5630 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc.h
> +++ b/drivers/gpu/drm/i915/display/intel_fbc.h
> @@ -9,6 +9,7 @@
>  #include <linux/types.h>
>  
>  enum fb_op_origin;
> +enum pipe;
>  struct intel_atomic_state;
>  struct intel_crtc;
>  struct intel_crtc_state;
> @@ -27,6 +28,7 @@ enum intel_fbc_id {
>  	I915_MAX_FBCS,
>  };
>  
> +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe);
>  int intel_fbc_atomic_check(struct intel_atomic_state *state);
>  int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state);
>  bool intel_fbc_pre_update(struct intel_atomic_state *state,
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> index bc55fafe9ce3..275ee2903219 100644
> --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> @@ -439,11 +439,6 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb,
>  	return 4096;
>  }
>  
> -static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
> -{
> -	return pipe - PIPE_A + INTEL_FBC_A;
> -}
> -
>  static bool skl_plane_has_fbc(struct intel_display *display,
>  			      enum intel_fbc_id fbc_id, enum plane_id plane_id)
>  {
> @@ -896,7 +891,7 @@ static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb,
>  						  bool enable)
>  {
>  	struct intel_display *display = to_intel_display(plane);
> -	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe);
> +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(plane->pipe);
>  	u32 val;
>  
>  	/* Only HDR planes have pixel normalizer and don't matter if no FBC */
> @@ -2442,7 +2437,7 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state,
>  static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
>  				       enum pipe pipe, enum plane_id plane_id)
>  {
> -	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
> +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>  
>  	if (skl_plane_has_fbc(display, fbc_id, plane_id))
>  		return display->fbc[fbc_id];
> 
> -- 
> 2.51.0
> 

-- 
Matt Roper
Graphics Software Engineer
Linux GPU Platform Enablement
Intel Corporation

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

* Re: [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe()
  2025-11-10 16:35   ` Matt Roper
@ 2025-11-10 17:03     ` Ville Syrjälä
  2025-11-10 22:18       ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Ville Syrjälä @ 2025-11-10 17:03 UTC (permalink / raw)
  To: Matt Roper
  Cc: Gustavo Sousa, intel-xe, intel-gfx, Ankit Nautiyal,
	Dnyaneshwar Bhadane, Jouni Högander, Juha-pekka Heikkila,
	Luca Coelho, Lucas De Marchi, Matt Atwood, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

On Mon, Nov 10, 2025 at 08:35:03AM -0800, Matt Roper wrote:
> On Fri, Nov 07, 2025 at 09:05:38PM -0300, Gustavo Sousa wrote:
> > We will need to know the FBC id respective to the pipe in other parts of
> > the driver. Let's promote the static function skl_fbc_id_for_pipe() to a
> > public one named intel_fbc_id_for_pipe().
> > 
> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_fbc.c           | 5 +++++
> >  drivers/gpu/drm/i915/display/intel_fbc.h           | 2 ++
> >  drivers/gpu/drm/i915/display/skl_universal_plane.c | 9 ++-------
> >  3 files changed, 9 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
> > index a1e3083022ee..435bfd05109c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fbc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_fbc.c
> > @@ -129,6 +129,11 @@ struct intel_fbc {
> >  	const char *no_fbc_reason;
> >  };
> >  
> > +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe)
> > +{
> > +	return pipe - PIPE_A + INTEL_FBC_A;
> 
> The existing usage of skl_fbc_id_for_pipe() was to call this function to
> receive a (possibly bogus) FBC ID, and then follow up with a call to
> skl_plane_has_fbc() which had checks to make sure the returned FBC ID
> actually existed on the platform.  So, for example, calling
> skl_fbc_id_for_pipe(PIPE_B) on something like an ICL would return
> INTEL_FBC_B here, but then the subsequent call to skl_plane_has_fbc()
> would realize that there is no FBC_B on that platform and bail out.
> It's only relatively recently (MTL and beyond I think?) that FBC has
> become usable on pipes other than A.
> 
> Now that we're promoting this function to be more general, should we
> also adjust the logic so that this function either returns a *valid* FBC
> ID or and error?  Otherwise it may not be apparent to people writing new
> code that the result returned here can't be immediately trusted without
> additional checking.

The simples way to find the FBC instance for a pipe is to grab it from
the primary plane. That is already used elsewhere so won't make things
any less generic.

> 
> 
> Matt
> 
> > +}
> > +
> >  /* plane stride in pixels */
> >  static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
> >  {
> > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
> > index 91424563206a..3d02f3fe5630 100644
> > --- a/drivers/gpu/drm/i915/display/intel_fbc.h
> > +++ b/drivers/gpu/drm/i915/display/intel_fbc.h
> > @@ -9,6 +9,7 @@
> >  #include <linux/types.h>
> >  
> >  enum fb_op_origin;
> > +enum pipe;
> >  struct intel_atomic_state;
> >  struct intel_crtc;
> >  struct intel_crtc_state;
> > @@ -27,6 +28,7 @@ enum intel_fbc_id {
> >  	I915_MAX_FBCS,
> >  };
> >  
> > +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe);
> >  int intel_fbc_atomic_check(struct intel_atomic_state *state);
> >  int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state);
> >  bool intel_fbc_pre_update(struct intel_atomic_state *state,
> > diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > index bc55fafe9ce3..275ee2903219 100644
> > --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> > @@ -439,11 +439,6 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb,
> >  	return 4096;
> >  }
> >  
> > -static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
> > -{
> > -	return pipe - PIPE_A + INTEL_FBC_A;
> > -}
> > -
> >  static bool skl_plane_has_fbc(struct intel_display *display,
> >  			      enum intel_fbc_id fbc_id, enum plane_id plane_id)
> >  {
> > @@ -896,7 +891,7 @@ static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb,
> >  						  bool enable)
> >  {
> >  	struct intel_display *display = to_intel_display(plane);
> > -	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe);
> > +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(plane->pipe);
> >  	u32 val;
> >  
> >  	/* Only HDR planes have pixel normalizer and don't matter if no FBC */
> > @@ -2442,7 +2437,7 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state,
> >  static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
> >  				       enum pipe pipe, enum plane_id plane_id)
> >  {
> > -	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
> > +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
> >  
> >  	if (skl_plane_has_fbc(display, fbc_id, plane_id))
> >  		return display->fbc[fbc_id];
> > 
> > -- 
> > 2.51.0
> > 
> 
> -- 
> Matt Roper
> Graphics Software Engineer
> Linux GPU Platform Enablement
> Intel Corporation

-- 
Ville Syrjälä
Intel

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
  2025-11-10 11:45   ` Jani Nikula
@ 2025-11-10 17:03   ` Ville Syrjälä
  2025-11-10 23:42     ` Gustavo Sousa
  1 sibling, 1 reply; 48+ messages in thread
From: Ville Syrjälä @ 2025-11-10 17:03 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

On Fri, Nov 07, 2025 at 09:05:39PM -0300, Gustavo Sousa wrote:
> Xe3p_LPD added several bits containing information that can be relevant
> to debugging FIFO underruns.  Add the logic necessary to handle them
> when reporting underruns.
> 
> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
> 
> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
> 
> Bspec: 69111, 69561, 74411, 74412
> Cc: Jani Nikula <jani.nikula@intel.com>
> Cc: Matt Roper <matthew.d.roper@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
> I tested this by adding a change on top of this series that updates
> Xe3p_LPD's CDCLK table to use bad values and I got the following
> messages:
> 
>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
> ---
>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>  4 files changed, 147 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
> index b559ef43d547..91d8cfac5eff 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>  #define HAS_TRANSCODER(__display, trans)	((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>  						  BIT(trans)) != 0)
>  #define HAS_UNCOMPRESSED_JOINER(__display)	(DISPLAY_VER(__display) >= 13)
> +#define HAS_UNDERRUN_DBG_INFO(__display)	(DISPLAY_VER(__display) >= 35)
>  #define HAS_ULTRAJOINER(__display)	(((__display)->platform.dgfx && \
>  					  DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>  #define HAS_VRR(__display)		(DISPLAY_VER(__display) >= 11)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 9d71e26a4fa2..89ea0156ee06 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -882,6 +882,21 @@
>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK		REG_GENMASK(2, 0) /* tgl+ */
>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)	REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>  
> +#define _UNDERRUN_DBG1_A			0x70064
> +#define _UNDERRUN_DBG1_B			0x71064
> +#define UNDERRUN_DBG1(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK	REG_GENMASK(29, 24)
> +#define   UNDERRUN_DDB_EMPTY_MASK		REG_GENMASK(21, 16)
> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK		REG_GENMASK(13, 8)
> +#define   UNDERRUN_BELOW_WM0_MASK		REG_GENMASK(5, 0)
> +
> +#define _UNDERRUN_DBG2_A			0x70068
> +#define _UNDERRUN_DBG2_B			0x71068
> +#define UNDERRUN_DBG2(pipe)			_MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN	REG_BIT(31)
> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK	REG_GENMASK(30, 20)
> +#define   UNDERRUN_LINE_COUNT_MASK		REG_GENMASK(19, 0)
> +
>  #define DPINVGTT				_MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>  #define   DPINVGTT_EN_MASK_CHV				REG_GENMASK(27, 16)
>  #define   DPINVGTT_EN_MASK_VLV				REG_GENMASK(23, 16)
> @@ -1416,6 +1431,7 @@
>  
>  #define GEN12_DCPR_STATUS_1				_MMIO(0x46440)
>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS		REG_BIT(26)
> +#define  XE3P_UNDERRUN_PKGC				REG_BIT(21)
>  
>  #define FUSE_STRAP		_MMIO(0x42014)
>  #define   ILK_INTERNAL_GRAPHICS_DISABLE	REG_BIT(31)
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> index b1d0161a3196..77d8321c4fb3 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> @@ -88,6 +88,8 @@
>  #define DPFC_FENCE_YOFF			_MMIO(0x3218)
>  #define ILK_DPFC_FENCE_YOFF(fbc_id)	_MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>  #define DPFC_CHICKEN			_MMIO(0x3224)
> +#define FBC_DEBUG_STATUS(fbc_id)	_MMIO_PIPE((fbc_id), 0x43220, 0x43260)
> +#define   FBC_UNDERRUN_DECMPR			REG_BIT(27)
>  #define ILK_DPFC_CHICKEN(fbc_id)	_MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>  #define   DPFC_HT_MODIFY			REG_BIT(31) /* pre-ivb */
>  #define   DPFC_NUKE_ON_ANY_MODIFICATION		REG_BIT(23) /* bdw+ */
> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> index c2ce8461ac9e..8a05b5c5fccd 100644
> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
> @@ -25,6 +25,8 @@
>   *
>   */
>  
> +#include <linux/seq_buf.h>
> +
>  #include <drm/drm_print.h>
>  
>  #include "i915_reg.h"
> @@ -34,6 +36,7 @@
>  #include "intel_display_trace.h"
>  #include "intel_display_types.h"
>  #include "intel_fbc.h"
> +#include "intel_fbc_regs.h"
>  #include "intel_fifo_underrun.h"
>  #include "intel_pch_display.h"
>  
> @@ -57,6 +60,118 @@
>   * The code also supports underrun detection on the PCH transcoder.
>   */
>  
> +#define UNDERRUN_DBG1_NUM_PLANES 6
> +
> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
> +	struct {
> +		u32 plane_mask;
> +		const char *info;
> +	} masks[] = {
> +		{ REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
> +		{ REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
> +		{ REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
> +		{ REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
> +	};
> +	DECLARE_SEQ_BUF(planes_desc, 32);
> +
> +	if (!val)
> +		return;
> +
> +	intel_de_write(display, UNDERRUN_DBG1(pipe), val);
> +
> +	if (!log)
> +		return;
> +
> +	for (int i = 0; i < ARRAY_SIZE(masks); i++) {
> +		if (!masks[i].plane_mask)
> +			continue;
> +
> +		seq_buf_clear(&planes_desc);
> +
> +		for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
> +			if (!(masks[i].plane_mask & REG_BIT(j)))
> +				continue;
> +
> +			if (j == 0)
> +				seq_buf_puts(&planes_desc, "[C]");
> +			else
> +				seq_buf_printf(&planes_desc, "[%d]", j);
> +		}
> +
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: %s on planes: %s\n",
> +			pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
> +
> +		drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
> +	}
> +}
> +
> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
> +
> +	if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
> +		return;
> +
> +	intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
> +			pipe_name(pipe),
> +			REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
> +			REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
> +}
> +
> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
> +{
> +	enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
> +	u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
> +
> +	if (!(val & FBC_UNDERRUN_DECMPR))
> +		return;
> +
> +	intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"Pipe %c FIFO underrun info: FBC decompressing\n",
> +			pipe_name(pipe));
> +}

FBC code belongs in intel_fbc.c

> +
> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
> +{
> +	u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
> +
> +	if (!(val & XE3P_UNDERRUN_PKGC))
> +		return;
> +
> +	/*
> +	 * Note: If there are multiple pipes enabled, only one of them will see
> +	 * XE3P_UNDERRUN_PKGC set.
> +	 */
> +	intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
> +
> +	if (log)
> +		drm_err(display->drm,
> +			"General FIFO underrun info: Package C-state blocking memory\n");
> +}
> +
> +static void read_underrun_dbg_info(struct intel_display *display,
> +				   enum pipe pipe,
> +				   bool log)
> +{
> +	if (!HAS_UNDERRUN_DBG_INFO(display))
> +		return;
> +
> +	read_underrun_dbg1(display, pipe, log);
> +	read_underrun_dbg2(display, pipe, log);
> +	read_underrun_dbg_fbc(display, pipe, log);
> +	read_underrun_dbg_pkgc(display, log);
> +}
> +
>  static bool ivb_can_enable_err_int(struct intel_display *display)
>  {
>  	struct intel_crtc *crtc;
> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>  	old = !crtc->cpu_fifo_underrun_disabled;
>  	crtc->cpu_fifo_underrun_disabled = !enable;
>  
> +	/*
> +	 * The debug bits get latched at the time of the FIFO underrun ISR bit
> +	 * getting set.  That means that any existing debug bit that is set when
> +	 * handling a FIFO underrun interrupt has the potential to belong to
> +	 * another underrun event (past or future).  To alleviate this problem,
> +	 * let's clear existing bits before enabling the interrupt, so that at
> +	 * least we don't get information that is too out-of-date.
> +	 */
> +	if (enable && !old)
> +		read_underrun_dbg_info(display, pipe, false);
> +
>  	if (HAS_GMCH(display))
>  		i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>  	else if (display->platform.ironlake || display->platform.sandybridge)
> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>  		trace_intel_cpu_fifo_underrun(display, pipe);
>  
>  		drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
> +
> +		read_underrun_dbg_info(display, pipe, true);
>  	}
>  
>  	intel_fbc_handle_fifo_underrun_irq(display);
> 
> -- 
> 2.51.0

-- 
Ville Syrjälä
Intel

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

* Re: [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe()
  2025-11-10 17:03     ` Ville Syrjälä
@ 2025-11-10 22:18       ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-10 22:18 UTC (permalink / raw)
  To: Ville Syrjälä, Matt Roper
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

Quoting Ville Syrjälä (2025-11-10 14:03:03-03:00)
>On Mon, Nov 10, 2025 at 08:35:03AM -0800, Matt Roper wrote:
>> On Fri, Nov 07, 2025 at 09:05:38PM -0300, Gustavo Sousa wrote:
>> > We will need to know the FBC id respective to the pipe in other parts of
>> > the driver. Let's promote the static function skl_fbc_id_for_pipe() to a
>> > public one named intel_fbc_id_for_pipe().
>> > 
>> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/display/intel_fbc.c           | 5 +++++
>> >  drivers/gpu/drm/i915/display/intel_fbc.h           | 2 ++
>> >  drivers/gpu/drm/i915/display/skl_universal_plane.c | 9 ++-------
>> >  3 files changed, 9 insertions(+), 7 deletions(-)
>> > 
>> > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
>> > index a1e3083022ee..435bfd05109c 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_fbc.c
>> > +++ b/drivers/gpu/drm/i915/display/intel_fbc.c
>> > @@ -129,6 +129,11 @@ struct intel_fbc {
>> >          const char *no_fbc_reason;
>> >  };
>> >  
>> > +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe)
>> > +{
>> > +        return pipe - PIPE_A + INTEL_FBC_A;
>> 
>> The existing usage of skl_fbc_id_for_pipe() was to call this function to
>> receive a (possibly bogus) FBC ID, and then follow up with a call to
>> skl_plane_has_fbc() which had checks to make sure the returned FBC ID
>> actually existed on the platform.  So, for example, calling
>> skl_fbc_id_for_pipe(PIPE_B) on something like an ICL would return
>> INTEL_FBC_B here, but then the subsequent call to skl_plane_has_fbc()
>> would realize that there is no FBC_B on that platform and bail out.
>> It's only relatively recently (MTL and beyond I think?) that FBC has
>> become usable on pipes other than A.
>> 
>> Now that we're promoting this function to be more general, should we
>> also adjust the logic so that this function either returns a *valid* FBC
>> ID or and error?  Otherwise it may not be apparent to people writing new
>> code that the result returned here can't be immediately trusted without
>> additional checking.
>
>The simples way to find the FBC instance for a pipe is to grab it from
>the primary plane. That is already used elsewhere so won't make things
>any less generic.

And do that internally without a public function, right?  Because the
feedback in the next patch is that the part that handles the "FBC
decompressing" bit should be in intel_fbc.c.

How should the primary plane be found? Loop with
for_each_intel_plane_on_crtc() and get the one with type
DRM_PLANE_TYPE_PRIMARY?  For example:

    static struct intel_fbc *intel_fbc_for_pipe(struct intel_display *display, enum pipe pipe)
    {
    	struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
    	struct intel_plane *primary = NULL;
    	struct intel_plane *plane;

    	for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
    		if (plane->base.type == DRM_PLANE_TYPE_PRIMARY) {
    			primary = plane;
    			break;
    		}
    	}

    	if (drm_WARN_ON(display->drm, primary == NULL))
    		return NULL;

    	return primary->fbc;
    }

I saw that the DRM layer keeps a "primary" plane in struct drm_crtc,
but, reading the kerneldoc for that member, I get the feeling that we
should not use it.

--
Gustavo Sousa

>
>> 
>> 
>> Matt
>> 
>> > +}
>> > +
>> >  /* plane stride in pixels */
>> >  static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
>> >  {
>> > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
>> > index 91424563206a..3d02f3fe5630 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_fbc.h
>> > +++ b/drivers/gpu/drm/i915/display/intel_fbc.h
>> > @@ -9,6 +9,7 @@
>> >  #include <linux/types.h>
>> >  
>> >  enum fb_op_origin;
>> > +enum pipe;
>> >  struct intel_atomic_state;
>> >  struct intel_crtc;
>> >  struct intel_crtc_state;
>> > @@ -27,6 +28,7 @@ enum intel_fbc_id {
>> >          I915_MAX_FBCS,
>> >  };
>> >  
>> > +enum intel_fbc_id intel_fbc_id_for_pipe(enum pipe pipe);
>> >  int intel_fbc_atomic_check(struct intel_atomic_state *state);
>> >  int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state);
>> >  bool intel_fbc_pre_update(struct intel_atomic_state *state,
>> > diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
>> > index bc55fafe9ce3..275ee2903219 100644
>> > --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
>> > +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
>> > @@ -439,11 +439,6 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb,
>> >          return 4096;
>> >  }
>> >  
>> > -static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
>> > -{
>> > -        return pipe - PIPE_A + INTEL_FBC_A;
>> > -}
>> > -
>> >  static bool skl_plane_has_fbc(struct intel_display *display,
>> >                                enum intel_fbc_id fbc_id, enum plane_id plane_id)
>> >  {
>> > @@ -896,7 +891,7 @@ static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb,
>> >                                                    bool enable)
>> >  {
>> >          struct intel_display *display = to_intel_display(plane);
>> > -        enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe);
>> > +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(plane->pipe);
>> >          u32 val;
>> >  
>> >          /* Only HDR planes have pixel normalizer and don't matter if no FBC */
>> > @@ -2442,7 +2437,7 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state,
>> >  static struct intel_fbc *skl_plane_fbc(struct intel_display *display,
>> >                                         enum pipe pipe, enum plane_id plane_id)
>> >  {
>> > -        enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
>> > +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>> >  
>> >          if (skl_plane_has_fbc(display, fbc_id, plane_id))
>> >                  return display->fbc[fbc_id];
>> > 
>> > -- 
>> > 2.51.0
>> > 
>> 
>> -- 
>> Matt Roper
>> Graphics Software Engineer
>> Linux GPU Platform Enablement
>> Intel Corporation
>
>-- 
>Ville Syrjälä
>Intel

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-10 17:03   ` Ville Syrjälä
@ 2025-11-10 23:42     ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-10 23:42 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

Quoting Ville Syrjälä (2025-11-10 14:03:44-03:00)
>On Fri, Nov 07, 2025 at 09:05:39PM -0300, Gustavo Sousa wrote:
>> Xe3p_LPD added several bits containing information that can be relevant
>> to debugging FIFO underruns.  Add the logic necessary to handle them
>> when reporting underruns.
>> 
>> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
>> 
>> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
>> 
>> Bspec: 69111, 69561, 74411, 74412
>> Cc: Jani Nikula <jani.nikula@intel.com>
>> Cc: Matt Roper <matthew.d.roper@intel.com>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>> I tested this by adding a change on top of this series that updates
>> Xe3p_LPD's CDCLK table to use bad values and I got the following
>> messages:
>> 
>>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
>> ---
>>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>>  4 files changed, 147 insertions(+)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
>> index b559ef43d547..91d8cfac5eff 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
>> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>>  #define HAS_TRANSCODER(__display, trans)        ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>>                                                    BIT(trans)) != 0)
>>  #define HAS_UNCOMPRESSED_JOINER(__display)        (DISPLAY_VER(__display) >= 13)
>> +#define HAS_UNDERRUN_DBG_INFO(__display)        (DISPLAY_VER(__display) >= 35)
>>  #define HAS_ULTRAJOINER(__display)        (((__display)->platform.dgfx && \
>>                                            DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>>  #define HAS_VRR(__display)                (DISPLAY_VER(__display) >= 11)
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> index 9d71e26a4fa2..89ea0156ee06 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> @@ -882,6 +882,21 @@
>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK                REG_GENMASK(2, 0) /* tgl+ */
>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)        REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>>  
>> +#define _UNDERRUN_DBG1_A                        0x70064
>> +#define _UNDERRUN_DBG1_B                        0x71064
>> +#define UNDERRUN_DBG1(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
>> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK        REG_GENMASK(29, 24)
>> +#define   UNDERRUN_DDB_EMPTY_MASK                REG_GENMASK(21, 16)
>> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK                REG_GENMASK(13, 8)
>> +#define   UNDERRUN_BELOW_WM0_MASK                REG_GENMASK(5, 0)
>> +
>> +#define _UNDERRUN_DBG2_A                        0x70068
>> +#define _UNDERRUN_DBG2_B                        0x71068
>> +#define UNDERRUN_DBG2(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
>> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN        REG_BIT(31)
>> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK        REG_GENMASK(30, 20)
>> +#define   UNDERRUN_LINE_COUNT_MASK                REG_GENMASK(19, 0)
>> +
>>  #define DPINVGTT                                _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>>  #define   DPINVGTT_EN_MASK_CHV                                REG_GENMASK(27, 16)
>>  #define   DPINVGTT_EN_MASK_VLV                                REG_GENMASK(23, 16)
>> @@ -1416,6 +1431,7 @@
>>  
>>  #define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
>>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
>> +#define  XE3P_UNDERRUN_PKGC                                REG_BIT(21)
>>  
>>  #define FUSE_STRAP                _MMIO(0x42014)
>>  #define   ILK_INTERNAL_GRAPHICS_DISABLE        REG_BIT(31)
>> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> index b1d0161a3196..77d8321c4fb3 100644
>> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> @@ -88,6 +88,8 @@
>>  #define DPFC_FENCE_YOFF                        _MMIO(0x3218)
>>  #define ILK_DPFC_FENCE_YOFF(fbc_id)        _MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>>  #define DPFC_CHICKEN                        _MMIO(0x3224)
>> +#define FBC_DEBUG_STATUS(fbc_id)        _MMIO_PIPE((fbc_id), 0x43220, 0x43260)
>> +#define   FBC_UNDERRUN_DECMPR                        REG_BIT(27)
>>  #define ILK_DPFC_CHICKEN(fbc_id)        _MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>>  #define   DPFC_HT_MODIFY                        REG_BIT(31) /* pre-ivb */
>>  #define   DPFC_NUKE_ON_ANY_MODIFICATION                REG_BIT(23) /* bdw+ */
>> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> index c2ce8461ac9e..8a05b5c5fccd 100644
>> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> @@ -25,6 +25,8 @@
>>   *
>>   */
>>  
>> +#include <linux/seq_buf.h>
>> +
>>  #include <drm/drm_print.h>
>>  
>>  #include "i915_reg.h"
>> @@ -34,6 +36,7 @@
>>  #include "intel_display_trace.h"
>>  #include "intel_display_types.h"
>>  #include "intel_fbc.h"
>> +#include "intel_fbc_regs.h"
>>  #include "intel_fifo_underrun.h"
>>  #include "intel_pch_display.h"
>>  
>> @@ -57,6 +60,118 @@
>>   * The code also supports underrun detection on the PCH transcoder.
>>   */
>>  
>> +#define UNDERRUN_DBG1_NUM_PLANES 6
>> +
>> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>> +        struct {
>> +                u32 plane_mask;
>> +                const char *info;
>> +        } masks[] = {
>> +                { REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
>> +                { REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
>> +                { REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
>> +                { REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
>> +        };
>> +        DECLARE_SEQ_BUF(planes_desc, 32);
>> +
>> +        if (!val)
>> +                return;
>> +
>> +        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>> +
>> +        if (!log)
>> +                return;
>> +
>> +        for (int i = 0; i < ARRAY_SIZE(masks); i++) {
>> +                if (!masks[i].plane_mask)
>> +                        continue;
>> +
>> +                seq_buf_clear(&planes_desc);
>> +
>> +                for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
>> +                        if (!(masks[i].plane_mask & REG_BIT(j)))
>> +                                continue;
>> +
>> +                        if (j == 0)
>> +                                seq_buf_puts(&planes_desc, "[C]");
>> +                        else
>> +                                seq_buf_printf(&planes_desc, "[%d]", j);
>> +                }
>> +
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: %s on planes: %s\n",
>> +                        pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
>> +
>> +                drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
>> +        }
>> +}
>> +
>> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
>> +
>> +        if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
>> +                return;
>> +
>> +        intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
>> +                        pipe_name(pipe),
>> +                        REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
>> +                        REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
>> +}
>> +
>> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>> +        u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
>> +
>> +        if (!(val & FBC_UNDERRUN_DECMPR))
>> +                return;
>> +
>> +        intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: FBC decompressing\n",
>> +                        pipe_name(pipe));
>> +}
>
>FBC code belongs in intel_fbc.c

Alright.  Moving this to intel_fbc.c, then.

Thanks!

--
Gustavo Sousa

>
>> +
>> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
>> +{
>> +        u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
>> +
>> +        if (!(val & XE3P_UNDERRUN_PKGC))
>> +                return;
>> +
>> +        /*
>> +         * Note: If there are multiple pipes enabled, only one of them will see
>> +         * XE3P_UNDERRUN_PKGC set.
>> +         */
>> +        intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "General FIFO underrun info: Package C-state blocking memory\n");
>> +}
>> +
>> +static void read_underrun_dbg_info(struct intel_display *display,
>> +                                   enum pipe pipe,
>> +                                   bool log)
>> +{
>> +        if (!HAS_UNDERRUN_DBG_INFO(display))
>> +                return;
>> +
>> +        read_underrun_dbg1(display, pipe, log);
>> +        read_underrun_dbg2(display, pipe, log);
>> +        read_underrun_dbg_fbc(display, pipe, log);
>> +        read_underrun_dbg_pkgc(display, log);
>> +}
>> +
>>  static bool ivb_can_enable_err_int(struct intel_display *display)
>>  {
>>          struct intel_crtc *crtc;
>> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>>          old = !crtc->cpu_fifo_underrun_disabled;
>>          crtc->cpu_fifo_underrun_disabled = !enable;
>>  
>> +        /*
>> +         * The debug bits get latched at the time of the FIFO underrun ISR bit
>> +         * getting set.  That means that any existing debug bit that is set when
>> +         * handling a FIFO underrun interrupt has the potential to belong to
>> +         * another underrun event (past or future).  To alleviate this problem,
>> +         * let's clear existing bits before enabling the interrupt, so that at
>> +         * least we don't get information that is too out-of-date.
>> +         */
>> +        if (enable && !old)
>> +                read_underrun_dbg_info(display, pipe, false);
>> +
>>          if (HAS_GMCH(display))
>>                  i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>>          else if (display->platform.ironlake || display->platform.sandybridge)
>> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>>                  trace_intel_cpu_fifo_underrun(display, pipe);
>>  
>>                  drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
>> +
>> +                read_underrun_dbg_info(display, pipe, true);
>>          }
>>  
>>          intel_fbc_handle_fifo_underrun_irq(display);
>> 
>> -- 
>> 2.51.0
>
>-- 
>Ville Syrjälä
>Intel

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-10 11:45   ` Jani Nikula
@ 2025-11-11  0:23     ` Gustavo Sousa
  2025-11-11 10:22       ` Jani Nikula
  0 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-11  0:23 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Jouni Högander,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, Ville Syrjälä

Quoting Jani Nikula (2025-11-10 08:45:48-03:00)
>On Fri, 07 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
>> Xe3p_LPD added several bits containing information that can be relevant
>> to debugging FIFO underruns.  Add the logic necessary to handle them
>> when reporting underruns.
>>
>> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
>>
>> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
>>
>> Bspec: 69111, 69561, 74411, 74412
>> Cc: Jani Nikula <jani.nikula@intel.com>
>> Cc: Matt Roper <matthew.d.roper@intel.com>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>> I tested this by adding a change on top of this series that updates
>> Xe3p_LPD's CDCLK table to use bad values and I got the following
>> messages:
>>
>>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
>> ---
>>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>>  4 files changed, 147 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
>> index b559ef43d547..91d8cfac5eff 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
>> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>>  #define HAS_TRANSCODER(__display, trans)        ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>>                                                    BIT(trans)) != 0)
>>  #define HAS_UNCOMPRESSED_JOINER(__display)        (DISPLAY_VER(__display) >= 13)
>> +#define HAS_UNDERRUN_DBG_INFO(__display)        (DISPLAY_VER(__display) >= 35)
>>  #define HAS_ULTRAJOINER(__display)        (((__display)->platform.dgfx && \
>>                                            DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>>  #define HAS_VRR(__display)                (DISPLAY_VER(__display) >= 11)
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> index 9d71e26a4fa2..89ea0156ee06 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> @@ -882,6 +882,21 @@
>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK                REG_GENMASK(2, 0) /* tgl+ */
>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)        REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>>  
>> +#define _UNDERRUN_DBG1_A                        0x70064
>> +#define _UNDERRUN_DBG1_B                        0x71064
>> +#define UNDERRUN_DBG1(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
>> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK        REG_GENMASK(29, 24)
>> +#define   UNDERRUN_DDB_EMPTY_MASK                REG_GENMASK(21, 16)
>> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK                REG_GENMASK(13, 8)
>> +#define   UNDERRUN_BELOW_WM0_MASK                REG_GENMASK(5, 0)
>> +
>> +#define _UNDERRUN_DBG2_A                        0x70068
>> +#define _UNDERRUN_DBG2_B                        0x71068
>> +#define UNDERRUN_DBG2(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
>> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN        REG_BIT(31)
>> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK        REG_GENMASK(30, 20)
>> +#define   UNDERRUN_LINE_COUNT_MASK                REG_GENMASK(19, 0)
>> +
>>  #define DPINVGTT                                _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>>  #define   DPINVGTT_EN_MASK_CHV                                REG_GENMASK(27, 16)
>>  #define   DPINVGTT_EN_MASK_VLV                                REG_GENMASK(23, 16)
>> @@ -1416,6 +1431,7 @@
>>  
>>  #define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
>>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
>> +#define  XE3P_UNDERRUN_PKGC                                REG_BIT(21)
>>  
>>  #define FUSE_STRAP                _MMIO(0x42014)
>>  #define   ILK_INTERNAL_GRAPHICS_DISABLE        REG_BIT(31)
>> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> index b1d0161a3196..77d8321c4fb3 100644
>> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>> @@ -88,6 +88,8 @@
>>  #define DPFC_FENCE_YOFF                        _MMIO(0x3218)
>>  #define ILK_DPFC_FENCE_YOFF(fbc_id)        _MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>>  #define DPFC_CHICKEN                        _MMIO(0x3224)
>> +#define FBC_DEBUG_STATUS(fbc_id)        _MMIO_PIPE((fbc_id), 0x43220, 0x43260)
>> +#define   FBC_UNDERRUN_DECMPR                        REG_BIT(27)
>>  #define ILK_DPFC_CHICKEN(fbc_id)        _MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>>  #define   DPFC_HT_MODIFY                        REG_BIT(31) /* pre-ivb */
>>  #define   DPFC_NUKE_ON_ANY_MODIFICATION                REG_BIT(23) /* bdw+ */
>> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> index c2ce8461ac9e..8a05b5c5fccd 100644
>> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>> @@ -25,6 +25,8 @@
>>   *
>>   */
>>  
>> +#include <linux/seq_buf.h>
>> +
>>  #include <drm/drm_print.h>
>>  
>>  #include "i915_reg.h"
>> @@ -34,6 +36,7 @@
>>  #include "intel_display_trace.h"
>>  #include "intel_display_types.h"
>>  #include "intel_fbc.h"
>> +#include "intel_fbc_regs.h"
>>  #include "intel_fifo_underrun.h"
>>  #include "intel_pch_display.h"
>>  
>> @@ -57,6 +60,118 @@
>>   * The code also supports underrun detection on the PCH transcoder.
>>   */
>>  
>> +#define UNDERRUN_DBG1_NUM_PLANES 6
>> +
>> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>
>Nitpick, I really don't like the style of using "functional" (for want
>of a better word) initializers. Complicated is fine, like below for
>masks[], but doing something with the hardware or something that can
>fail, feels iffy.

Alright.  I'll update this to do as you suggested below.  One little
annoyance is that we will need to open code REG_FIELD_GET() (as done in
[1]), because the mask parameter needs to be a constant expression.

[1] https://lore.kernel.org/all/20251021-xe3p_lpd-basic-enabling-v2-11-10eae6d655b8@intel.com/

>
>> +        struct {
>> +                u32 plane_mask;
>> +                const char *info;
>> +        } masks[] = {
>> +                { REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
>> +                { REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
>> +                { REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
>> +                { REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
>> +        };
>> +        DECLARE_SEQ_BUF(planes_desc, 32);
>> +
>
>IMO there's also a lot more clarity in having the assignment and the
>check back to back here:
>
>        val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>        if (!val)
>                return;
>
>Ditto below.

I'll update those as well.

That said, for curiosity:

Do you prefer to always use the pattern of declaring a variable for
register values and assigning the result of the reading as separate
statements?  Or is this a preference for specific cases, like this one?

I did

    git grep -W 'u32\s\+\w\+\s*=\s*intel_de_read' -- drivers/gpu/drm/i915/display/

and found cases where the pattern "u32 val = intel_de_read(...)" appears
to make the code a bit more concise IMO.

While here in read_underrun_dbg1() the other variables and initializers
do get in the way of readability/clarity, I see cases like:

    u32 val = intel_de_read(...);

    do_something_with(val);

to be still clear, and each saves up 1 line of editor real estate.

--
Gustavo Sousa

>
>BR,
>Jani.
>
>
>> +        if (!val)
>> +                return;
>> +
>> +        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>> +
>> +        if (!log)
>> +                return;
>> +
>> +        for (int i = 0; i < ARRAY_SIZE(masks); i++) {
>> +                if (!masks[i].plane_mask)
>> +                        continue;
>> +
>> +                seq_buf_clear(&planes_desc);
>> +
>> +                for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
>> +                        if (!(masks[i].plane_mask & REG_BIT(j)))
>> +                                continue;
>> +
>> +                        if (j == 0)
>> +                                seq_buf_puts(&planes_desc, "[C]");
>> +                        else
>> +                                seq_buf_printf(&planes_desc, "[%d]", j);
>> +                }
>> +
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: %s on planes: %s\n",
>> +                        pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
>> +
>> +                drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
>> +        }
>> +}
>> +
>> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
>> +
>> +        if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
>> +                return;
>> +
>> +        intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
>> +                        pipe_name(pipe),
>> +                        REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
>> +                        REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
>> +}
>> +
>> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
>> +{
>> +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>> +        u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
>> +
>> +        if (!(val & FBC_UNDERRUN_DECMPR))
>> +                return;
>> +
>> +        intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "Pipe %c FIFO underrun info: FBC decompressing\n",
>> +                        pipe_name(pipe));
>> +}
>> +
>> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
>> +{
>> +        u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
>> +
>> +        if (!(val & XE3P_UNDERRUN_PKGC))
>> +                return;
>> +
>> +        /*
>> +         * Note: If there are multiple pipes enabled, only one of them will see
>> +         * XE3P_UNDERRUN_PKGC set.
>> +         */
>> +        intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
>> +
>> +        if (log)
>> +                drm_err(display->drm,
>> +                        "General FIFO underrun info: Package C-state blocking memory\n");
>> +}
>> +
>> +static void read_underrun_dbg_info(struct intel_display *display,
>> +                                   enum pipe pipe,
>> +                                   bool log)
>> +{
>> +        if (!HAS_UNDERRUN_DBG_INFO(display))
>> +                return;
>> +
>> +        read_underrun_dbg1(display, pipe, log);
>> +        read_underrun_dbg2(display, pipe, log);
>> +        read_underrun_dbg_fbc(display, pipe, log);
>> +        read_underrun_dbg_pkgc(display, log);
>> +}
>> +
>>  static bool ivb_can_enable_err_int(struct intel_display *display)
>>  {
>>          struct intel_crtc *crtc;
>> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>>          old = !crtc->cpu_fifo_underrun_disabled;
>>          crtc->cpu_fifo_underrun_disabled = !enable;
>>  
>> +        /*
>> +         * The debug bits get latched at the time of the FIFO underrun ISR bit
>> +         * getting set.  That means that any existing debug bit that is set when
>> +         * handling a FIFO underrun interrupt has the potential to belong to
>> +         * another underrun event (past or future).  To alleviate this problem,
>> +         * let's clear existing bits before enabling the interrupt, so that at
>> +         * least we don't get information that is too out-of-date.
>> +         */
>> +        if (enable && !old)
>> +                read_underrun_dbg_info(display, pipe, false);
>> +
>>          if (HAS_GMCH(display))
>>                  i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>>          else if (display->platform.ironlake || display->platform.sandybridge)
>> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>>                  trace_intel_cpu_fifo_underrun(display, pipe);
>>  
>>                  drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
>> +
>> +                read_underrun_dbg_info(display, pipe, true);
>>          }
>>  
>>          intel_fbc_handle_fifo_underrun_irq(display);
>
>-- 
>Jani Nikula, Intel

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-11  0:23     ` Gustavo Sousa
@ 2025-11-11 10:22       ` Jani Nikula
  2025-11-11 12:22         ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Jani Nikula @ 2025-11-11 10:22 UTC (permalink / raw)
  To: Gustavo Sousa, intel-gfx, intel-xe
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Jouni Högander,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, Ville Syrjälä

On Mon, 10 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
> Quoting Jani Nikula (2025-11-10 08:45:48-03:00)
>>On Fri, 07 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
>>> Xe3p_LPD added several bits containing information that can be relevant
>>> to debugging FIFO underruns.  Add the logic necessary to handle them
>>> when reporting underruns.
>>>
>>> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
>>>
>>> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
>>>
>>> Bspec: 69111, 69561, 74411, 74412
>>> Cc: Jani Nikula <jani.nikula@intel.com>
>>> Cc: Matt Roper <matthew.d.roper@intel.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>>> ---
>>> I tested this by adding a change on top of this series that updates
>>> Xe3p_LPD's CDCLK table to use bad values and I got the following
>>> messages:
>>>
>>>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>>>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>>>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>>>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
>>> ---
>>>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>>>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>>>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>>>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>>>  4 files changed, 147 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
>>> index b559ef43d547..91d8cfac5eff 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
>>> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>>>  #define HAS_TRANSCODER(__display, trans)        ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>>>                                                    BIT(trans)) != 0)
>>>  #define HAS_UNCOMPRESSED_JOINER(__display)        (DISPLAY_VER(__display) >= 13)
>>> +#define HAS_UNDERRUN_DBG_INFO(__display)        (DISPLAY_VER(__display) >= 35)
>>>  #define HAS_ULTRAJOINER(__display)        (((__display)->platform.dgfx && \
>>>                                            DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>>>  #define HAS_VRR(__display)                (DISPLAY_VER(__display) >= 11)
>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> index 9d71e26a4fa2..89ea0156ee06 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>> @@ -882,6 +882,21 @@
>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK                REG_GENMASK(2, 0) /* tgl+ */
>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)        REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>>>  
>>> +#define _UNDERRUN_DBG1_A                        0x70064
>>> +#define _UNDERRUN_DBG1_B                        0x71064
>>> +#define UNDERRUN_DBG1(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
>>> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK        REG_GENMASK(29, 24)
>>> +#define   UNDERRUN_DDB_EMPTY_MASK                REG_GENMASK(21, 16)
>>> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK                REG_GENMASK(13, 8)
>>> +#define   UNDERRUN_BELOW_WM0_MASK                REG_GENMASK(5, 0)
>>> +
>>> +#define _UNDERRUN_DBG2_A                        0x70068
>>> +#define _UNDERRUN_DBG2_B                        0x71068
>>> +#define UNDERRUN_DBG2(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
>>> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN        REG_BIT(31)
>>> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK        REG_GENMASK(30, 20)
>>> +#define   UNDERRUN_LINE_COUNT_MASK                REG_GENMASK(19, 0)
>>> +
>>>  #define DPINVGTT                                _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>>>  #define   DPINVGTT_EN_MASK_CHV                                REG_GENMASK(27, 16)
>>>  #define   DPINVGTT_EN_MASK_VLV                                REG_GENMASK(23, 16)
>>> @@ -1416,6 +1431,7 @@
>>>  
>>>  #define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
>>>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
>>> +#define  XE3P_UNDERRUN_PKGC                                REG_BIT(21)
>>>  
>>>  #define FUSE_STRAP                _MMIO(0x42014)
>>>  #define   ILK_INTERNAL_GRAPHICS_DISABLE        REG_BIT(31)
>>> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>> index b1d0161a3196..77d8321c4fb3 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>> @@ -88,6 +88,8 @@
>>>  #define DPFC_FENCE_YOFF                        _MMIO(0x3218)
>>>  #define ILK_DPFC_FENCE_YOFF(fbc_id)        _MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>>>  #define DPFC_CHICKEN                        _MMIO(0x3224)
>>> +#define FBC_DEBUG_STATUS(fbc_id)        _MMIO_PIPE((fbc_id), 0x43220, 0x43260)
>>> +#define   FBC_UNDERRUN_DECMPR                        REG_BIT(27)
>>>  #define ILK_DPFC_CHICKEN(fbc_id)        _MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>>>  #define   DPFC_HT_MODIFY                        REG_BIT(31) /* pre-ivb */
>>>  #define   DPFC_NUKE_ON_ANY_MODIFICATION                REG_BIT(23) /* bdw+ */
>>> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> index c2ce8461ac9e..8a05b5c5fccd 100644
>>> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>> @@ -25,6 +25,8 @@
>>>   *
>>>   */
>>>  
>>> +#include <linux/seq_buf.h>
>>> +
>>>  #include <drm/drm_print.h>
>>>  
>>>  #include "i915_reg.h"
>>> @@ -34,6 +36,7 @@
>>>  #include "intel_display_trace.h"
>>>  #include "intel_display_types.h"
>>>  #include "intel_fbc.h"
>>> +#include "intel_fbc_regs.h"
>>>  #include "intel_fifo_underrun.h"
>>>  #include "intel_pch_display.h"
>>>  
>>> @@ -57,6 +60,118 @@
>>>   * The code also supports underrun detection on the PCH transcoder.
>>>   */
>>>  
>>> +#define UNDERRUN_DBG1_NUM_PLANES 6
>>> +
>>> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
>>> +{
>>> +        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>>
>>Nitpick, I really don't like the style of using "functional" (for want
>>of a better word) initializers. Complicated is fine, like below for
>>masks[], but doing something with the hardware or something that can
>>fail, feels iffy.
>
> Alright.  I'll update this to do as you suggested below.  One little
> annoyance is that we will need to open code REG_FIELD_GET() (as done in
> [1]), because the mask parameter needs to be a constant expression.
>
> [1] https://lore.kernel.org/all/20251021-xe3p_lpd-basic-enabling-v2-11-10eae6d655b8@intel.com/
>
>>
>>> +        struct {
>>> +                u32 plane_mask;
>>> +                const char *info;
>>> +        } masks[] = {
>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
>>> +                { REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
>>> +                { REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
>>> +        };
>>> +        DECLARE_SEQ_BUF(planes_desc, 32);
>>> +

Mmh, right, I didn't even spot that val was being used in the masks[]
initialization.

Here's a completely different approach that avoids some of the
problems. I'm not sure if it's better or worse, just different. Two
lines shorter than the original.

static void log_underrun_dbg(struct intel_display *display, unsigned long plane_mask,
			     enum pipe pipe, const char *info)
{
	DECLARE_SEQ_BUF(planes_desc, 32);
	unsigned int i;

	if (!plane_mask)
		return;

	for_each_set_bit(i, &plane_mask, UNDERRUN_DBG1_NUM_PLANES) {
		if (i == 0)
			seq_buf_puts(&planes_desc, "[C]");
		else
			seq_buf_printf(&planes_desc, "[%d]", i);
	}
	
	drm_err(display->drm, "Pipe %c FIFO underrun info: %s on planes: %s\n",
		pipe_name(pipe), info, seq_buf_str(&planes_desc));
	
	drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
}

static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
{
	u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));

	if (!val)
		return;

	intel_de_write(display, UNDERRUN_DBG1(pipe), val);

	if (!log)
		return;

	log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val),
			 pipe, "DBUF block not valid");
	log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val),
			 pipe, "DDB empty");
	log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val),
			 pipe, "DBUF not completely filled");
	log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val),
			 pipe, "DBUF below WM0");
}

>>IMO there's also a lot more clarity in having the assignment and the
>>check back to back here:
>>
>>        val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>>        if (!val)
>>                return;
>>
>>Ditto below.
>
> I'll update those as well.
>
> That said, for curiosity:
>
> Do you prefer to always use the pattern of declaring a variable for
> register values and assigning the result of the reading as separate
> statements?  Or is this a preference for specific cases, like this one?
>
> I did
>
>     git grep -W 'u32\s\+\w\+\s*=\s*intel_de_read' -- drivers/gpu/drm/i915/display/
>
> and found cases where the pattern "u32 val = intel_de_read(...)" appears
> to make the code a bit more concise IMO.
>
> While here in read_underrun_dbg1() the other variables and initializers
> do get in the way of readability/clarity, I see cases like:
>
>     u32 val = intel_de_read(...);
>
>     do_something_with(val);
>
> to be still clear, and each saves up 1 line of editor real estate.

Yeah, I guess it's a bit hard to have hard rules, and in small functions
or blocks it's fine to combine. Let's maybe file this under a knee-jerk
reaction to read_underrun_dbg1() where there's a bunch of declarations,
and the actual code starts with if (!val) and you're like where did that
come from. The other functions appear small enough. Fair?

BR,
Jani.

>
> --
> Gustavo Sousa
>
>>
>>BR,
>>Jani.
>>
>>
>>> +        if (!val)
>>> +                return;
>>> +
>>> +        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>>> +
>>> +        if (!log)
>>> +                return;
>>> +
>>> +        for (int i = 0; i < ARRAY_SIZE(masks); i++) {
>>> +                if (!masks[i].plane_mask)
>>> +                        continue;
>>> +
>>> +                seq_buf_clear(&planes_desc);
>>> +
>>> +                for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
>>> +                        if (!(masks[i].plane_mask & REG_BIT(j)))
>>> +                                continue;
>>> +
>>> +                        if (j == 0)
>>> +                                seq_buf_puts(&planes_desc, "[C]");
>>> +                        else
>>> +                                seq_buf_printf(&planes_desc, "[%d]", j);
>>> +                }
>>> +
>>> +                drm_err(display->drm,
>>> +                        "Pipe %c FIFO underrun info: %s on planes: %s\n",
>>> +                        pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
>>> +
>>> +                drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
>>> +        }
>>> +}
>>> +
>>> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
>>> +{
>>> +        u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
>>> +
>>> +        if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
>>> +                return;
>>> +
>>> +        intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
>>> +
>>> +        if (log)
>>> +                drm_err(display->drm,
>>> +                        "Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
>>> +                        pipe_name(pipe),
>>> +                        REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
>>> +                        REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
>>> +}
>>> +
>>> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
>>> +{
>>> +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>>> +        u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
>>> +
>>> +        if (!(val & FBC_UNDERRUN_DECMPR))
>>> +                return;
>>> +
>>> +        intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
>>> +
>>> +        if (log)
>>> +                drm_err(display->drm,
>>> +                        "Pipe %c FIFO underrun info: FBC decompressing\n",
>>> +                        pipe_name(pipe));
>>> +}
>>> +
>>> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
>>> +{
>>> +        u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
>>> +
>>> +        if (!(val & XE3P_UNDERRUN_PKGC))
>>> +                return;
>>> +
>>> +        /*
>>> +         * Note: If there are multiple pipes enabled, only one of them will see
>>> +         * XE3P_UNDERRUN_PKGC set.
>>> +         */
>>> +        intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
>>> +
>>> +        if (log)
>>> +                drm_err(display->drm,
>>> +                        "General FIFO underrun info: Package C-state blocking memory\n");
>>> +}
>>> +
>>> +static void read_underrun_dbg_info(struct intel_display *display,
>>> +                                   enum pipe pipe,
>>> +                                   bool log)
>>> +{
>>> +        if (!HAS_UNDERRUN_DBG_INFO(display))
>>> +                return;
>>> +
>>> +        read_underrun_dbg1(display, pipe, log);
>>> +        read_underrun_dbg2(display, pipe, log);
>>> +        read_underrun_dbg_fbc(display, pipe, log);
>>> +        read_underrun_dbg_pkgc(display, log);
>>> +}
>>> +
>>>  static bool ivb_can_enable_err_int(struct intel_display *display)
>>>  {
>>>          struct intel_crtc *crtc;
>>> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>>>          old = !crtc->cpu_fifo_underrun_disabled;
>>>          crtc->cpu_fifo_underrun_disabled = !enable;
>>>  
>>> +        /*
>>> +         * The debug bits get latched at the time of the FIFO underrun ISR bit
>>> +         * getting set.  That means that any existing debug bit that is set when
>>> +         * handling a FIFO underrun interrupt has the potential to belong to
>>> +         * another underrun event (past or future).  To alleviate this problem,
>>> +         * let's clear existing bits before enabling the interrupt, so that at
>>> +         * least we don't get information that is too out-of-date.
>>> +         */
>>> +        if (enable && !old)
>>> +                read_underrun_dbg_info(display, pipe, false);
>>> +
>>>          if (HAS_GMCH(display))
>>>                  i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>>>          else if (display->platform.ironlake || display->platform.sandybridge)
>>> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>>>                  trace_intel_cpu_fifo_underrun(display, pipe);
>>>  
>>>                  drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
>>> +
>>> +                read_underrun_dbg_info(display, pipe, true);
>>>          }
>>>  
>>>          intel_fbc_handle_fifo_underrun_irq(display);
>>
>>-- 
>>Jani Nikula, Intel

-- 
Jani Nikula, Intel

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

* Re: [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits
  2025-11-11 10:22       ` Jani Nikula
@ 2025-11-11 12:22         ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-11 12:22 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe
  Cc: Ankit Nautiyal, Dnyaneshwar Bhadane, Jouni Högander,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, Ville Syrjälä

Quoting Jani Nikula (2025-11-11 07:22:43-03:00)
>On Mon, 10 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
>> Quoting Jani Nikula (2025-11-10 08:45:48-03:00)
>>>On Fri, 07 Nov 2025, Gustavo Sousa <gustavo.sousa@intel.com> wrote:
>>>> Xe3p_LPD added several bits containing information that can be relevant
>>>> to debugging FIFO underruns.  Add the logic necessary to handle them
>>>> when reporting underruns.
>>>>
>>>> This was adapted from the initial patch[1] from Sai Teja Pottumuttu.
>>>>
>>>> [1] https://lore.kernel.org/all/20251015-xe3p_lpd-basic-enabling-v1-12-d2d1e26520aa@intel.com/
>>>>
>>>> Bspec: 69111, 69561, 74411, 74412
>>>> Cc: Jani Nikula <jani.nikula@intel.com>
>>>> Cc: Matt Roper <matthew.d.roper@intel.com>
>>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>>>> ---
>>>> I tested this by adding a change on top of this series that updates
>>>> Xe3p_LPD's CDCLK table to use bad values and I got the following
>>>> messages:
>>>>
>>>>     [  +0.000237] xe 0000:00:02.0: [drm:intel_modeset_verify_crtc [xe]] [CRTC:88:pipe A]
>>>>     [  +0.000674] xe 0000:00:02.0: [drm] *ERROR* CPU pipe A FIFO underrun
>>>>     [  +0.000015] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF block not valid on planes: [1]
>>>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DDB empty on planes: [1]
>>>>     [  +0.000001] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: DBUF below WM0 on planes: [1]
>>>>     [  +0.000004] xe 0000:00:02.0: [drm] *ERROR* Pipe A FIFO underrun info: frame count: 1890, line count: 44
>>>> ---
>>>>  .../gpu/drm/i915/display/intel_display_device.h    |   1 +
>>>>  drivers/gpu/drm/i915/display/intel_display_regs.h  |  16 +++
>>>>  drivers/gpu/drm/i915/display/intel_fbc_regs.h      |   2 +
>>>>  drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 128 +++++++++++++++++++++
>>>>  4 files changed, 147 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
>>>> index b559ef43d547..91d8cfac5eff 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
>>>> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
>>>> @@ -197,6 +197,7 @@ struct intel_display_platforms {
>>>>  #define HAS_TRANSCODER(__display, trans)        ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
>>>>                                                    BIT(trans)) != 0)
>>>>  #define HAS_UNCOMPRESSED_JOINER(__display)        (DISPLAY_VER(__display) >= 13)
>>>> +#define HAS_UNDERRUN_DBG_INFO(__display)        (DISPLAY_VER(__display) >= 35)
>>>>  #define HAS_ULTRAJOINER(__display)        (((__display)->platform.dgfx && \
>>>>                                            DISPLAY_VER(__display) == 14) && HAS_DSC(__display))
>>>>  #define HAS_VRR(__display)                (DISPLAY_VER(__display) >= 11)
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>>> index 9d71e26a4fa2..89ea0156ee06 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>>>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>>>> @@ -882,6 +882,21 @@
>>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK                REG_GENMASK(2, 0) /* tgl+ */
>>>>  #define   PIPE_MISC2_FLIP_INFO_PLANE_SEL(plane_id)        REG_FIELD_PREP(PIPE_MISC2_FLIP_INFO_PLANE_SEL_MASK, (plane_id))
>>>>  
>>>> +#define _UNDERRUN_DBG1_A                        0x70064
>>>> +#define _UNDERRUN_DBG1_B                        0x71064
>>>> +#define UNDERRUN_DBG1(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG1_A, _UNDERRUN_DBG1_B)
>>>> +#define   UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK        REG_GENMASK(29, 24)
>>>> +#define   UNDERRUN_DDB_EMPTY_MASK                REG_GENMASK(21, 16)
>>>> +#define   UNDERRUN_DBUF_NOT_FILLED_MASK                REG_GENMASK(13, 8)
>>>> +#define   UNDERRUN_BELOW_WM0_MASK                REG_GENMASK(5, 0)
>>>> +
>>>> +#define _UNDERRUN_DBG2_A                        0x70068
>>>> +#define _UNDERRUN_DBG2_B                        0x71068
>>>> +#define UNDERRUN_DBG2(pipe)                        _MMIO_PIPE(pipe, _UNDERRUN_DBG2_A, _UNDERRUN_DBG2_B)
>>>> +#define   UNDERRUN_FRAME_LINE_COUNTERS_FROZEN        REG_BIT(31)
>>>> +#define   UNDERRUN_PIPE_FRAME_COUNT_MASK        REG_GENMASK(30, 20)
>>>> +#define   UNDERRUN_LINE_COUNT_MASK                REG_GENMASK(19, 0)
>>>> +
>>>>  #define DPINVGTT                                _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
>>>>  #define   DPINVGTT_EN_MASK_CHV                                REG_GENMASK(27, 16)
>>>>  #define   DPINVGTT_EN_MASK_VLV                                REG_GENMASK(23, 16)
>>>> @@ -1416,6 +1431,7 @@
>>>>  
>>>>  #define GEN12_DCPR_STATUS_1                                _MMIO(0x46440)
>>>>  #define  XELPDP_PMDEMAND_INFLIGHT_STATUS                REG_BIT(26)
>>>> +#define  XE3P_UNDERRUN_PKGC                                REG_BIT(21)
>>>>  
>>>>  #define FUSE_STRAP                _MMIO(0x42014)
>>>>  #define   ILK_INTERNAL_GRAPHICS_DISABLE        REG_BIT(31)
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>>> index b1d0161a3196..77d8321c4fb3 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>>> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
>>>> @@ -88,6 +88,8 @@
>>>>  #define DPFC_FENCE_YOFF                        _MMIO(0x3218)
>>>>  #define ILK_DPFC_FENCE_YOFF(fbc_id)        _MMIO_PIPE((fbc_id), 0x43218, 0x43258)
>>>>  #define DPFC_CHICKEN                        _MMIO(0x3224)
>>>> +#define FBC_DEBUG_STATUS(fbc_id)        _MMIO_PIPE((fbc_id), 0x43220, 0x43260)
>>>> +#define   FBC_UNDERRUN_DECMPR                        REG_BIT(27)
>>>>  #define ILK_DPFC_CHICKEN(fbc_id)        _MMIO_PIPE((fbc_id), 0x43224, 0x43264)
>>>>  #define   DPFC_HT_MODIFY                        REG_BIT(31) /* pre-ivb */
>>>>  #define   DPFC_NUKE_ON_ANY_MODIFICATION                REG_BIT(23) /* bdw+ */
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>>> index c2ce8461ac9e..8a05b5c5fccd 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>>> +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c
>>>> @@ -25,6 +25,8 @@
>>>>   *
>>>>   */
>>>>  
>>>> +#include <linux/seq_buf.h>
>>>> +
>>>>  #include <drm/drm_print.h>
>>>>  
>>>>  #include "i915_reg.h"
>>>> @@ -34,6 +36,7 @@
>>>>  #include "intel_display_trace.h"
>>>>  #include "intel_display_types.h"
>>>>  #include "intel_fbc.h"
>>>> +#include "intel_fbc_regs.h"
>>>>  #include "intel_fifo_underrun.h"
>>>>  #include "intel_pch_display.h"
>>>>  
>>>> @@ -57,6 +60,118 @@
>>>>   * The code also supports underrun detection on the PCH transcoder.
>>>>   */
>>>>  
>>>> +#define UNDERRUN_DBG1_NUM_PLANES 6
>>>> +
>>>> +static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
>>>> +{
>>>> +        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>>>
>>>Nitpick, I really don't like the style of using "functional" (for want
>>>of a better word) initializers. Complicated is fine, like below for
>>>masks[], but doing something with the hardware or something that can
>>>fail, feels iffy.
>>
>> Alright.  I'll update this to do as you suggested below.  One little
>> annoyance is that we will need to open code REG_FIELD_GET() (as done in
>> [1]), because the mask parameter needs to be a constant expression.
>>
>> [1] https://lore.kernel.org/all/20251021-xe3p_lpd-basic-enabling-v2-11-10eae6d655b8@intel.com/
>>
>>>
>>>> +        struct {
>>>> +                u32 plane_mask;
>>>> +                const char *info;
>>>> +        } masks[] = {
>>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val), "DBUF block not valid" },
>>>> +                { REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val), "DDB empty" },
>>>> +                { REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val), "DBUF not completely filled" },
>>>> +                { REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val), "DBUF below WM0" },
>>>> +        };
>>>> +        DECLARE_SEQ_BUF(planes_desc, 32);
>>>> +
>
>Mmh, right, I didn't even spot that val was being used in the masks[]
>initialization.
>
>Here's a completely different approach that avoids some of the
>problems. I'm not sure if it's better or worse, just different. Two
>lines shorter than the original.
>
>static void log_underrun_dbg(struct intel_display *display, unsigned long plane_mask,
>                             enum pipe pipe, const char *info)
>{
>        DECLARE_SEQ_BUF(planes_desc, 32);
>        unsigned int i;
>
>        if (!plane_mask)
>                return;
>
>        for_each_set_bit(i, &plane_mask, UNDERRUN_DBG1_NUM_PLANES) {
>                if (i == 0)
>                        seq_buf_puts(&planes_desc, "[C]");
>                else
>                        seq_buf_printf(&planes_desc, "[%d]", i);
>        }
>        
>        drm_err(display->drm, "Pipe %c FIFO underrun info: %s on planes: %s\n",
>                pipe_name(pipe), info, seq_buf_str(&planes_desc));
>        
>        drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
>}
>
>static void read_underrun_dbg1(struct intel_display *display, enum pipe pipe, bool log)
>{
>        u32 val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>
>        if (!val)
>                return;
>
>        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>
>        if (!log)
>                return;
>
>        log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DBUF_BLOCK_NOT_VALID_MASK, val),
>                         pipe, "DBUF block not valid");
>        log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DDB_EMPTY_MASK, val),
>                         pipe, "DDB empty");
>        log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_DBUF_NOT_FILLED_MASK, val),
>                         pipe, "DBUF not completely filled");
>        log_underrun_dbg(display, REG_FIELD_GET(UNDERRUN_BELOW_WM0_MASK, val),
>                         pipe, "DBUF below WM0");
>}

I like this approach! I'll use it. Thanks! :-)

>
>>>IMO there's also a lot more clarity in having the assignment and the
>>>check back to back here:
>>>
>>>        val = intel_de_read(display, UNDERRUN_DBG1(pipe));
>>>        if (!val)
>>>                return;
>>>
>>>Ditto below.
>>
>> I'll update those as well.
>>
>> That said, for curiosity:
>>
>> Do you prefer to always use the pattern of declaring a variable for
>> register values and assigning the result of the reading as separate
>> statements?  Or is this a preference for specific cases, like this one?
>>
>> I did
>>
>>     git grep -W 'u32\s\+\w\+\s*=\s*intel_de_read' -- drivers/gpu/drm/i915/display/
>>
>> and found cases where the pattern "u32 val = intel_de_read(...)" appears
>> to make the code a bit more concise IMO.
>>
>> While here in read_underrun_dbg1() the other variables and initializers
>> do get in the way of readability/clarity, I see cases like:
>>
>>     u32 val = intel_de_read(...);
>>
>>     do_something_with(val);
>>
>> to be still clear, and each saves up 1 line of editor real estate.
>
>Yeah, I guess it's a bit hard to have hard rules, and in small functions
>or blocks it's fine to combine. Let's maybe file this under a knee-jerk
>reaction to read_underrun_dbg1() where there's a bunch of declarations,
>and the actual code starts with if (!val) and you're like where did that
>come from. The other functions appear small enough. Fair?

Sounds good to me!

Thanks.

--
Gustavo Sousa

>
>BR,
>Jani.
>
>>
>> --
>> Gustavo Sousa
>>
>>>
>>>BR,
>>>Jani.
>>>
>>>
>>>> +        if (!val)
>>>> +                return;
>>>> +
>>>> +        intel_de_write(display, UNDERRUN_DBG1(pipe), val);
>>>> +
>>>> +        if (!log)
>>>> +                return;
>>>> +
>>>> +        for (int i = 0; i < ARRAY_SIZE(masks); i++) {
>>>> +                if (!masks[i].plane_mask)
>>>> +                        continue;
>>>> +
>>>> +                seq_buf_clear(&planes_desc);
>>>> +
>>>> +                for (int j = 0; j < UNDERRUN_DBG1_NUM_PLANES; j++) {
>>>> +                        if (!(masks[i].plane_mask & REG_BIT(j)))
>>>> +                                continue;
>>>> +
>>>> +                        if (j == 0)
>>>> +                                seq_buf_puts(&planes_desc, "[C]");
>>>> +                        else
>>>> +                                seq_buf_printf(&planes_desc, "[%d]", j);
>>>> +                }
>>>> +
>>>> +                drm_err(display->drm,
>>>> +                        "Pipe %c FIFO underrun info: %s on planes: %s\n",
>>>> +                        pipe_name(pipe), masks[i].info, seq_buf_str(&planes_desc));
>>>> +
>>>> +                drm_WARN_ON(display->drm, seq_buf_has_overflowed(&planes_desc));
>>>> +        }
>>>> +}
>>>> +
>>>> +static void read_underrun_dbg2(struct intel_display *display, enum pipe pipe, bool log)
>>>> +{
>>>> +        u32 val = intel_de_read(display, UNDERRUN_DBG2(pipe));
>>>> +
>>>> +        if (!(val & UNDERRUN_FRAME_LINE_COUNTERS_FROZEN))
>>>> +                return;
>>>> +
>>>> +        intel_de_write(display, UNDERRUN_DBG2(pipe), UNDERRUN_FRAME_LINE_COUNTERS_FROZEN);
>>>> +
>>>> +        if (log)
>>>> +                drm_err(display->drm,
>>>> +                        "Pipe %c FIFO underrun info: frame count: %u, line count: %u\n",
>>>> +                        pipe_name(pipe),
>>>> +                        REG_FIELD_GET(UNDERRUN_PIPE_FRAME_COUNT_MASK, val),
>>>> +                        REG_FIELD_GET(UNDERRUN_LINE_COUNT_MASK, val));
>>>> +}
>>>> +
>>>> +static void read_underrun_dbg_fbc(struct intel_display *display, enum pipe pipe, bool log)
>>>> +{
>>>> +        enum intel_fbc_id fbc_id = intel_fbc_id_for_pipe(pipe);
>>>> +        u32 val = intel_de_read(display, FBC_DEBUG_STATUS(fbc_id));
>>>> +
>>>> +        if (!(val & FBC_UNDERRUN_DECMPR))
>>>> +                return;
>>>> +
>>>> +        intel_de_write(display, FBC_DEBUG_STATUS(fbc_id), FBC_UNDERRUN_DECMPR);
>>>> +
>>>> +        if (log)
>>>> +                drm_err(display->drm,
>>>> +                        "Pipe %c FIFO underrun info: FBC decompressing\n",
>>>> +                        pipe_name(pipe));
>>>> +}
>>>> +
>>>> +static void read_underrun_dbg_pkgc(struct intel_display *display, bool log)
>>>> +{
>>>> +        u32 val = intel_de_read(display, GEN12_DCPR_STATUS_1);
>>>> +
>>>> +        if (!(val & XE3P_UNDERRUN_PKGC))
>>>> +                return;
>>>> +
>>>> +        /*
>>>> +         * Note: If there are multiple pipes enabled, only one of them will see
>>>> +         * XE3P_UNDERRUN_PKGC set.
>>>> +         */
>>>> +        intel_de_write(display, GEN12_DCPR_STATUS_1, XE3P_UNDERRUN_PKGC);
>>>> +
>>>> +        if (log)
>>>> +                drm_err(display->drm,
>>>> +                        "General FIFO underrun info: Package C-state blocking memory\n");
>>>> +}
>>>> +
>>>> +static void read_underrun_dbg_info(struct intel_display *display,
>>>> +                                   enum pipe pipe,
>>>> +                                   bool log)
>>>> +{
>>>> +        if (!HAS_UNDERRUN_DBG_INFO(display))
>>>> +                return;
>>>> +
>>>> +        read_underrun_dbg1(display, pipe, log);
>>>> +        read_underrun_dbg2(display, pipe, log);
>>>> +        read_underrun_dbg_fbc(display, pipe, log);
>>>> +        read_underrun_dbg_pkgc(display, log);
>>>> +}
>>>> +
>>>>  static bool ivb_can_enable_err_int(struct intel_display *display)
>>>>  {
>>>>          struct intel_crtc *crtc;
>>>> @@ -262,6 +377,17 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
>>>>          old = !crtc->cpu_fifo_underrun_disabled;
>>>>          crtc->cpu_fifo_underrun_disabled = !enable;
>>>>  
>>>> +        /*
>>>> +         * The debug bits get latched at the time of the FIFO underrun ISR bit
>>>> +         * getting set.  That means that any existing debug bit that is set when
>>>> +         * handling a FIFO underrun interrupt has the potential to belong to
>>>> +         * another underrun event (past or future).  To alleviate this problem,
>>>> +         * let's clear existing bits before enabling the interrupt, so that at
>>>> +         * least we don't get information that is too out-of-date.
>>>> +         */
>>>> +        if (enable && !old)
>>>> +                read_underrun_dbg_info(display, pipe, false);
>>>> +
>>>>          if (HAS_GMCH(display))
>>>>                  i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
>>>>          else if (display->platform.ironlake || display->platform.sandybridge)
>>>> @@ -379,6 +505,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
>>>>                  trace_intel_cpu_fifo_underrun(display, pipe);
>>>>  
>>>>                  drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
>>>> +
>>>> +                read_underrun_dbg_info(display, pipe, true);
>>>>          }
>>>>  
>>>>          intel_fbc_handle_fifo_underrun_irq(display);
>>>
>>>-- 
>>>Jani Nikula, Intel
>
>-- 
>Jani Nikula, Intel

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

* Re: [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-08  0:05 ` [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc Gustavo Sousa
@ 2025-11-11 16:02   ` Imre Deak
  2025-11-11 16:15     ` Imre Deak
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-11 16:02 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

On Fri, Nov 07, 2025 at 09:05:35PM -0300, Gustavo Sousa wrote:
> VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
> configuring SoC for TC ports and PHYs.  Update the code to match the
> updates in VBT.
> 
> The new field dedicated_external is used to represent TC ports that are
> connected to PHYs outside of the Type-C subsystem, meaning that they
> behave like dedicated ports and don't require the extra Type-C
> programming.  In an upcoming change, we will update the driver to take
> this field into consideration when detecting the type of port.
> 
> The new field dyn_port_over_tc is used to inform that the TC port can be
> dynamically allocated for a legacy connector in the Type-C subsystem,
> which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
> that field in order to handle the IOM resource management programming
> required for that.
> 
> Note that, when dedicated_external is set, the fields dp_usb_type_c and
> tbt are tagged as "don't care" in the spec, so they should be ignored in
> that case, so also add a sanitization function to take care of forcing
> them to zero when dedicated_external is true.
> 
> v2:
>   - Use sanitization function to force dp_usb_type_c and tbt fields to
>     be zero instead of adding a
>     intel_bios_encoder_is_dedicated_external() check in each of their
>     respective accessor functions. (Jani)
>   - Print info about dedicated external ports in print_ddi_port().
>     (Jani)
> 
> Bspec: 20124, 68954, 74304
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
>  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
>  3 files changed, 56 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 852e4d6db8a3..1487d5e5a69d 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
>  	return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
>  }
>  
> +static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
> +					enum port port)
> +{
> +	struct intel_display *display = devdata->display;
> +
> +	if (!intel_bios_encoder_is_dedicated_external(devdata))
> +		return;
> +
> +	/*
> +	 * Fields dp_usb_type_c and tbt must be ignored when
> +	 * dedicated_external is set.  Since dedicated_external is for
> +	 * ports connected to PHYs outside of the Type-C subsystem, it
> +	 * is safe to force those fields to zero.
> +	 */
> +
> +	if (devdata->child.dp_usb_type_c) {
> +		drm_dbg_kms(display->drm,
> +			    "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
> +			    port_name(port));
> +		devdata->child.dp_usb_type_c = 0;
> +	}
> +
> +	if (devdata->child.tbt) {
> +		drm_dbg_kms(display->drm,
> +			    "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
> +			    port_name(port));
> +		devdata->child.tbt = 0;
> +	}
> +}
> +
>  static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
>  				 enum port port)
>  {
> @@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>  {
>  	struct intel_display *display = devdata->display;
>  	const struct child_device_config *child = &devdata->child;
> -	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
> +	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
> +		supports_tbt, dedicated_external;
>  	int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
>  	enum port port;
>  
> @@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>  		    supports_typec_usb, supports_tbt,
>  		    devdata->dsc != NULL);
>  
> +	dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
> +	if (dedicated_external)

Nit: the variable could be dropped imo, and would be good to print the
dyn_port_over_tc info as well. Either way:

Reviewed-by: Imre Deak <imre.deak@intel.com>

> +		drm_dbg_kms(display->drm,
> +			    "Port %c is dedicated external\n",
> +			    port_name(port));
> +
>  	hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
>  	if (hdmi_level_shift >= 0) {
>  		drm_dbg_kms(display->drm,
> @@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
>  		return;
>  	}
>  
> +	sanitize_dedicated_external(devdata, port);
>  	sanitize_device_type(devdata, port);
>  	sanitize_hdmi_level_shift(devdata, port);
>  }
> @@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
>  {
>  	BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
>  
> -	if (version > 263)
> +	if (version > 264)
>  		return -ENOENT;
>  	else if (version >= 263)
>  		return 44;
> @@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
>  	return devdata->display->vbt.version >= 209 && devdata->child.tbt;
>  }
>  
> +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
> +{
> +	return devdata->display->vbt.version >= 264 &&
> +		devdata->child.dedicated_external;
> +}
> +
> +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
> +{
> +	return devdata->display->vbt.version >= 264 &&
> +		devdata->child.dyn_port_over_tc;
> +}
> +
>  bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
>  {
>  	return devdata && devdata->child.lane_reversal;
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> index f9e438b2787b..75dff27b4228 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.h
> +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> @@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
>  bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
>  bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
>  bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
> +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
> +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
>  bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
>  bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
>  bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
> diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> index 70e31520c560..57fda5824c9c 100644
> --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> @@ -554,7 +554,8 @@ struct child_device_config {
>  	u8 dvo_function;
>  	u8 dp_usb_type_c:1;					/* 195+ */
>  	u8 tbt:1;						/* 209+ */
> -	u8 flags2_reserved:2;					/* 195+ */
> +	u8 dedicated_external:1;				/* 264+ */
> +	u8 dyn_port_over_tc:1;					/* 264+ */
>  	u8 dp_port_trace_length:4;				/* 209+ */
>  	u8 dp_gpio_index;					/* 195+ */
>  	u16 dp_gpio_pin_num;					/* 195+ */
> 
> -- 
> 2.51.0
> 

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

* Re: [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-11 16:02   ` Imre Deak
@ 2025-11-11 16:15     ` Imre Deak
  2025-11-12 13:00       ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-11 16:15 UTC (permalink / raw)
  To: Gustavo Sousa, intel-xe, intel-gfx, Ankit Nautiyal,
	Dnyaneshwar Bhadane, Jouni Högander, Juha-pekka Heikkila,
	Luca Coelho, Lucas De Marchi, Matt Atwood, Matt Roper,
	Ravi Kumar Vodapalli, Shekhar Chauhan, Vinod Govindapillai,
	Jani Nikula

On Tue, Nov 11, 2025 at 06:02:31PM +0200, Imre Deak wrote:
> On Fri, Nov 07, 2025 at 09:05:35PM -0300, Gustavo Sousa wrote:
> > VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
> > configuring SoC for TC ports and PHYs.  Update the code to match the
> > updates in VBT.
> > 
> > The new field dedicated_external is used to represent TC ports that are
> > connected to PHYs outside of the Type-C subsystem, meaning that they
> > behave like dedicated ports and don't require the extra Type-C
> > programming.  In an upcoming change, we will update the driver to take
> > this field into consideration when detecting the type of port.
> > 
> > The new field dyn_port_over_tc is used to inform that the TC port can be
> > dynamically allocated for a legacy connector in the Type-C subsystem,
> > which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
> > that field in order to handle the IOM resource management programming
> > required for that.
> > 
> > Note that, when dedicated_external is set, the fields dp_usb_type_c and
> > tbt are tagged as "don't care" in the spec, so they should be ignored in
> > that case, so also add a sanitization function to take care of forcing
> > them to zero when dedicated_external is true.
> > 
> > v2:
> >   - Use sanitization function to force dp_usb_type_c and tbt fields to
> >     be zero instead of adding a
> >     intel_bios_encoder_is_dedicated_external() check in each of their
> >     respective accessor functions. (Jani)
> >   - Print info about dedicated external ports in print_ddi_port().
> >     (Jani)
> > 
> > Bspec: 20124, 68954, 74304
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
> >  drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
> >  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
> >  3 files changed, 56 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 852e4d6db8a3..1487d5e5a69d 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
> >  	return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
> >  }
> >  
> > +static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
> > +					enum port port)
> > +{
> > +	struct intel_display *display = devdata->display;
> > +
> > +	if (!intel_bios_encoder_is_dedicated_external(devdata))
> > +		return;
> > +
> > +	/*
> > +	 * Fields dp_usb_type_c and tbt must be ignored when
> > +	 * dedicated_external is set.  Since dedicated_external is for
> > +	 * ports connected to PHYs outside of the Type-C subsystem, it
> > +	 * is safe to force those fields to zero.
> > +	 */

Forgot this: IIUC dyn_port_over_tc doesn't make either sense for a
dedicated external port. IOW, a dedicated port/PHY is not enabled by the
TypeC sequences defined at bspec/68954 and so for such a port/PHY the
DDI->PHY mapping is always 1:1 and so the corresponding DDI can't either
be dynamically allocated to different PHYs. If that's a correct
understanding, dyn_port_over_tc should be also verified/zeroed out here
imo.

> > +
> > +	if (devdata->child.dp_usb_type_c) {
> > +		drm_dbg_kms(display->drm,
> > +			    "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
> > +			    port_name(port));
> > +		devdata->child.dp_usb_type_c = 0;
> > +	}
> > +
> > +	if (devdata->child.tbt) {
> > +		drm_dbg_kms(display->drm,
> > +			    "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
> > +			    port_name(port));
> > +		devdata->child.tbt = 0;
> > +	}
> > +}
> > +
> >  static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
> >  				 enum port port)
> >  {
> > @@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
> >  {
> >  	struct intel_display *display = devdata->display;
> >  	const struct child_device_config *child = &devdata->child;
> > -	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
> > +	bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
> > +		supports_tbt, dedicated_external;
> >  	int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
> >  	enum port port;
> >  
> > @@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
> >  		    supports_typec_usb, supports_tbt,
> >  		    devdata->dsc != NULL);
> >  
> > +	dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
> > +	if (dedicated_external)
> 
> Nit: the variable could be dropped imo, and would be good to print the
> dyn_port_over_tc info as well. Either way:
> 
> Reviewed-by: Imre Deak <imre.deak@intel.com>
> 
> > +		drm_dbg_kms(display->drm,
> > +			    "Port %c is dedicated external\n",
> > +			    port_name(port));
> > +
> >  	hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
> >  	if (hdmi_level_shift >= 0) {
> >  		drm_dbg_kms(display->drm,
> > @@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
> >  		return;
> >  	}
> >  
> > +	sanitize_dedicated_external(devdata, port);
> >  	sanitize_device_type(devdata, port);
> >  	sanitize_hdmi_level_shift(devdata, port);
> >  }
> > @@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
> >  {
> >  	BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
> >  
> > -	if (version > 263)
> > +	if (version > 264)
> >  		return -ENOENT;
> >  	else if (version >= 263)
> >  		return 44;
> > @@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
> >  	return devdata->display->vbt.version >= 209 && devdata->child.tbt;
> >  }
> >  
> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
> > +{
> > +	return devdata->display->vbt.version >= 264 &&
> > +		devdata->child.dedicated_external;
> > +}
> > +
> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
> > +{
> > +	return devdata->display->vbt.version >= 264 &&
> > +		devdata->child.dyn_port_over_tc;
> > +}
> > +
> >  bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
> >  {
> >  	return devdata && devdata->child.lane_reversal;
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> > index f9e438b2787b..75dff27b4228 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> > @@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
> >  bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
> >  bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
> >  bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
> >  bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
> >  bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
> >  bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
> > diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > index 70e31520c560..57fda5824c9c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > @@ -554,7 +554,8 @@ struct child_device_config {
> >  	u8 dvo_function;
> >  	u8 dp_usb_type_c:1;					/* 195+ */
> >  	u8 tbt:1;						/* 209+ */
> > -	u8 flags2_reserved:2;					/* 195+ */
> > +	u8 dedicated_external:1;				/* 264+ */
> > +	u8 dyn_port_over_tc:1;					/* 264+ */
> >  	u8 dp_port_trace_length:4;				/* 209+ */
> >  	u8 dp_gpio_index;					/* 195+ */
> >  	u16 dp_gpio_pin_num;					/* 195+ */
> > 
> > -- 
> > 2.51.0
> > 

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

* RE: [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward
  2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
@ 2025-11-12  3:46   ` Kandpal, Suraj
  2025-11-12 12:45     ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Kandpal, Suraj @ 2025-11-12  3:46 UTC (permalink / raw)
  To: Sousa, Gustavo, intel-xe@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org
  Cc: Nautiyal, Ankit K, Bhadane, Dnyaneshwar, Sousa, Gustavo,
	Hogander, Jouni, Heikkila, Juha-pekka, Coelho, Luciano,
	De Marchi, Lucas, Atwood, Matthew S, Roper, Matthew D,
	Vodapalli, Ravi Kumar, Chauhan, Shekhar, Govindapillai, Vinod,
	Ville Syrjälä

> Subject: [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic
> on Xe3 onward
> 
> The Windows driver is rejecting non-monotonic ranges latency values for Xe3.
> Let's make sure that we do not call make_wm_latency_monotonic() for Xe3 and
> beyond.

Idt saying we are doing It because Windows driver is doing it is the correct reason to do this.
This may very well be needed but I think its better to add the right reason here.
Also Bspec no. at trailer if available.

Rest looks good to me

Regards,
Suraj Kandpal

> 
> Also, because of that, let's add a check at the end of
> adjust_wm_latency() to ensure we raise a warning if the final list of latency values
> is not monotonic.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
>  drivers/gpu/drm/i915/display/skl_watermark.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c
> b/drivers/gpu/drm/i915/display/skl_watermark.c
> index 36a266f882d1..ed55fe84e930 100644
> --- a/drivers/gpu/drm/i915/display/skl_watermark.c
> +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
> @@ -3218,6 +3218,18 @@ static void make_wm_latency_monotonic(struct
> intel_display *display)
>  	}
>  }
> 
> +static bool is_wm_latency_monotonic(struct intel_display *display) {
> +	u16 *wm = display->wm.skl_latency;
> +	int level, num_levels = display->wm.num_levels;
> +
> +	for (level = 1; level < num_levels; level++)
> +		if (wm[level] < wm[level - 1])
> +			return false;
> +
> +	return true;
> +}
> +
>  static void
>  adjust_wm_latency(struct intel_display *display)  { @@ -3228,7 +3240,8 @@
> adjust_wm_latency(struct intel_display *display)
> 
>  	sanitize_wm_latency(display);
> 
> -	make_wm_latency_monotonic(display);
> +	if (DISPLAY_VER(display) < 30)
> +		make_wm_latency_monotonic(display);
> 
>  	/*
>  	 * WaWmMemoryReadLatency
> @@ -3248,6 +3261,8 @@ adjust_wm_latency(struct intel_display *display)
>  	 */
>  	if (need_16gb_dimm_wa(display))
>  		increase_wm_latency(display, 1);
> +
> +	drm_WARN_ON(display->drm, !is_wm_latency_monotonic(display));
>  }
> 
>  static void mtl_read_wm_latency(struct intel_display *display)
> 
> --
> 2.51.0


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

* RE: [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward
  2025-11-12  3:46   ` Kandpal, Suraj
@ 2025-11-12 12:45     ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-12 12:45 UTC (permalink / raw)
  To: Kandpal, Suraj, Ville Syrjälä,
	intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
  Cc: Nautiyal, Ankit K, Bhadane, Dnyaneshwar, Hogander, Jouni,
	Heikkila, Juha-pekka, Coelho, Luciano, De Marchi, Lucas,
	Atwood, Matthew S, Roper, Matthew D, Vodapalli, Ravi Kumar,
	Chauhan, Shekhar, Govindapillai, Vinod

Quoting Kandpal, Suraj (2025-11-12 00:46:59-03:00)
>> Subject: [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic
>> on Xe3 onward
>> 
>> The Windows driver is rejecting non-monotonic ranges latency values for Xe3.
>> Let's make sure that we do not call make_wm_latency_monotonic() for Xe3 and
>> beyond.
>
>Idt saying we are doing It because Windows driver is doing it is the correct reason to do this.
>This may very well be needed but I think its better to add the right reason here.

Yeah, that's fair.  Maybe Ville can provide more details here.

Also note that there is some discussion[1] on v3 of the series (v4 was
posted here because of an imminent unavailability of my part).

[1] https://lore.kernel.org/all/176255963559.2001.856665786291066518@intel.com/

>Also Bspec no. at trailer if available.

I am not sure there is a good Bspec number to refer to here. :-\

>
>Rest looks good to me

Thanks!

--
Gustavo Sousa

>
>Regards,
>Suraj Kandpal
>
>> 
>> Also, because of that, let's add a check at the end of
>> adjust_wm_latency() to ensure we raise a warning if the final list of latency values
>> is not monotonic.
>> 
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>>  drivers/gpu/drm/i915/display/skl_watermark.c | 17 ++++++++++++++++-
>>  1 file changed, 16 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c
>> b/drivers/gpu/drm/i915/display/skl_watermark.c
>> index 36a266f882d1..ed55fe84e930 100644
>> --- a/drivers/gpu/drm/i915/display/skl_watermark.c
>> +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
>> @@ -3218,6 +3218,18 @@ static void make_wm_latency_monotonic(struct
>> intel_display *display)
>>          }
>>  }
>> 
>> +static bool is_wm_latency_monotonic(struct intel_display *display) {
>> +        u16 *wm = display->wm.skl_latency;
>> +        int level, num_levels = display->wm.num_levels;
>> +
>> +        for (level = 1; level < num_levels; level++)
>> +                if (wm[level] < wm[level - 1])
>> +                        return false;
>> +
>> +        return true;
>> +}
>> +
>>  static void
>>  adjust_wm_latency(struct intel_display *display)  { @@ -3228,7 +3240,8 @@
>> adjust_wm_latency(struct intel_display *display)
>> 
>>          sanitize_wm_latency(display);
>> 
>> -        make_wm_latency_monotonic(display);
>> +        if (DISPLAY_VER(display) < 30)
>> +                make_wm_latency_monotonic(display);
>> 
>>          /*
>>           * WaWmMemoryReadLatency
>> @@ -3248,6 +3261,8 @@ adjust_wm_latency(struct intel_display *display)
>>           */
>>          if (need_16gb_dimm_wa(display))
>>                  increase_wm_latency(display, 1);
>> +
>> +        drm_WARN_ON(display->drm, !is_wm_latency_monotonic(display));
>>  }
>> 
>>  static void mtl_read_wm_latency(struct intel_display *display)
>> 
>> --
>> 2.51.0
>

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

* Re: [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-11 16:15     ` Imre Deak
@ 2025-11-12 13:00       ` Gustavo Sousa
  2025-11-12 13:20         ` Imre Deak
  0 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-12 13:00 UTC (permalink / raw)
  To: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Imre Deak, Jani Nikula, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, intel-gfx, intel-xe

Quoting Imre Deak (2025-11-11 13:15:41-03:00)
>On Tue, Nov 11, 2025 at 06:02:31PM +0200, Imre Deak wrote:
>> On Fri, Nov 07, 2025 at 09:05:35PM -0300, Gustavo Sousa wrote:
>> > VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
>> > configuring SoC for TC ports and PHYs.  Update the code to match the
>> > updates in VBT.
>> > 
>> > The new field dedicated_external is used to represent TC ports that are
>> > connected to PHYs outside of the Type-C subsystem, meaning that they
>> > behave like dedicated ports and don't require the extra Type-C
>> > programming.  In an upcoming change, we will update the driver to take
>> > this field into consideration when detecting the type of port.
>> > 
>> > The new field dyn_port_over_tc is used to inform that the TC port can be
>> > dynamically allocated for a legacy connector in the Type-C subsystem,
>> > which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
>> > that field in order to handle the IOM resource management programming
>> > required for that.
>> > 
>> > Note that, when dedicated_external is set, the fields dp_usb_type_c and
>> > tbt are tagged as "don't care" in the spec, so they should be ignored in
>> > that case, so also add a sanitization function to take care of forcing
>> > them to zero when dedicated_external is true.
>> > 
>> > v2:
>> >   - Use sanitization function to force dp_usb_type_c and tbt fields to
>> >     be zero instead of adding a
>> >     intel_bios_encoder_is_dedicated_external() check in each of their
>> >     respective accessor functions. (Jani)
>> >   - Print info about dedicated external ports in print_ddi_port().
>> >     (Jani)
>> > 
>> > Bspec: 20124, 68954, 74304
>> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> > Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
>> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
>> >  drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
>> >  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
>> >  3 files changed, 56 insertions(+), 3 deletions(-)
>> > 
>> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
>> > index 852e4d6db8a3..1487d5e5a69d 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
>> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
>> > @@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
>> >          return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
>> >  }
>> >  
>> > +static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
>> > +                                        enum port port)
>> > +{
>> > +        struct intel_display *display = devdata->display;
>> > +
>> > +        if (!intel_bios_encoder_is_dedicated_external(devdata))
>> > +                return;
>> > +
>> > +        /*
>> > +         * Fields dp_usb_type_c and tbt must be ignored when
>> > +         * dedicated_external is set.  Since dedicated_external is for
>> > +         * ports connected to PHYs outside of the Type-C subsystem, it
>> > +         * is safe to force those fields to zero.
>> > +         */
>
>Forgot this: IIUC dyn_port_over_tc doesn't make either sense for a
>dedicated external port. IOW, a dedicated port/PHY is not enabled by the
>TypeC sequences defined at bspec/68954 and so for such a port/PHY the
>DDI->PHY mapping is always 1:1 and so the corresponding DDI can't either
>be dynamically allocated to different PHYs. If that's a correct
>understanding, dyn_port_over_tc should be also verified/zeroed out here
>imo.

Yep, there shouldn't be any need for DDI allocation for dedicated
external ports.  However, we would only be checking for dyn_port_over_tc
when doing the Type-C flows, which would not happen for a dedicated
external port.  Give that, do you think we need to add the extra check
here?

The main reason we are adding those checks below is because the VBT spec
marks those bits as "don't care" when dedicated_external is set.

--
Gustavo Sousa

>
>> > +
>> > +        if (devdata->child.dp_usb_type_c) {
>> > +                drm_dbg_kms(display->drm,
>> > +                            "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
>> > +                            port_name(port));
>> > +                devdata->child.dp_usb_type_c = 0;
>> > +        }
>> > +
>> > +        if (devdata->child.tbt) {
>> > +                drm_dbg_kms(display->drm,
>> > +                            "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
>> > +                            port_name(port));
>> > +                devdata->child.tbt = 0;
>> > +        }
>> > +}
>> > +
>> >  static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
>> >                                   enum port port)
>> >  {
>> > @@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>> >  {
>> >          struct intel_display *display = devdata->display;
>> >          const struct child_device_config *child = &devdata->child;
>> > -        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
>> > +        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
>> > +                supports_tbt, dedicated_external;
>> >          int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
>> >          enum port port;
>> >  
>> > @@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>> >                      supports_typec_usb, supports_tbt,
>> >                      devdata->dsc != NULL);
>> >  
>> > +        dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
>> > +        if (dedicated_external)
>> 
>> Nit: the variable could be dropped imo, and would be good to print the
>> dyn_port_over_tc info as well. Either way:
>> 
>> Reviewed-by: Imre Deak <imre.deak@intel.com>
>> 
>> > +                drm_dbg_kms(display->drm,
>> > +                            "Port %c is dedicated external\n",
>> > +                            port_name(port));
>> > +
>> >          hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
>> >          if (hdmi_level_shift >= 0) {
>> >                  drm_dbg_kms(display->drm,
>> > @@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
>> >                  return;
>> >          }
>> >  
>> > +        sanitize_dedicated_external(devdata, port);
>> >          sanitize_device_type(devdata, port);
>> >          sanitize_hdmi_level_shift(devdata, port);
>> >  }
>> > @@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
>> >  {
>> >          BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
>> >  
>> > -        if (version > 263)
>> > +        if (version > 264)
>> >                  return -ENOENT;
>> >          else if (version >= 263)
>> >                  return 44;
>> > @@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
>> >          return devdata->display->vbt.version >= 209 && devdata->child.tbt;
>> >  }
>> >  
>> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
>> > +{
>> > +        return devdata->display->vbt.version >= 264 &&
>> > +                devdata->child.dedicated_external;
>> > +}
>> > +
>> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
>> > +{
>> > +        return devdata->display->vbt.version >= 264 &&
>> > +                devdata->child.dyn_port_over_tc;
>> > +}
>> > +
>> >  bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
>> >  {
>> >          return devdata && devdata->child.lane_reversal;
>> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
>> > index f9e438b2787b..75dff27b4228 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
>> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
>> > @@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
>> >  bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
>> >  bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
>> >  bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
>> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
>> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
>> >  bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
>> >  bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
>> >  bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
>> > diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> > index 70e31520c560..57fda5824c9c 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> > +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> > @@ -554,7 +554,8 @@ struct child_device_config {
>> >          u8 dvo_function;
>> >          u8 dp_usb_type_c:1;                                        /* 195+ */
>> >          u8 tbt:1;                                                /* 209+ */
>> > -        u8 flags2_reserved:2;                                        /* 195+ */
>> > +        u8 dedicated_external:1;                                /* 264+ */
>> > +        u8 dyn_port_over_tc:1;                                        /* 264+ */
>> >          u8 dp_port_trace_length:4;                                /* 209+ */
>> >          u8 dp_gpio_index;                                        /* 195+ */
>> >          u16 dp_gpio_pin_num;                                        /* 195+ */
>> > 
>> > -- 
>> > 2.51.0
>> >

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

* Re: [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-12 13:00       ` Gustavo Sousa
@ 2025-11-12 13:20         ` Imre Deak
  2025-11-13 22:01           ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-12 13:20 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jani Nikula, Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi,
	Matt Atwood, Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

On Wed, Nov 12, 2025 at 10:00:27AM -0300, Gustavo Sousa wrote:
> Quoting Imre Deak (2025-11-11 13:15:41-03:00)
> >On Tue, Nov 11, 2025 at 06:02:31PM +0200, Imre Deak wrote:
> >> On Fri, Nov 07, 2025 at 09:05:35PM -0300, Gustavo Sousa wrote:
> >> > VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
> >> > configuring SoC for TC ports and PHYs.  Update the code to match the
> >> > updates in VBT.
> >> > 
> >> > The new field dedicated_external is used to represent TC ports that are
> >> > connected to PHYs outside of the Type-C subsystem, meaning that they
> >> > behave like dedicated ports and don't require the extra Type-C
> >> > programming.  In an upcoming change, we will update the driver to take
> >> > this field into consideration when detecting the type of port.
> >> > 
> >> > The new field dyn_port_over_tc is used to inform that the TC port can be
> >> > dynamically allocated for a legacy connector in the Type-C subsystem,
> >> > which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
> >> > that field in order to handle the IOM resource management programming
> >> > required for that.
> >> > 
> >> > Note that, when dedicated_external is set, the fields dp_usb_type_c and
> >> > tbt are tagged as "don't care" in the spec, so they should be ignored in
> >> > that case, so also add a sanitization function to take care of forcing
> >> > them to zero when dedicated_external is true.
> >> > 
> >> > v2:
> >> >   - Use sanitization function to force dp_usb_type_c and tbt fields to
> >> >     be zero instead of adding a
> >> >     intel_bios_encoder_is_dedicated_external() check in each of their
> >> >     respective accessor functions. (Jani)
> >> >   - Print info about dedicated external ports in print_ddi_port().
> >> >     (Jani)
> >> > 
> >> > Bspec: 20124, 68954, 74304
> >> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> >> > Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
> >> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> >> > ---
> >> >  drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
> >> >  drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
> >> >  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
> >> >  3 files changed, 56 insertions(+), 3 deletions(-)
> >> > 
> >> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> >> > index 852e4d6db8a3..1487d5e5a69d 100644
> >> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> >> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> >> > @@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
> >> >          return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
> >> >  }
> >> >  
> >> > +static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
> >> > +                                        enum port port)
> >> > +{
> >> > +        struct intel_display *display = devdata->display;
> >> > +
> >> > +        if (!intel_bios_encoder_is_dedicated_external(devdata))
> >> > +                return;
> >> > +
> >> > +        /*
> >> > +         * Fields dp_usb_type_c and tbt must be ignored when
> >> > +         * dedicated_external is set.  Since dedicated_external is for
> >> > +         * ports connected to PHYs outside of the Type-C subsystem, it
> >> > +         * is safe to force those fields to zero.
> >> > +         */
> >
> >Forgot this: IIUC dyn_port_over_tc doesn't make either sense for a
> >dedicated external port. IOW, a dedicated port/PHY is not enabled by the
> >TypeC sequences defined at bspec/68954 and so for such a port/PHY the
> >DDI->PHY mapping is always 1:1 and so the corresponding DDI can't either
> >be dynamically allocated to different PHYs. If that's a correct
> >understanding, dyn_port_over_tc should be also verified/zeroed out here
> >imo.
> 
> Yep, there shouldn't be any need for DDI allocation for dedicated
> external ports.  However, we would only be checking for dyn_port_over_tc
> when doing the Type-C flows, which would not happen for a dedicated
> external port.  Give that, do you think we need to add the extra check
> here?
>
> The main reason we are adding those checks below is because the VBT spec
> marks those bits as "don't care" when dedicated_external is set.

Right. To me, the interdependencies of these flags in VBT are a bit
complex. We are reflecting now about the above dependency, which is
good, since we'll at least agree then how these flags are supposed to
work. Imo it should've been also documented more explicitly in Bspec,
similarly to the DP-alt and TBT "don't care" documentation.

With all that, at least a code comment would be good about this for a
future reader, but even the verify/zeroing would be useful imo, in case
there is a VBT setting the flags contrary to our assumptions (that would
remind us then to figure out if our or the VBT authors' assumptions were
wrong).

It's a detail only, I'm not insisting on either of the above, so up to
you (maybe you'd only update it in case you have to resend the patch
anyway or stg).

> --
> Gustavo Sousa
> 
> >
> >> > +
> >> > +        if (devdata->child.dp_usb_type_c) {
> >> > +                drm_dbg_kms(display->drm,
> >> > +                            "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
> >> > +                            port_name(port));
> >> > +                devdata->child.dp_usb_type_c = 0;
> >> > +        }
> >> > +
> >> > +        if (devdata->child.tbt) {
> >> > +                drm_dbg_kms(display->drm,
> >> > +                            "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
> >> > +                            port_name(port));
> >> > +                devdata->child.tbt = 0;
> >> > +        }
> >> > +}
> >> > +
> >> >  static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
> >> >                                   enum port port)
> >> >  {
> >> > @@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
> >> >  {
> >> >          struct intel_display *display = devdata->display;
> >> >          const struct child_device_config *child = &devdata->child;
> >> > -        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
> >> > +        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
> >> > +                supports_tbt, dedicated_external;
> >> >          int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
> >> >          enum port port;
> >> >  
> >> > @@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
> >> >                      supports_typec_usb, supports_tbt,
> >> >                      devdata->dsc != NULL);
> >> >  
> >> > +        dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
> >> > +        if (dedicated_external)
> >> 
> >> Nit: the variable could be dropped imo, and would be good to print the
> >> dyn_port_over_tc info as well. Either way:
> >> 
> >> Reviewed-by: Imre Deak <imre.deak@intel.com>
> >> 
> >> > +                drm_dbg_kms(display->drm,
> >> > +                            "Port %c is dedicated external\n",
> >> > +                            port_name(port));
> >> > +
> >> >          hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
> >> >          if (hdmi_level_shift >= 0) {
> >> >                  drm_dbg_kms(display->drm,
> >> > @@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
> >> >                  return;
> >> >          }
> >> >  
> >> > +        sanitize_dedicated_external(devdata, port);
> >> >          sanitize_device_type(devdata, port);
> >> >          sanitize_hdmi_level_shift(devdata, port);
> >> >  }
> >> > @@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
> >> >  {
> >> >          BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
> >> >  
> >> > -        if (version > 263)
> >> > +        if (version > 264)
> >> >                  return -ENOENT;
> >> >          else if (version >= 263)
> >> >                  return 44;
> >> > @@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
> >> >          return devdata->display->vbt.version >= 209 && devdata->child.tbt;
> >> >  }
> >> >  
> >> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
> >> > +{
> >> > +        return devdata->display->vbt.version >= 264 &&
> >> > +                devdata->child.dedicated_external;
> >> > +}
> >> > +
> >> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
> >> > +{
> >> > +        return devdata->display->vbt.version >= 264 &&
> >> > +                devdata->child.dyn_port_over_tc;
> >> > +}
> >> > +
> >> >  bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
> >> >  {
> >> >          return devdata && devdata->child.lane_reversal;
> >> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> >> > index f9e438b2787b..75dff27b4228 100644
> >> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
> >> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> >> > @@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
> >> >  bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
> >> >  bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
> >> >  bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
> >> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
> >> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
> >> >  bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
> >> >  bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
> >> >  bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
> >> > diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> >> > index 70e31520c560..57fda5824c9c 100644
> >> > --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> >> > +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> >> > @@ -554,7 +554,8 @@ struct child_device_config {
> >> >          u8 dvo_function;
> >> >          u8 dp_usb_type_c:1;                                        /* 195+ */
> >> >          u8 tbt:1;                                                /* 209+ */
> >> > -        u8 flags2_reserved:2;                                        /* 195+ */
> >> > +        u8 dedicated_external:1;                                /* 264+ */
> >> > +        u8 dyn_port_over_tc:1;                                        /* 264+ */
> >> >          u8 dp_port_trace_length:4;                                /* 209+ */
> >> >          u8 dp_gpio_index;                                        /* 195+ */
> >> >          u16 dp_gpio_pin_num;                                        /* 195+ */
> >> > 
> >> > -- 
> >> > 2.51.0
> >> >

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

* Re: [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc()
  2025-11-08  0:05 ` [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc() Gustavo Sousa
@ 2025-11-12 16:19   ` Imre Deak
  2025-11-13 22:01     ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-12 16:19 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

On Fri, Nov 07, 2025 at 09:05:36PM -0300, Gustavo Sousa wrote:
> Starting with Xe3p_LPD, when intel_phy_is_tc() returns true, it does
> not necessarily mean that the port is connected to a PHY in the Type-C
> subsystem.  The reason is that there is now a VBT field called
> dedicated_external that will indicate that a Type-C capable port is
> connected to a (most likely) combo/dedicated PHY.  When that's the case,
> we must not do the extra programming required for Type-C connections.
> 
> In an upcoming change, we will modify intel_encoder_is_tc() to take the
> VBT field dedicated_external into consideration.  Update
> intel_display_power_well.c to use that function instead of
> intel_phy_is_tc().
> 
> Note that, even though icl_aux_power_well_{enable,disable} are not part
> of Xe3p_LPD's display paths, we modify them anyway for uniformity.
> 
> Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
> Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
>  .../drm/i915/display/intel_display_power_well.c    | 26 +++++++++++++++-------
>  1 file changed, 18 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
> index eab7019f2252..1485fc65ab87 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
> @@ -258,8 +258,9 @@ aux_ch_to_digital_port(struct intel_display *display,
>  	return NULL;
>  }
>  
> -static enum phy icl_aux_pw_to_phy(struct intel_display *display,
> -				  const struct i915_power_well *power_well)
> +static struct intel_encoder *
> +icl_aux_pw_to_encoder(struct intel_display *display,
> +		      const struct i915_power_well *power_well)
>  {
>  	enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
>  	struct intel_digital_port *dig_port = aux_ch_to_digital_port(display, aux_ch);
> @@ -271,7 +272,15 @@ static enum phy icl_aux_pw_to_phy(struct intel_display *display,
>  	 * as HDMI-only and routed to a combo PHY, the encoder either won't be
>  	 * present at all or it will not have an aux_ch assigned.
>  	 */
> -	return dig_port ? intel_encoder_to_phy(&dig_port->base) : PHY_NONE;
> +	return dig_port ? &dig_port->base : NULL;
> +}
> +
> +static enum phy icl_aux_pw_to_phy(struct intel_display *display,
> +				  const struct i915_power_well *power_well)
> +{
> +	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
> +
> +	return encoder ? intel_encoder_to_phy(encoder) : PHY_NONE;
>  }
>  
>  static void hsw_wait_for_power_well_enable(struct intel_display *display,
> @@ -570,9 +579,9 @@ static void
>  icl_aux_power_well_enable(struct intel_display *display,
>  			  struct i915_power_well *power_well)
>  {
> -	enum phy phy = icl_aux_pw_to_phy(display, power_well);
> +	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>  
> -	if (intel_phy_is_tc(display, phy))
> +	if (encoder && intel_encoder_is_tc(encoder))

Adding an icl_aux_pw_is_tc_phy(display, power_well) helper would
simplify things avoiding the need to retrieve the encoder.

>  		return icl_tc_phy_aux_power_well_enable(display, power_well);
>  	else if (display->platform.icelake)
>  		return icl_combo_phy_aux_power_well_enable(display,
> @@ -585,9 +594,9 @@ static void
>  icl_aux_power_well_disable(struct intel_display *display,
>  			   struct i915_power_well *power_well)
>  {
> -	enum phy phy = icl_aux_pw_to_phy(display, power_well);
> +	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>  
> -	if (intel_phy_is_tc(display, phy))
> +	if (encoder && intel_encoder_is_tc(encoder))
>  		return hsw_power_well_disable(display, power_well);
>  	else if (display->platform.icelake)
>  		return icl_combo_phy_aux_power_well_disable(display,
> @@ -1849,10 +1858,11 @@ tgl_tc_cold_off_power_well_is_enabled(struct intel_display *display,
>  static void xelpdp_aux_power_well_enable(struct intel_display *display,
>  					 struct i915_power_well *power_well)
>  {
> +	struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>  	enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
>  	enum phy phy = icl_aux_pw_to_phy(display, power_well);
>  
> -	if (intel_phy_is_tc(display, phy))
> +	if (encoder && intel_encoder_is_tc(encoder))
>  		icl_tc_port_assert_ref_held(display, power_well,
>  					    aux_ch_to_digital_port(display, aux_ch));
>  
> 
> -- 
> 2.51.0
> 

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

* Re: [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
  2025-11-08  0:05 ` [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc() Gustavo Sousa
@ 2025-11-12 16:24   ` Imre Deak
  2025-11-13 22:02     ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-12 16:24 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

On Fri, Nov 07, 2025 at 09:05:37PM -0300, Gustavo Sousa wrote:
> Starting with Xe3p_LPD, the VBT has a new field, called in the driver
> "dedicated_external", which tells that a Type-C capable port is
> physically connected to a PHY outside of the Type-C subsystem.  When
> that's the case, the driver must not do the extra Type-C programming for
> that port.  Update intel_encoder_is_tc() to check for that case.
> 
> While at it, add a note to intel_phy_is_tc() to remind us that it is
> about whether the respective port is a Type-C capable port rather than
> the PHY itself.
> 
> (Maybe it would be a nice idea to rename intel_phy_is_tc()?)
> 
> Note that this was handled with a new bool member added to struct
> intel_digital_port instead of having querying the VBT directly because
> VBT memory is freed (intel_bios_driver_remove) before encoder cleanup
> (intel_ddi_encoder_destroy), which would cause an oops to happen when
> the latter calls intel_encoder_is_tc().  This could be fixed by keeping
> VBT data around longer, but that's left for a follow-up work, if deemed
> necessary.
> 
> v2:
>   - Drop printing info about dedicated external, now that we are doing
>     it when parsing the VBT. (Jani)
>   - Add a FIXME comment on the code explaining why we need to store
>     dedicated_external in struct intel_digital_port. (Jani)
> 
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c           | 11 +++++++++++
>  drivers/gpu/drm/i915/display/intel_display.c       | 19 ++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_display_types.h |  1 +
>  3 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 733ef4559131..d9aaeafd1570 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -5376,6 +5376,17 @@ void intel_ddi_init(struct intel_display *display,
>  			goto err;
>  	}
>  
> +	/*
> +	 * FIXME: We currently need to store dedicated_external because devdata
> +	 * does not live long enough for when intel_encoder_is_tc() is called on
> +	 * the unbind path.  This needs to be fixed by making sure that the VBT
> +	 * data is kept long enough, so that
> +	 * intel_bios_encoder_is_dedicated_external() can be called directly
> +	 * from intel_encoder_is_tc().
> +	 */
> +	if (intel_bios_encoder_is_dedicated_external(devdata))
> +		dig_port->dedicated_external = true;
> +
>  	if (intel_encoder_is_tc(encoder)) {
>  		bool is_legacy =
>  			!intel_bios_encoder_supports_typec_usb(devdata) &&
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 25986bd8fbdd..431f7f030a9b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -1800,7 +1800,17 @@ bool intel_phy_is_combo(struct intel_display *display, enum phy phy)
>  		return false;
>  }
>  
> -/* Prefer intel_encoder_is_tc() */
> +/*
> + * This function returns true if the DDI port respective to the PHY enumeration
> + * is a Type-C capable port.
> + *
> + * Depending on the VBT, the port might be configured
> + * as a "dedicated external" port, meaning that actual physical PHY is outside
> + * of the Type-C subsystem and, as such, not really a "Type-C PHY".
> + *
> + * Prefer intel_encoder_is_tc(), especially if you really need to know if we
> + * are dealing with Type-C connections.
> + */
>  bool intel_phy_is_tc(struct intel_display *display, enum phy phy)
>  {
>  	/*
> @@ -1885,6 +1895,13 @@ bool intel_encoder_is_tc(struct intel_encoder *encoder)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
>  
> +	if (intel_encoder_is_dig_port(encoder)) {
> +		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

Just dig_port = enc_to_dig_port(encoder); ... if (dig_port &&
dig_port->dedicated_external) would be simpler and would be also more
consistent wrt. MST encoders.

> +
> +		if (dig_port->dedicated_external)
> +			return false;
> +	}
> +
>  	return intel_phy_is_tc(display, intel_encoder_to_phy(encoder));
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 00600134bda0..8bf392bc0d5d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1937,6 +1937,7 @@ struct intel_digital_port {
>  	bool lane_reversal;
>  	bool ddi_a_4_lanes;
>  	bool release_cl2_override;
> +	bool dedicated_external;
>  	u8 max_lanes;
>  	/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
>  	enum aux_ch aux_ch;
> 
> -- 
> 2.51.0
> 

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-08  0:05 ` [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation Gustavo Sousa
@ 2025-11-12 17:53   ` Imre Deak
  2025-11-14 19:46     ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-12 17:53 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
> the DDI (TC ones) port to drive a legacy connection on the Type-C
> subsystem.  This allows better resource utilization, because now there
> is no need to statically reserve ports for legacy connectors on the
> Type-C subsystem.
> 
> That said, our driver is not yet ready for the dynamic allocation.
> Thus, as an incremental step, let's add the logic containing the
> required programming sequence for the allocation, but, instead of
> selecting the first available port, we try so use the 1:1 mapping
> expected by the driver today.
> 
> Bspec: 68954
> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> ---
> 
> NOTE: This patch is still a WIP. There are some opens to resolve here.
> Nevertheless, I'm sending it here for early feedback.
> 
> For the HIP-index stuff, I have a local refactor started and need to
> finish it up and send it.
> 
> The other open is about concurrent calls to iom_dp_resource_lock().  It
> is likely that we need to have a software lock to prevent concurrent
> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
> ---
>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
>  2 files changed, 169 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 89ea0156ee06..0cf7d43ce210 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
>  #define   DP_PIN_ASSIGNMENT(idx, x)		((x) << ((idx) * 4))
>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
>  
> +/*
> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
> + * We need to consolidate the definitions.
> + */
> +#define HIP_INDEX_REG0				_MMIO(0x1010a0)
> +#define   HIP_168_INDEX_MASK			REG_GENMASK(3, 0)
> +#define   HIP_168_IOM_RES_MGMT			REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
> +
> +#define IOM_DP_HW_RESOURCE_SEMAPHORE		_MMIO(0x168038)
> +#define   IOM_DP_HW_SEMLOCK			REG_BIT(31)
> +#define   IOM_REQUESTOR_ID_MASK			REG_GENMASK(3, 0)
> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE	REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
> +
> +#define IOM_DP_RESOURCE_MNG			_MMIO(0x16802c)
> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)	((tc_port) * 4)
> +#define   IOM_DDI_CONSUMER_MASK(tc_port)	(0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
> +#define   IOM_DDI_CONSUMER(tc_port, x)		((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)	IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))

It would be simpler to define the above without the shift, i.e. as 8 +
tc_port.

> +
>  #define _TCSS_DDI_STATUS_1			0x161500
>  #define _TCSS_DDI_STATUS_2			0x161504
>  #define TCSS_DDI_STATUS(tc)			_MMIO(_PICK_EVEN(tc, \
> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
>  #define   MTL_TRDPRE_MASK		REG_GENMASK(7, 0)
>  
>  
> -
>  #endif /* __INTEL_DISPLAY_REGS_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
> index 7e17ca018748..3c333999bbe4 100644
> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> @@ -9,6 +9,7 @@
>  
>  #include "i915_reg.h"
>  #include "intel_atomic.h"
> +#include "intel_bios.h"
>  #include "intel_cx0_phy_regs.h"
>  #include "intel_ddi.h"
>  #include "intel_de.h"
> @@ -25,6 +26,9 @@
>  #include "intel_modeset_lock.h"
>  #include "intel_tc.h"
>  
> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US	10
> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US	10000

The above param names should make it clear how poll_timeout_us() uses
them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
retry_timeout), but probably even clearer to just drop the defines and
inline the values in the call.

> +
>  enum tc_port_mode {
>  	TC_PORT_DISCONNECTED,
>  	TC_PORT_TBT_ALT,
> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
>  	__tc_cold_unblock(tc, domain, tc_cold_wref);
>  }
>  
> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
> +{
> +	/*
> +	 * IOM resource management registers live in the 2nd 4KB page of IOM
> +	 * address space. So we need to configure HIP_INDEX_REG0 with the
> +	 * correct index.
> +	 *
> +	 * FIXME: We need to have this and dekel PHY implementation using a
> +	 * common abstraction to access registers on the HIP-indexed ranges, and
> +	 * this function would then be dropped.
> +	 */
> +	intel_de_rmw(display, HIP_INDEX_REG0,
> +		     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);

This matches what intel_dkl_phy.c does, that one also taking the
required lock around the access. At one point the intel_dkl_phy
file/interface could be renamed to intel_tc_reg or similar accordingly.

> +}
> +
> +/*
> + * FIXME: This function also needs to avoid concurrent accesses from the driver
> + * itself, possibly via a software lock.
> + */
> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +	u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
> +	int ret;
> +
> +	iom_res_mgmt_prepare_reg_access(display);
> +	ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
> +			      (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,

This happens to work, but it's more future proof/bspec conformant to
properly mask the requestor ID field when reading it back.

> +			      IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
> +			      IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
> +
> +	if (ret)
> +		drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
> +			tc->port_name);
> +
> +	return ret;
> +}
> +
> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +
> +	iom_res_mgmt_prepare_reg_access(display);
> +	intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
> +}
> +
> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
> +{
> +	struct intel_display *display = to_intel_display(tc->dig_port);
> +	struct intel_digital_port *dig_port = tc->dig_port;
> +	enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
> +	u32 val;
> +	u32 consumer;
> +	u32 expected_consumer;
> +	bool ret;
> +
> +	if (DISPLAY_VER(display) < 35)
> +		return true;
> +
> +	if (tc->mode != TC_PORT_LEGACY)
> +		return true;
> +
> +	if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))

dedicated_external is stored separately in dig_port, why the "related"
dyn_port_over_tc flag isn't?

> +		return true;
> +
> +	if (iom_dp_resource_lock(tc))
> +		return false;
> +
> +	val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> +
> +	consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> +	consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> +
> +	/*
> +	 * Bspec instructs to select first available DDI, but our driver is not
> +	 * ready for such dynamic allocation yet. For now, we force a "static"
> +	 * allocation: map the physical port (where HPD happens) to the
> +	 * encoder's DDI (logical TC port, represented by tc_port).
> +	 */
> +	expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> +	expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> +
> +	if (allocate) {
> +		struct intel_encoder *other_encoder;
> +
> +		/*
> +		 * Check if this encoder's DDI is already allocated for another
> +		 * physical port, which could have happened prior to the driver
> +		 * taking over (e.g. GOP).
> +		 */
> +		for_each_intel_encoder(display->drm, other_encoder) {
> +			enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
> +			u32 other_consumer;
> +
> +			if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
> +				continue;
> +
> +			other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
> +			other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
> +			if (other_consumer == expected_consumer) {
> +				drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
> +					tc->port_name, expected_consumer, val);
> +				ret = false;
> +				goto out_resource_unlock;
> +			}
> +		}
> +
> +		if (consumer == 0) {
> +			/* DDI is free to use, let's allocate it. */
> +			val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> +			val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
> +			intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> +			ret = true;
> +		} else if (consumer == expected_consumer) {
> +			/*
> +			 * Nothing to do, as the expected "static" DDI allocation is
> +			 * already in place.
> +			 */
> +			ret = true;
> +		} else {
> +			drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
> +				tc->port_name, consumer, val);
> +			ret = false;
> +		}
> +	} else {
> +		drm_WARN_ON(display->drm, consumer != expected_consumer);
> +		val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> +		intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> +		ret = true;
> +	}
> +
> +out_resource_unlock:
> +	iom_dp_resource_unlock(tc);
> +
> +	return ret;
> +}
> +
>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  {
>  	tc->lock_wakeref = tc_cold_block(tc);
> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  		return true;
>  	}
>  
> -	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> +	if (!xe3p_tc_iom_allocate_ddi(tc, true))

This doesn't work. A connector registered to userspace must be always
functional (except for MST connectors which are dynamically registered).
So the DDI allocation and with that connecting the PHY cannot fail here
for a legacy connector/PHY. Instead of this the allocation could be
moved to happen already in intel_tc_phy_ops::init for now, allocating a
DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
fails also fail the corresponding connector/encoder registration in
intel_ddi_init(). The DDI would need to be released by
intel_tc_port_cleanup().

>  		goto out_unblock_tccold;
>  
> +	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> +		goto out_deallocate_ddi;
> +
>  	xelpdp_tc_phy_take_ownership(tc, true);
>  
>  	read_pin_configuration(tc);
> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>  	xelpdp_tc_phy_take_ownership(tc, false);
>  	xelpdp_tc_phy_wait_for_tcss_power(tc, false);
>  
> +out_deallocate_ddi:
> +	xe3p_tc_iom_allocate_ddi(tc, false);
> +
>  out_unblock_tccold:
>  	tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
>  
> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
>  {
>  	switch (tc->mode) {
>  	case TC_PORT_LEGACY:
> +		xe3p_tc_iom_allocate_ddi(tc, false);
> +		fallthrough;
>  	case TC_PORT_DP_ALT:
>  		xelpdp_tc_phy_take_ownership(tc, false);
>  		xelpdp_tc_phy_enable_tcss_power(tc, false);
> 
> -- 
> 2.51.0
> 

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

* Re: [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc
  2025-11-12 13:20         ` Imre Deak
@ 2025-11-13 22:01           ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-13 22:01 UTC (permalink / raw)
  To: Imre Deak
  Cc: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jani Nikula, Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi,
	Matt Atwood, Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

Quoting Imre Deak (2025-11-12 10:20:31-03:00)
>On Wed, Nov 12, 2025 at 10:00:27AM -0300, Gustavo Sousa wrote:
>> Quoting Imre Deak (2025-11-11 13:15:41-03:00)
>> >On Tue, Nov 11, 2025 at 06:02:31PM +0200, Imre Deak wrote:
>> >> On Fri, Nov 07, 2025 at 09:05:35PM -0300, Gustavo Sousa wrote:
>> >> > VBT version 264 adds new fields associated to Xe3p_LPD's new ways of
>> >> > configuring SoC for TC ports and PHYs.  Update the code to match the
>> >> > updates in VBT.
>> >> > 
>> >> > The new field dedicated_external is used to represent TC ports that are
>> >> > connected to PHYs outside of the Type-C subsystem, meaning that they
>> >> > behave like dedicated ports and don't require the extra Type-C
>> >> > programming.  In an upcoming change, we will update the driver to take
>> >> > this field into consideration when detecting the type of port.
>> >> > 
>> >> > The new field dyn_port_over_tc is used to inform that the TC port can be
>> >> > dynamically allocated for a legacy connector in the Type-C subsystem,
>> >> > which is a new feature in Xe3p_LPD.  In upcoming changes, we will use
>> >> > that field in order to handle the IOM resource management programming
>> >> > required for that.
>> >> > 
>> >> > Note that, when dedicated_external is set, the fields dp_usb_type_c and
>> >> > tbt are tagged as "don't care" in the spec, so they should be ignored in
>> >> > that case, so also add a sanitization function to take care of forcing
>> >> > them to zero when dedicated_external is true.
>> >> > 
>> >> > v2:
>> >> >   - Use sanitization function to force dp_usb_type_c and tbt fields to
>> >> >     be zero instead of adding a
>> >> >     intel_bios_encoder_is_dedicated_external() check in each of their
>> >> >     respective accessor functions. (Jani)
>> >> >   - Print info about dedicated external ports in print_ddi_port().
>> >> >     (Jani)
>> >> > 
>> >> > Bspec: 20124, 68954, 74304
>> >> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> >> > Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
>> >> > Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> >> > ---
>> >> >  drivers/gpu/drm/i915/display/intel_bios.c     | 54 ++++++++++++++++++++++++++-
>> >> >  drivers/gpu/drm/i915/display/intel_bios.h     |  2 +
>> >> >  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  3 +-
>> >> >  3 files changed, 56 insertions(+), 3 deletions(-)
>> >> > 
>> >> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
>> >> > index 852e4d6db8a3..1487d5e5a69d 100644
>> >> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
>> >> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
>> >> > @@ -2530,6 +2530,36 @@ intel_bios_encoder_reject_edp_rate(const struct intel_bios_encoder_data *devdata
>> >> >          return devdata->child.edp_data_rate_override & edp_rate_override_mask(rate);
>> >> >  }
>> >> >  
>> >> > +static void sanitize_dedicated_external(struct intel_bios_encoder_data *devdata,
>> >> > +                                        enum port port)
>> >> > +{
>> >> > +        struct intel_display *display = devdata->display;
>> >> > +
>> >> > +        if (!intel_bios_encoder_is_dedicated_external(devdata))
>> >> > +                return;
>> >> > +
>> >> > +        /*
>> >> > +         * Fields dp_usb_type_c and tbt must be ignored when
>> >> > +         * dedicated_external is set.  Since dedicated_external is for
>> >> > +         * ports connected to PHYs outside of the Type-C subsystem, it
>> >> > +         * is safe to force those fields to zero.
>> >> > +         */
>> >
>> >Forgot this: IIUC dyn_port_over_tc doesn't make either sense for a
>> >dedicated external port. IOW, a dedicated port/PHY is not enabled by the
>> >TypeC sequences defined at bspec/68954 and so for such a port/PHY the
>> >DDI->PHY mapping is always 1:1 and so the corresponding DDI can't either
>> >be dynamically allocated to different PHYs. If that's a correct
>> >understanding, dyn_port_over_tc should be also verified/zeroed out here
>> >imo.
>> 
>> Yep, there shouldn't be any need for DDI allocation for dedicated
>> external ports.  However, we would only be checking for dyn_port_over_tc
>> when doing the Type-C flows, which would not happen for a dedicated
>> external port.  Give that, do you think we need to add the extra check
>> here?
>>
>> The main reason we are adding those checks below is because the VBT spec
>> marks those bits as "don't care" when dedicated_external is set.
>
>Right. To me, the interdependencies of these flags in VBT are a bit
>complex. We are reflecting now about the above dependency, which is
>good, since we'll at least agree then how these flags are supposed to
>work. Imo it should've been also documented more explicitly in Bspec,
>similarly to the DP-alt and TBT "don't care" documentation.
>
>With all that, at least a code comment would be good about this for a
>future reader, but even the verify/zeroing would be useful imo, in case
>there is a VBT setting the flags contrary to our assumptions (that would
>remind us then to figure out if our or the VBT authors' assumptions were
>wrong).
>
>It's a detail only, I'm not insisting on either of the above, so up to
>you (maybe you'd only update it in case you have to resend the patch
>anyway or stg).

I'll have a new version of this series and I added the logic to zero out
dyn_port_over_tc as well.  Thanks!

>
>> --
>> Gustavo Sousa
>> 
>> >
>> >> > +
>> >> > +        if (devdata->child.dp_usb_type_c) {
>> >> > +                drm_dbg_kms(display->drm,
>> >> > +                            "VBT claims Port %c supports USB Type-C, but the port is dedicated external, ignoring\n",
>> >> > +                            port_name(port));
>> >> > +                devdata->child.dp_usb_type_c = 0;
>> >> > +        }
>> >> > +
>> >> > +        if (devdata->child.tbt) {
>> >> > +                drm_dbg_kms(display->drm,
>> >> > +                            "VBT claims Port %c supports TBT, but the port is dedicated external, ignoring\n",
>> >> > +                            port_name(port));
>> >> > +                devdata->child.tbt = 0;
>> >> > +        }
>> >> > +}
>> >> > +
>> >> >  static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
>> >> >                                   enum port port)
>> >> >  {
>> >> > @@ -2668,7 +2698,8 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>> >> >  {
>> >> >          struct intel_display *display = devdata->display;
>> >> >          const struct child_device_config *child = &devdata->child;
>> >> > -        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
>> >> > +        bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb,
>> >> > +                supports_tbt, dedicated_external;
>> >> >          int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
>> >> >          enum port port;
>> >> >  
>> >> > @@ -2694,6 +2725,12 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
>> >> >                      supports_typec_usb, supports_tbt,
>> >> >                      devdata->dsc != NULL);
>> >> >  
>> >> > +        dedicated_external = intel_bios_encoder_is_dedicated_external(devdata);
>> >> > +        if (dedicated_external)
>> >> 
>> >> Nit: the variable could be dropped imo, and would be good to print the
>> >> dyn_port_over_tc info as well. Either way:

Incorporated this into local v5.  Thanks!

--
Gustavo Sousa

>> >> 
>> >> Reviewed-by: Imre Deak <imre.deak@intel.com>
>> >> 
>> >> > +                drm_dbg_kms(display->drm,
>> >> > +                            "Port %c is dedicated external\n",
>> >> > +                            port_name(port));
>> >> > +
>> >> >          hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
>> >> >          if (hdmi_level_shift >= 0) {
>> >> >                  drm_dbg_kms(display->drm,
>> >> > @@ -2751,6 +2788,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
>> >> >                  return;
>> >> >          }
>> >> >  
>> >> > +        sanitize_dedicated_external(devdata, port);
>> >> >          sanitize_device_type(devdata, port);
>> >> >          sanitize_hdmi_level_shift(devdata, port);
>> >> >  }
>> >> > @@ -2778,7 +2816,7 @@ static int child_device_expected_size(u16 version)
>> >> >  {
>> >> >          BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
>> >> >  
>> >> > -        if (version > 263)
>> >> > +        if (version > 264)
>> >> >                  return -ENOENT;
>> >> >          else if (version >= 263)
>> >> >                  return 44;
>> >> > @@ -3723,6 +3761,18 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
>> >> >          return devdata->display->vbt.version >= 209 && devdata->child.tbt;
>> >> >  }
>> >> >  
>> >> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
>> >> > +{
>> >> > +        return devdata->display->vbt.version >= 264 &&
>> >> > +                devdata->child.dedicated_external;
>> >> > +}
>> >> > +
>> >> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata)
>> >> > +{
>> >> > +        return devdata->display->vbt.version >= 264 &&
>> >> > +                devdata->child.dyn_port_over_tc;
>> >> > +}
>> >> > +
>> >> >  bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
>> >> >  {
>> >> >          return devdata && devdata->child.lane_reversal;
>> >> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
>> >> > index f9e438b2787b..75dff27b4228 100644
>> >> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
>> >> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
>> >> > @@ -79,6 +79,8 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat
>> >> >  bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata);
>> >> >  bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata);
>> >> >  bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata);
>> >> > +bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata);
>> >> > +bool intel_bios_encoder_supports_dyn_port_over_tc(const struct intel_bios_encoder_data *devdata);
>> >> >  bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata);
>> >> >  bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata);
>> >> >  bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata);
>> >> > diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> >> > index 70e31520c560..57fda5824c9c 100644
>> >> > --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> >> > +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
>> >> > @@ -554,7 +554,8 @@ struct child_device_config {
>> >> >          u8 dvo_function;
>> >> >          u8 dp_usb_type_c:1;                                        /* 195+ */
>> >> >          u8 tbt:1;                                                /* 209+ */
>> >> > -        u8 flags2_reserved:2;                                        /* 195+ */
>> >> > +        u8 dedicated_external:1;                                /* 264+ */
>> >> > +        u8 dyn_port_over_tc:1;                                        /* 264+ */
>> >> >          u8 dp_port_trace_length:4;                                /* 209+ */
>> >> >          u8 dp_gpio_index;                                        /* 195+ */
>> >> >          u16 dp_gpio_pin_num;                                        /* 195+ */
>> >> > 
>> >> > -- 
>> >> > 2.51.0
>> >> >

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

* Re: [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc()
  2025-11-12 16:19   ` Imre Deak
@ 2025-11-13 22:01     ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-13 22:01 UTC (permalink / raw)
  To: Imre Deak
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Suraj Kandpal

Quoting Imre Deak (2025-11-12 13:19:07-03:00)
>On Fri, Nov 07, 2025 at 09:05:36PM -0300, Gustavo Sousa wrote:
>> Starting with Xe3p_LPD, when intel_phy_is_tc() returns true, it does
>> not necessarily mean that the port is connected to a PHY in the Type-C
>> subsystem.  The reason is that there is now a VBT field called
>> dedicated_external that will indicate that a Type-C capable port is
>> connected to a (most likely) combo/dedicated PHY.  When that's the case,
>> we must not do the extra programming required for Type-C connections.
>> 
>> In an upcoming change, we will modify intel_encoder_is_tc() to take the
>> VBT field dedicated_external into consideration.  Update
>> intel_display_power_well.c to use that function instead of
>> intel_phy_is_tc().
>> 
>> Note that, even though icl_aux_power_well_{enable,disable} are not part
>> of Xe3p_LPD's display paths, we modify them anyway for uniformity.
>> 
>> Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
>> Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>>  .../drm/i915/display/intel_display_power_well.c    | 26 +++++++++++++++-------
>>  1 file changed, 18 insertions(+), 8 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
>> index eab7019f2252..1485fc65ab87 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
>> @@ -258,8 +258,9 @@ aux_ch_to_digital_port(struct intel_display *display,
>>          return NULL;
>>  }
>>  
>> -static enum phy icl_aux_pw_to_phy(struct intel_display *display,
>> -                                  const struct i915_power_well *power_well)
>> +static struct intel_encoder *
>> +icl_aux_pw_to_encoder(struct intel_display *display,
>> +                      const struct i915_power_well *power_well)
>>  {
>>          enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
>>          struct intel_digital_port *dig_port = aux_ch_to_digital_port(display, aux_ch);
>> @@ -271,7 +272,15 @@ static enum phy icl_aux_pw_to_phy(struct intel_display *display,
>>           * as HDMI-only and routed to a combo PHY, the encoder either won't be
>>           * present at all or it will not have an aux_ch assigned.
>>           */
>> -        return dig_port ? intel_encoder_to_phy(&dig_port->base) : PHY_NONE;
>> +        return dig_port ? &dig_port->base : NULL;
>> +}
>> +
>> +static enum phy icl_aux_pw_to_phy(struct intel_display *display,
>> +                                  const struct i915_power_well *power_well)
>> +{
>> +        struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>> +
>> +        return encoder ? intel_encoder_to_phy(encoder) : PHY_NONE;
>>  }
>>  
>>  static void hsw_wait_for_power_well_enable(struct intel_display *display,
>> @@ -570,9 +579,9 @@ static void
>>  icl_aux_power_well_enable(struct intel_display *display,
>>                            struct i915_power_well *power_well)
>>  {
>> -        enum phy phy = icl_aux_pw_to_phy(display, power_well);
>> +        struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>>  
>> -        if (intel_phy_is_tc(display, phy))
>> +        if (encoder && intel_encoder_is_tc(encoder))
>
>Adding an icl_aux_pw_is_tc_phy(display, power_well) helper would
>simplify things avoiding the need to retrieve the encoder.

Ack.

--
Gustavo Sousa

>
>>                  return icl_tc_phy_aux_power_well_enable(display, power_well);
>>          else if (display->platform.icelake)
>>                  return icl_combo_phy_aux_power_well_enable(display,
>> @@ -585,9 +594,9 @@ static void
>>  icl_aux_power_well_disable(struct intel_display *display,
>>                             struct i915_power_well *power_well)
>>  {
>> -        enum phy phy = icl_aux_pw_to_phy(display, power_well);
>> +        struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>>  
>> -        if (intel_phy_is_tc(display, phy))
>> +        if (encoder && intel_encoder_is_tc(encoder))
>>                  return hsw_power_well_disable(display, power_well);
>>          else if (display->platform.icelake)
>>                  return icl_combo_phy_aux_power_well_disable(display,
>> @@ -1849,10 +1858,11 @@ tgl_tc_cold_off_power_well_is_enabled(struct intel_display *display,
>>  static void xelpdp_aux_power_well_enable(struct intel_display *display,
>>                                           struct i915_power_well *power_well)
>>  {
>> +        struct intel_encoder *encoder = icl_aux_pw_to_encoder(display, power_well);
>>          enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
>>          enum phy phy = icl_aux_pw_to_phy(display, power_well);
>>  
>> -        if (intel_phy_is_tc(display, phy))
>> +        if (encoder && intel_encoder_is_tc(encoder))
>>                  icl_tc_port_assert_ref_held(display, power_well,
>>                                              aux_ch_to_digital_port(display, aux_ch));
>>  
>> 
>> -- 
>> 2.51.0
>>

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

* Re: [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc()
  2025-11-12 16:24   ` Imre Deak
@ 2025-11-13 22:02     ` Gustavo Sousa
  0 siblings, 0 replies; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-13 22:02 UTC (permalink / raw)
  To: Imre Deak
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai, Jani Nikula

Quoting Imre Deak (2025-11-12 13:24:30-03:00)
>On Fri, Nov 07, 2025 at 09:05:37PM -0300, Gustavo Sousa wrote:
>> Starting with Xe3p_LPD, the VBT has a new field, called in the driver
>> "dedicated_external", which tells that a Type-C capable port is
>> physically connected to a PHY outside of the Type-C subsystem.  When
>> that's the case, the driver must not do the extra Type-C programming for
>> that port.  Update intel_encoder_is_tc() to check for that case.
>> 
>> While at it, add a note to intel_phy_is_tc() to remind us that it is
>> about whether the respective port is a Type-C capable port rather than
>> the PHY itself.
>> 
>> (Maybe it would be a nice idea to rename intel_phy_is_tc()?)
>> 
>> Note that this was handled with a new bool member added to struct
>> intel_digital_port instead of having querying the VBT directly because
>> VBT memory is freed (intel_bios_driver_remove) before encoder cleanup
>> (intel_ddi_encoder_destroy), which would cause an oops to happen when
>> the latter calls intel_encoder_is_tc().  This could be fixed by keeping
>> VBT data around longer, but that's left for a follow-up work, if deemed
>> necessary.
>> 
>> v2:
>>   - Drop printing info about dedicated external, now that we are doing
>>     it when parsing the VBT. (Jani)
>>   - Add a FIXME comment on the code explaining why we need to store
>>     dedicated_external in struct intel_digital_port. (Jani)
>> 
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> Cc: Shekhar Chauhan <shekhar.chauhan@intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>>  drivers/gpu/drm/i915/display/intel_ddi.c           | 11 +++++++++++
>>  drivers/gpu/drm/i915/display/intel_display.c       | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/i915/display/intel_display_types.h |  1 +
>>  3 files changed, 30 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
>> index 733ef4559131..d9aaeafd1570 100644
>> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
>> @@ -5376,6 +5376,17 @@ void intel_ddi_init(struct intel_display *display,
>>                          goto err;
>>          }
>>  
>> +        /*
>> +         * FIXME: We currently need to store dedicated_external because devdata
>> +         * does not live long enough for when intel_encoder_is_tc() is called on
>> +         * the unbind path.  This needs to be fixed by making sure that the VBT
>> +         * data is kept long enough, so that
>> +         * intel_bios_encoder_is_dedicated_external() can be called directly
>> +         * from intel_encoder_is_tc().
>> +         */
>> +        if (intel_bios_encoder_is_dedicated_external(devdata))
>> +                dig_port->dedicated_external = true;
>> +
>>          if (intel_encoder_is_tc(encoder)) {
>>                  bool is_legacy =
>>                          !intel_bios_encoder_supports_typec_usb(devdata) &&
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>> index 25986bd8fbdd..431f7f030a9b 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -1800,7 +1800,17 @@ bool intel_phy_is_combo(struct intel_display *display, enum phy phy)
>>                  return false;
>>  }
>>  
>> -/* Prefer intel_encoder_is_tc() */
>> +/*
>> + * This function returns true if the DDI port respective to the PHY enumeration
>> + * is a Type-C capable port.
>> + *
>> + * Depending on the VBT, the port might be configured
>> + * as a "dedicated external" port, meaning that actual physical PHY is outside
>> + * of the Type-C subsystem and, as such, not really a "Type-C PHY".
>> + *
>> + * Prefer intel_encoder_is_tc(), especially if you really need to know if we
>> + * are dealing with Type-C connections.
>> + */
>>  bool intel_phy_is_tc(struct intel_display *display, enum phy phy)
>>  {
>>          /*
>> @@ -1885,6 +1895,13 @@ bool intel_encoder_is_tc(struct intel_encoder *encoder)
>>  {
>>          struct intel_display *display = to_intel_display(encoder);
>>  
>> +        if (intel_encoder_is_dig_port(encoder)) {
>> +                struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
>
>Just dig_port = enc_to_dig_port(encoder); ... if (dig_port &&
>dig_port->dedicated_external) would be simpler and would be also more
>consistent wrt. MST encoders.

Ack.

Thanks!

--
Gustavo Sousa

>
>> +
>> +                if (dig_port->dedicated_external)
>> +                        return false;
>> +        }
>> +
>>          return intel_phy_is_tc(display, intel_encoder_to_phy(encoder));
>>  }
>>  
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
>> index 00600134bda0..8bf392bc0d5d 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
>> @@ -1937,6 +1937,7 @@ struct intel_digital_port {
>>          bool lane_reversal;
>>          bool ddi_a_4_lanes;
>>          bool release_cl2_override;
>> +        bool dedicated_external;
>>          u8 max_lanes;
>>          /* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
>>          enum aux_ch aux_ch;
>> 
>> -- 
>> 2.51.0
>>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-12 17:53   ` Imre Deak
@ 2025-11-14 19:46     ` Gustavo Sousa
  2025-11-15  0:40       ` Imre Deak
  0 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-14 19:46 UTC (permalink / raw)
  To: Imre Deak
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

Quoting Imre Deak (2025-11-12 14:53:47-03:00)
>On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
>> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
>> the DDI (TC ones) port to drive a legacy connection on the Type-C
>> subsystem.  This allows better resource utilization, because now there
>> is no need to statically reserve ports for legacy connectors on the
>> Type-C subsystem.
>> 
>> That said, our driver is not yet ready for the dynamic allocation.
>> Thus, as an incremental step, let's add the logic containing the
>> required programming sequence for the allocation, but, instead of
>> selecting the first available port, we try so use the 1:1 mapping
>> expected by the driver today.
>> 
>> Bspec: 68954
>> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> ---
>> 
>> NOTE: This patch is still a WIP. There are some opens to resolve here.
>> Nevertheless, I'm sending it here for early feedback.
>> 
>> For the HIP-index stuff, I have a local refactor started and need to
>> finish it up and send it.
>> 
>> The other open is about concurrent calls to iom_dp_resource_lock().  It
>> is likely that we need to have a software lock to prevent concurrent
>> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
>> ---
>>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
>>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
>>  2 files changed, 169 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> index 89ea0156ee06..0cf7d43ce210 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
>>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
>>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
>>  
>> +/*
>> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
>> + * We need to consolidate the definitions.
>> + */
>> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
>> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
>> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
>> +
>> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
>> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
>> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
>> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
>> +
>> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
>> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
>> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
>
>It would be simpler to define the above without the shift, i.e. as 8 +
>tc_port.

You mean something like this?

#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))

?

Yeah... Looking at the code, we wouldn't need to shift back when
defining expected_consumer.

>
>> +
>>  #define _TCSS_DDI_STATUS_1                        0x161500
>>  #define _TCSS_DDI_STATUS_2                        0x161504
>>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
>> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
>>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
>>  
>>  
>> -
>>  #endif /* __INTEL_DISPLAY_REGS_H__ */
>> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
>> index 7e17ca018748..3c333999bbe4 100644
>> --- a/drivers/gpu/drm/i915/display/intel_tc.c
>> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
>> @@ -9,6 +9,7 @@
>>  
>>  #include "i915_reg.h"
>>  #include "intel_atomic.h"
>> +#include "intel_bios.h"
>>  #include "intel_cx0_phy_regs.h"
>>  #include "intel_ddi.h"
>>  #include "intel_de.h"
>> @@ -25,6 +26,9 @@
>>  #include "intel_modeset_lock.h"
>>  #include "intel_tc.h"
>>  
>> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
>> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
>
>The above param names should make it clear how poll_timeout_us() uses
>them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
>retry_timeout), but probably even clearer to just drop the defines and
>inline the values in the call.

Ack.  I going with the latter.

>
>> +
>>  enum tc_port_mode {
>>          TC_PORT_DISCONNECTED,
>>          TC_PORT_TBT_ALT,
>> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
>>          __tc_cold_unblock(tc, domain, tc_cold_wref);
>>  }
>>  
>> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
>> +{
>> +        /*
>> +         * IOM resource management registers live in the 2nd 4KB page of IOM
>> +         * address space. So we need to configure HIP_INDEX_REG0 with the
>> +         * correct index.
>> +         *
>> +         * FIXME: We need to have this and dekel PHY implementation using a
>> +         * common abstraction to access registers on the HIP-indexed ranges, and
>> +         * this function would then be dropped.
>> +         */
>> +        intel_de_rmw(display, HIP_INDEX_REG0,
>> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
>
>This matches what intel_dkl_phy.c does, that one also taking the
>required lock around the access. At one point the intel_dkl_phy
>file/interface could be renamed to intel_tc_reg or similar accordingly.

I have already started a local series that introduces the "HIP-index
based registers" abstraction.  I need to go back to finish it up.

The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
functions specific to accessing registers behind the HIP-based ranges.

To give an idea, here is a copy/paste of the kerneldoc I currently have
in that WIP series:

  | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
  | new file mode 100644
  | index 000000000000..ff2492b8275d
  | --- /dev/null
  | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
  | @@ -0,0 +1,110 @@
  | +// SPDX-License-Identifier: MIT
  | +/*
  | + * Copyright (C) 2025 Intel Corporation
  | + */
  | +
  | +/**
  | + * DOC: Display HIP-indexed register access
  | + *
  | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
  | + * configurations in the HIP_INDEX registers provided by the hardware.
  | + *
  | + * Usually each of the valid 4KB range in that space will be mapped to some IP
  | + * block, providing access to registers of that IP. The HIP_INDEX registers
  | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
  | + * to access data that is beyond the initial 4KB block provided by the target
  | + * IP.
  | + *
  | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
  | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
  | + * register file, we would need to set the index respective to
  | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
  | + * window, we would need to set the index to 1.
  | + *
  | + * For simple read, write or rmw operations on a single register, the
  | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
  | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
  | + * and intel_hip_idx_unlock() internally.
  | + *
  | + * For other scenarios, then it is necessary to wrap the register accesses
  | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
  | + * use the MMIO functions provided by intel_de.h. For the latter, the function
  | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
  | + * correct reg argument to those functions.
  | + */
  | (...)

>
>> +}
>> +
>> +/*
>> + * FIXME: This function also needs to avoid concurrent accesses from the driver
>> + * itself, possibly via a software lock.
>> + */
>> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
>> +{
>> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
>> +        int ret;
>> +
>> +        iom_res_mgmt_prepare_reg_access(display);
>> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
>> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
>
>This happens to work, but it's more future proof/bspec conformant to
>properly mask the requestor ID field when reading it back.

Agreed.

>
>> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
>> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
>> +
>> +        if (ret)
>> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
>> +                        tc->port_name);
>> +
>> +        return ret;
>> +}
>> +
>> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
>> +{
>> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> +
>> +        iom_res_mgmt_prepare_reg_access(display);
>> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
>> +}
>> +
>> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
>> +{
>> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> +        struct intel_digital_port *dig_port = tc->dig_port;
>> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
>> +        u32 val;
>> +        u32 consumer;
>> +        u32 expected_consumer;
>> +        bool ret;
>> +
>> +        if (DISPLAY_VER(display) < 35)
>> +                return true;
>> +
>> +        if (tc->mode != TC_PORT_LEGACY)
>> +                return true;
>> +
>> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
>
>dedicated_external is stored separately in dig_port, why the "related"
>dyn_port_over_tc flag isn't?

The only reason dedicated_external is stored is because VBT data is
already freed by the time intel_encoder_is_tc() is called in the driver
unbind path.  In the future we should fix the VBT lifetime issue in
order to be able to drop the dedicated_external member of dig_port.

>
>> +                return true;
>> +
>> +        if (iom_dp_resource_lock(tc))
>> +                return false;
>> +
>> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
>> +
>> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
>> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> +
>> +        /*
>> +         * Bspec instructs to select first available DDI, but our driver is not
>> +         * ready for such dynamic allocation yet. For now, we force a "static"
>> +         * allocation: map the physical port (where HPD happens) to the
>> +         * encoder's DDI (logical TC port, represented by tc_port).
>> +         */
>> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
>> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> +
>> +        if (allocate) {
>> +                struct intel_encoder *other_encoder;
>> +
>> +                /*
>> +                 * Check if this encoder's DDI is already allocated for another
>> +                 * physical port, which could have happened prior to the driver
>> +                 * taking over (e.g. GOP).
>> +                 */
>> +                for_each_intel_encoder(display->drm, other_encoder) {
>> +                        enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
>> +                        u32 other_consumer;
>> +
>> +                        if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
>> +                                continue;
>> +
>> +                        other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
>> +                        other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
>> +                        if (other_consumer == expected_consumer) {
>> +                                drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
>> +                                        tc->port_name, expected_consumer, val);
>> +                                ret = false;
>> +                                goto out_resource_unlock;
>> +                        }
>> +                }
>> +
>> +                if (consumer == 0) {
>> +                        /* DDI is free to use, let's allocate it. */
>> +                        val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
>> +                        val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
>> +                        intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
>> +                        ret = true;
>> +                } else if (consumer == expected_consumer) {
>> +                        /*
>> +                         * Nothing to do, as the expected "static" DDI allocation is
>> +                         * already in place.
>> +                         */
>> +                        ret = true;
>> +                } else {
>> +                        drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
>> +                                tc->port_name, consumer, val);
>> +                        ret = false;
>> +                }
>> +        } else {
>> +                drm_WARN_ON(display->drm, consumer != expected_consumer);
>> +                val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
>> +                intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
>> +                ret = true;
>> +        }
>> +
>> +out_resource_unlock:
>> +        iom_dp_resource_unlock(tc);
>> +
>> +        return ret;
>> +}
>> +
>>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>>  {
>>          tc->lock_wakeref = tc_cold_block(tc);
>> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>>                  return true;
>>          }
>>  
>> -        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
>> +        if (!xe3p_tc_iom_allocate_ddi(tc, true))
>
>This doesn't work. A connector registered to userspace must be always
>functional (except for MST connectors which are dynamically registered).
>So the DDI allocation and with that connecting the PHY cannot fail here
>for a legacy connector/PHY. Instead of this the allocation could be
>moved to happen already in intel_tc_phy_ops::init for now, allocating a
>DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
>fails also fail the corresponding connector/encoder registration in
>intel_ddi_init(). The DDI would need to be released by
>intel_tc_port_cleanup().

Ah, I see.  Well, I guess for legacy connections, doing your suggestion
seems fine.

Is there any power management aspect that we should be aware here? Like,
some power well being disabled and causing the allocation to be "lost"
somehow.  Since this thing is in the TCSS, I think no display power
wells could cause that, right?

By the way, I wonder how we would handle things in the future when/if we
enable the dynamic DDI allocation thing.

--
Gustavo Sousa

>
>>                  goto out_unblock_tccold;
>>  
>> +        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
>> +                goto out_deallocate_ddi;
>> +
>>          xelpdp_tc_phy_take_ownership(tc, true);
>>  
>>          read_pin_configuration(tc);
>> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>>          xelpdp_tc_phy_take_ownership(tc, false);
>>          xelpdp_tc_phy_wait_for_tcss_power(tc, false);
>>  
>> +out_deallocate_ddi:
>> +        xe3p_tc_iom_allocate_ddi(tc, false);
>> +
>>  out_unblock_tccold:
>>          tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
>>  
>> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
>>  {
>>          switch (tc->mode) {
>>          case TC_PORT_LEGACY:
>> +                xe3p_tc_iom_allocate_ddi(tc, false);
>> +                fallthrough;
>>          case TC_PORT_DP_ALT:
>>                  xelpdp_tc_phy_take_ownership(tc, false);
>>                  xelpdp_tc_phy_enable_tcss_power(tc, false);
>> 
>> -- 
>> 2.51.0
>>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-14 19:46     ` Gustavo Sousa
@ 2025-11-15  0:40       ` Imre Deak
  2025-11-15  1:22         ` Imre Deak
  2025-11-17 15:33         ` Gustavo Sousa
  0 siblings, 2 replies; 48+ messages in thread
From: Imre Deak @ 2025-11-15  0:40 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

On Fri, Nov 14, 2025 at 04:46:29PM -0300, Gustavo Sousa wrote:
> Quoting Imre Deak (2025-11-12 14:53:47-03:00)
> >On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
> >> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
> >> the DDI (TC ones) port to drive a legacy connection on the Type-C
> >> subsystem.  This allows better resource utilization, because now there
> >> is no need to statically reserve ports for legacy connectors on the
> >> Type-C subsystem.
> >> 
> >> That said, our driver is not yet ready for the dynamic allocation.
> >> Thus, as an incremental step, let's add the logic containing the
> >> required programming sequence for the allocation, but, instead of
> >> selecting the first available port, we try so use the 1:1 mapping
> >> expected by the driver today.
> >> 
> >> Bspec: 68954
> >> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> >> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> >> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> >> ---
> >> 
> >> NOTE: This patch is still a WIP. There are some opens to resolve here.
> >> Nevertheless, I'm sending it here for early feedback.
> >> 
> >> For the HIP-index stuff, I have a local refactor started and need to
> >> finish it up and send it.
> >> 
> >> The other open is about concurrent calls to iom_dp_resource_lock().  It
> >> is likely that we need to have a software lock to prevent concurrent
> >> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
> >> ---
> >>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
> >>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
> >>  2 files changed, 169 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> index 89ea0156ee06..0cf7d43ce210 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
> >>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
> >>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
> >>  
> >> +/*
> >> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
> >> + * We need to consolidate the definitions.
> >> + */
> >> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
> >> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
> >> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
> >> +
> >> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
> >> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
> >> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
> >> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
> >> +
> >> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
> >> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
> >> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
> >> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
> >> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
> >
> >It would be simpler to define the above without the shift, i.e. as 8 +
> >tc_port.
> 
> You mean something like this?
> 
> #define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))
> 
> ?
> 
> Yeah... Looking at the code, we wouldn't need to shift back when
> defining expected_consumer.

Yes.

> 
> >
> >> +
> >>  #define _TCSS_DDI_STATUS_1                        0x161500
> >>  #define _TCSS_DDI_STATUS_2                        0x161504
> >>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
> >> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
> >>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
> >>  
> >>  
> >> -
> >>  #endif /* __INTEL_DISPLAY_REGS_H__ */
> >> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
> >> index 7e17ca018748..3c333999bbe4 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> >> @@ -9,6 +9,7 @@
> >>  
> >>  #include "i915_reg.h"
> >>  #include "intel_atomic.h"
> >> +#include "intel_bios.h"
> >>  #include "intel_cx0_phy_regs.h"
> >>  #include "intel_ddi.h"
> >>  #include "intel_de.h"
> >> @@ -25,6 +26,9 @@
> >>  #include "intel_modeset_lock.h"
> >>  #include "intel_tc.h"
> >>  
> >> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
> >> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
> >
> >The above param names should make it clear how poll_timeout_us() uses
> >them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
> >retry_timeout), but probably even clearer to just drop the defines and
> >inline the values in the call.
> 
> Ack.  I going with the latter.
> 
> >
> >> +
> >>  enum tc_port_mode {
> >>          TC_PORT_DISCONNECTED,
> >>          TC_PORT_TBT_ALT,
> >> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
> >>          __tc_cold_unblock(tc, domain, tc_cold_wref);
> >>  }
> >>  
> >> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
> >> +{
> >> +        /*
> >> +         * IOM resource management registers live in the 2nd 4KB page of IOM
> >> +         * address space. So we need to configure HIP_INDEX_REG0 with the
> >> +         * correct index.
> >> +         *
> >> +         * FIXME: We need to have this and dekel PHY implementation using a
> >> +         * common abstraction to access registers on the HIP-indexed ranges, and
> >> +         * this function would then be dropped.
> >> +         */
> >> +        intel_de_rmw(display, HIP_INDEX_REG0,
> >> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
> >
> >This matches what intel_dkl_phy.c does, that one also taking the
> >required lock around the access. At one point the intel_dkl_phy
> >file/interface could be renamed to intel_tc_reg or similar accordingly.
> 
> I have already started a local series that introduces the "HIP-index
> based registers" abstraction.  I need to go back to finish it up.
> 
> The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
> functions specific to accessing registers behind the HIP-based ranges.

Using intel_hip_reg instead of intel_tc_reg is probably better, but I
still think the current interface should be just renamed, instead of
adding a new interface and making the current
intel_dkl_phy_read/write/rmw() use that new interface.

I went ahead and put the above together now:
https://github.com/ideak/linux/commits/hip-reg

> 
> To give an idea, here is a copy/paste of the kerneldoc I currently have
> in that WIP series:
> 
>   | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>   | new file mode 100644
>   | index 000000000000..ff2492b8275d
>   | --- /dev/null
>   | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>   | @@ -0,0 +1,110 @@
>   | +// SPDX-License-Identifier: MIT
>   | +/*
>   | + * Copyright (C) 2025 Intel Corporation
>   | + */
>   | +
>   | +/**
>   | + * DOC: Display HIP-indexed register access
>   | + *
>   | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
>   | + * configurations in the HIP_INDEX registers provided by the hardware.
>   | + *
>   | + * Usually each of the valid 4KB range in that space will be mapped to some IP
>   | + * block, providing access to registers of that IP. The HIP_INDEX registers
>   | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
>   | + * to access data that is beyond the initial 4KB block provided by the target
>   | + * IP.
>   | + *
>   | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
>   | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
>   | + * register file, we would need to set the index respective to
>   | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
>   | + * window, we would need to set the index to 1.
>   | + *
>   | + * For simple read, write or rmw operations on a single register, the
>   | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
>   | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
>   | + * and intel_hip_idx_unlock() internally.
>   | + *
>   | + * For other scenarios, then it is necessary to wrap the register accesses
>   | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
>   | + * use the MMIO functions provided by intel_de.h. For the latter, the function
>   | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
>   | + * correct reg argument to those functions.
>   | + */
>   | (...)
> 
> >
> >> +}
> >> +
> >> +/*
> >> + * FIXME: This function also needs to avoid concurrent accesses from the driver
> >> + * itself, possibly via a software lock.
> >> + */
> >> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
> >> +{
> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
> >> +        int ret;
> >> +
> >> +        iom_res_mgmt_prepare_reg_access(display);
> >> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
> >> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
> >
> >This happens to work, but it's more future proof/bspec conformant to
> >properly mask the requestor ID field when reading it back.
> 
> Agreed.
> 
> >
> >> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
> >> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
> >> +
> >> +        if (ret)
> >> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
> >> +                        tc->port_name);
> >> +
> >> +        return ret;
> >> +}
> >> +
> >> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
> >> +{
> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> +
> >> +        iom_res_mgmt_prepare_reg_access(display);
> >> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
> >> +}
> >> +
> >> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
> >> +{
> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> +        struct intel_digital_port *dig_port = tc->dig_port;
> >> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
> >> +        u32 val;
> >> +        u32 consumer;
> >> +        u32 expected_consumer;
> >> +        bool ret;
> >> +
> >> +        if (DISPLAY_VER(display) < 35)
> >> +                return true;
> >> +
> >> +        if (tc->mode != TC_PORT_LEGACY)
> >> +                return true;
> >> +
> >> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
> >
> >dedicated_external is stored separately in dig_port, why the "related"
> >dyn_port_over_tc flag isn't?
> 
> The only reason dedicated_external is stored is because VBT data is
> already freed by the time intel_encoder_is_tc() is called in the driver
> unbind path.  In the future we should fix the VBT lifetime issue in
> order to be able to drop the dedicated_external member of dig_port.
> 
> >
> >> +                return true;
> >> +
> >> +        if (iom_dp_resource_lock(tc))
> >> +                return false;
> >> +
> >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> >> +
> >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> +
> >> +        /*
> >> +         * Bspec instructs to select first available DDI, but our driver is not
> >> +         * ready for such dynamic allocation yet. For now, we force a "static"
> >> +         * allocation: map the physical port (where HPD happens) to the
> >> +         * encoder's DDI (logical TC port, represented by tc_port).
> >> +         */
> >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);

One more thing occured to me: why can't this allocate any free DDI? IOW
does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
on which DDI gets allocated (or is there any other dependency on which
DDI got allocated)? AFAICS there is no such dependency and the above
address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
DDI. In that case any free DDI could be allocated here.

> >> +
> >> +        if (allocate) {
> >> +                struct intel_encoder *other_encoder;
> >> +
> >> +                /*
> >> +                 * Check if this encoder's DDI is already allocated for another
> >> +                 * physical port, which could have happened prior to the driver
> >> +                 * taking over (e.g. GOP).
> >> +                 */
> >> +                for_each_intel_encoder(display->drm, other_encoder) {
> >> +                        enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
> >> +                        u32 other_consumer;
> >> +
> >> +                        if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
> >> +                                continue;
> >> +
> >> +                        other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
> >> +                        other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
> >> +                        if (other_consumer == expected_consumer) {
> >> +                                drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
> >> +                                        tc->port_name, expected_consumer, val);
> >> +                                ret = false;
> >> +                                goto out_resource_unlock;
> >> +                        }
> >> +                }
> >> +
> >> +                if (consumer == 0) {
> >> +                        /* DDI is free to use, let's allocate it. */
> >> +                        val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> >> +                        val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
> >> +                        intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> >> +                        ret = true;
> >> +                } else if (consumer == expected_consumer) {
> >> +                        /*
> >> +                         * Nothing to do, as the expected "static" DDI allocation is
> >> +                         * already in place.
> >> +                         */
> >> +                        ret = true;
> >> +                } else {
> >> +                        drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
> >> +                                tc->port_name, consumer, val);
> >> +                        ret = false;
> >> +                }
> >> +        } else {
> >> +                drm_WARN_ON(display->drm, consumer != expected_consumer);
> >> +                val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> >> +                intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> >> +                ret = true;
> >> +        }
> >> +
> >> +out_resource_unlock:
> >> +        iom_dp_resource_unlock(tc);
> >> +
> >> +        return ret;
> >> +}
> >> +
> >>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >>  {
> >>          tc->lock_wakeref = tc_cold_block(tc);
> >> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >>                  return true;
> >>          }
> >>  
> >> -        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> >> +        if (!xe3p_tc_iom_allocate_ddi(tc, true))
> >
> >This doesn't work. A connector registered to userspace must be always
> >functional (except for MST connectors which are dynamically registered).
> >So the DDI allocation and with that connecting the PHY cannot fail here
> >for a legacy connector/PHY. Instead of this the allocation could be
> >moved to happen already in intel_tc_phy_ops::init for now, allocating a
> >DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
> >fails also fail the corresponding connector/encoder registration in
> >intel_ddi_init(). The DDI would need to be released by
> >intel_tc_port_cleanup().
> 
> Ah, I see.  Well, I guess for legacy connections, doing your suggestion
> seems fine.
> 
> Is there any power management aspect that we should be aware here? Like,
> some power well being disabled and causing the allocation to be "lost"
> somehow.  Since this thing is in the TCSS, I think no display power
> wells could cause that, right?

It would make sense to me that the allocations are preserved by the
HW/FW across power transitions. If that's not the case then they should
be restored by the driver.

> By the way, I wonder how we would handle things in the future when/if we
> enable the dynamic DDI allocation thing.

In case of a DDI allocation failure, the modeset will still succeed, but
the corresponding port/pipe will not get enabled.

> --
> Gustavo Sousa
> 
> >
> >>                  goto out_unblock_tccold;
> >>  
> >> +        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> >> +                goto out_deallocate_ddi;
> >> +
> >>          xelpdp_tc_phy_take_ownership(tc, true);
> >>  
> >>          read_pin_configuration(tc);
> >> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >>          xelpdp_tc_phy_take_ownership(tc, false);
> >>          xelpdp_tc_phy_wait_for_tcss_power(tc, false);
> >>  
> >> +out_deallocate_ddi:
> >> +        xe3p_tc_iom_allocate_ddi(tc, false);
> >> +
> >>  out_unblock_tccold:
> >>          tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
> >>  
> >> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
> >>  {
> >>          switch (tc->mode) {
> >>          case TC_PORT_LEGACY:
> >> +                xe3p_tc_iom_allocate_ddi(tc, false);
> >> +                fallthrough;
> >>          case TC_PORT_DP_ALT:
> >>                  xelpdp_tc_phy_take_ownership(tc, false);
> >>                  xelpdp_tc_phy_enable_tcss_power(tc, false);
> >> 
> >> -- 
> >> 2.51.0
> >>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-15  0:40       ` Imre Deak
@ 2025-11-15  1:22         ` Imre Deak
  2025-11-17 15:02           ` Gustavo Sousa
  2025-11-17 15:33         ` Gustavo Sousa
  1 sibling, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-15  1:22 UTC (permalink / raw)
  To: Gustavo Sousa, intel-xe, intel-gfx, Ankit Nautiyal,
	Dnyaneshwar Bhadane, Jouni Högander, Juha-pekka Heikkila,
	Luca Coelho, Lucas De Marchi, Matt Atwood, Matt Roper,
	Ravi Kumar Vodapalli, Shekhar Chauhan, Vinod Govindapillai

On Sat, Nov 15, 2025 at 02:40:24AM +0200, Imre Deak wrote:
> On Fri, Nov 14, 2025 at 04:46:29PM -0300, Gustavo Sousa wrote:
> > Quoting Imre Deak (2025-11-12 14:53:47-03:00)
> > >On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
> > >> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
> > >> the DDI (TC ones) port to drive a legacy connection on the Type-C
> > >> subsystem.  This allows better resource utilization, because now there
> > >> is no need to statically reserve ports for legacy connectors on the
> > >> Type-C subsystem.
> > >> 
> > >> That said, our driver is not yet ready for the dynamic allocation.
> > >> Thus, as an incremental step, let's add the logic containing the
> > >> required programming sequence for the allocation, but, instead of
> > >> selecting the first available port, we try so use the 1:1 mapping
> > >> expected by the driver today.
> > >> 
> > >> Bspec: 68954
> > >> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> > >> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> > >> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> > >> ---
> > >> 
> > >> NOTE: This patch is still a WIP. There are some opens to resolve here.
> > >> Nevertheless, I'm sending it here for early feedback.
> > >> 
> > >> For the HIP-index stuff, I have a local refactor started and need to
> > >> finish it up and send it.
> > >> 
> > >> The other open is about concurrent calls to iom_dp_resource_lock().  It
> > >> is likely that we need to have a software lock to prevent concurrent
> > >> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
> > >> ---
> > >>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
> > >>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
> > >>  2 files changed, 169 insertions(+), 2 deletions(-)
> > >> 
> > >> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> > >> index 89ea0156ee06..0cf7d43ce210 100644
> > >> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> > >> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> > >> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
> > >>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
> > >>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
> > >>  
> > >> +/*
> > >> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
> > >> + * We need to consolidate the definitions.
> > >> + */
> > >> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
> > >> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
> > >> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
> > >> +
> > >> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
> > >> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
> > >> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
> > >> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
> > >> +
> > >> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
> > >> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
> > >> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
> > >> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
> > >> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
> > >
> > >It would be simpler to define the above without the shift, i.e. as 8 +
> > >tc_port.
> > 
> > You mean something like this?
> > 
> > #define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))
> > 
> > ?
> > 
> > Yeah... Looking at the code, we wouldn't need to shift back when
> > defining expected_consumer.
> 
> Yes.
> 
> > 
> > >
> > >> +
> > >>  #define _TCSS_DDI_STATUS_1                        0x161500
> > >>  #define _TCSS_DDI_STATUS_2                        0x161504
> > >>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
> > >> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
> > >>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
> > >>  
> > >>  
> > >> -
> > >>  #endif /* __INTEL_DISPLAY_REGS_H__ */
> > >> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
> > >> index 7e17ca018748..3c333999bbe4 100644
> > >> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> > >> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> > >> @@ -9,6 +9,7 @@
> > >>  
> > >>  #include "i915_reg.h"
> > >>  #include "intel_atomic.h"
> > >> +#include "intel_bios.h"
> > >>  #include "intel_cx0_phy_regs.h"
> > >>  #include "intel_ddi.h"
> > >>  #include "intel_de.h"
> > >> @@ -25,6 +26,9 @@
> > >>  #include "intel_modeset_lock.h"
> > >>  #include "intel_tc.h"
> > >>  
> > >> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
> > >> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
> > >
> > >The above param names should make it clear how poll_timeout_us() uses
> > >them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
> > >retry_timeout), but probably even clearer to just drop the defines and
> > >inline the values in the call.
> > 
> > Ack.  I going with the latter.
> > 
> > >
> > >> +
> > >>  enum tc_port_mode {
> > >>          TC_PORT_DISCONNECTED,
> > >>          TC_PORT_TBT_ALT,
> > >> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
> > >>          __tc_cold_unblock(tc, domain, tc_cold_wref);
> > >>  }
> > >>  
> > >> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
> > >> +{
> > >> +        /*
> > >> +         * IOM resource management registers live in the 2nd 4KB page of IOM
> > >> +         * address space. So we need to configure HIP_INDEX_REG0 with the
> > >> +         * correct index.
> > >> +         *
> > >> +         * FIXME: We need to have this and dekel PHY implementation using a
> > >> +         * common abstraction to access registers on the HIP-indexed ranges, and
> > >> +         * this function would then be dropped.
> > >> +         */
> > >> +        intel_de_rmw(display, HIP_INDEX_REG0,
> > >> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
> > >
> > >This matches what intel_dkl_phy.c does, that one also taking the
> > >required lock around the access. At one point the intel_dkl_phy
> > >file/interface could be renamed to intel_tc_reg or similar accordingly.
> > 
> > I have already started a local series that introduces the "HIP-index
> > based registers" abstraction.  I need to go back to finish it up.
> > 
> > The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
> > functions specific to accessing registers behind the HIP-based ranges.
> 
> Using intel_hip_reg instead of intel_tc_reg is probably better, but I
> still think the current interface should be just renamed, instead of
> adding a new interface and making the current
> intel_dkl_phy_read/write/rmw() use that new interface.
> 
> I went ahead and put the above together now:
> https://github.com/ideak/linux/commits/hip-reg
> 
> > 
> > To give an idea, here is a copy/paste of the kerneldoc I currently have
> > in that WIP series:
> > 
> >   | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
> >   | new file mode 100644
> >   | index 000000000000..ff2492b8275d
> >   | --- /dev/null
> >   | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
> >   | @@ -0,0 +1,110 @@
> >   | +// SPDX-License-Identifier: MIT
> >   | +/*
> >   | + * Copyright (C) 2025 Intel Corporation
> >   | + */
> >   | +
> >   | +/**
> >   | + * DOC: Display HIP-indexed register access
> >   | + *
> >   | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
> >   | + * configurations in the HIP_INDEX registers provided by the hardware.
> >   | + *
> >   | + * Usually each of the valid 4KB range in that space will be mapped to some IP
> >   | + * block, providing access to registers of that IP. The HIP_INDEX registers
> >   | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
> >   | + * to access data that is beyond the initial 4KB block provided by the target
> >   | + * IP.
> >   | + *
> >   | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
> >   | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
> >   | + * register file, we would need to set the index respective to
> >   | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
> >   | + * window, we would need to set the index to 1.
> >   | + *
> >   | + * For simple read, write or rmw operations on a single register, the
> >   | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
> >   | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
> >   | + * and intel_hip_idx_unlock() internally.
> >   | + *
> >   | + * For other scenarios, then it is necessary to wrap the register accesses
> >   | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
> >   | + * use the MMIO functions provided by intel_de.h. For the latter, the function
> >   | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
> >   | + * correct reg argument to those functions.
> >   | + */
> >   | (...)
> > 
> > >
> > >> +}
> > >> +
> > >> +/*
> > >> + * FIXME: This function also needs to avoid concurrent accesses from the driver
> > >> + * itself, possibly via a software lock.
> > >> + */
> > >> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
> > >> +{
> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> > >> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
> > >> +        int ret;
> > >> +
> > >> +        iom_res_mgmt_prepare_reg_access(display);
> > >> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
> > >> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
> > >
> > >This happens to work, but it's more future proof/bspec conformant to
> > >properly mask the requestor ID field when reading it back.
> > 
> > Agreed.
> > 
> > >
> > >> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
> > >> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
> > >> +
> > >> +        if (ret)
> > >> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
> > >> +                        tc->port_name);
> > >> +
> > >> +        return ret;
> > >> +}
> > >> +
> > >> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
> > >> +{
> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> > >> +
> > >> +        iom_res_mgmt_prepare_reg_access(display);
> > >> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
> > >> +}
> > >> +
> > >> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
> > >> +{
> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> > >> +        struct intel_digital_port *dig_port = tc->dig_port;
> > >> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
> > >> +        u32 val;
> > >> +        u32 consumer;
> > >> +        u32 expected_consumer;
> > >> +        bool ret;
> > >> +
> > >> +        if (DISPLAY_VER(display) < 35)
> > >> +                return true;
> > >> +
> > >> +        if (tc->mode != TC_PORT_LEGACY)
> > >> +                return true;
> > >> +
> > >> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
> > >
> > >dedicated_external is stored separately in dig_port, why the "related"
> > >dyn_port_over_tc flag isn't?
> > 
> > The only reason dedicated_external is stored is because VBT data is
> > already freed by the time intel_encoder_is_tc() is called in the driver
> > unbind path.  In the future we should fix the VBT lifetime issue in
> > order to be able to drop the dedicated_external member of dig_port.
> > 
> > >
> > >> +                return true;
> > >> +
> > >> +        if (iom_dp_resource_lock(tc))
> > >> +                return false;
> > >> +
> > >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> > >> +
> > >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> > >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> > >> +
> > >> +        /*
> > >> +         * Bspec instructs to select first available DDI, but our driver is not
> > >> +         * ready for such dynamic allocation yet. For now, we force a "static"
> > >> +         * allocation: map the physical port (where HPD happens) to the
> > >> +         * encoder's DDI (logical TC port, represented by tc_port).
> > >> +         */
> > >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> > >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> 
> One more thing occured to me: why can't this allocate any free DDI? IOW
> does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
> on which DDI gets allocated (or is there any other dependency on which
> DDI got allocated)? AFAICS there is no such dependency and the above
> address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
> DDI. In that case any free DDI could be allocated here.

Ok, checking this again, DDI_BUF_CTL etc. DDI register addresses will
depend on the allocated DDI. So nvm the above, the mapping needs to
stay 1:1 for now until all the DDI reg accesses are converted to index
the registers with the allocated DDI index.

> > >> +
> > >> +        if (allocate) {
> > >> +                struct intel_encoder *other_encoder;
> > >> +
> > >> +                /*
> > >> +                 * Check if this encoder's DDI is already allocated for another
> > >> +                 * physical port, which could have happened prior to the driver
> > >> +                 * taking over (e.g. GOP).
> > >> +                 */
> > >> +                for_each_intel_encoder(display->drm, other_encoder) {
> > >> +                        enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
> > >> +                        u32 other_consumer;
> > >> +
> > >> +                        if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
> > >> +                                continue;
> > >> +
> > >> +                        other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
> > >> +                        other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
> > >> +                        if (other_consumer == expected_consumer) {
> > >> +                                drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
> > >> +                                        tc->port_name, expected_consumer, val);
> > >> +                                ret = false;
> > >> +                                goto out_resource_unlock;
> > >> +                        }
> > >> +                }
> > >> +
> > >> +                if (consumer == 0) {
> > >> +                        /* DDI is free to use, let's allocate it. */
> > >> +                        val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> > >> +                        val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
> > >> +                        intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> > >> +                        ret = true;
> > >> +                } else if (consumer == expected_consumer) {
> > >> +                        /*
> > >> +                         * Nothing to do, as the expected "static" DDI allocation is
> > >> +                         * already in place.
> > >> +                         */
> > >> +                        ret = true;
> > >> +                } else {
> > >> +                        drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
> > >> +                                tc->port_name, consumer, val);
> > >> +                        ret = false;
> > >> +                }
> > >> +        } else {
> > >> +                drm_WARN_ON(display->drm, consumer != expected_consumer);
> > >> +                val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> > >> +                intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> > >> +                ret = true;
> > >> +        }
> > >> +
> > >> +out_resource_unlock:
> > >> +        iom_dp_resource_unlock(tc);
> > >> +
> > >> +        return ret;
> > >> +}
> > >> +
> > >>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> > >>  {
> > >>          tc->lock_wakeref = tc_cold_block(tc);
> > >> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> > >>                  return true;
> > >>          }
> > >>  
> > >> -        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> > >> +        if (!xe3p_tc_iom_allocate_ddi(tc, true))
> > >
> > >This doesn't work. A connector registered to userspace must be always
> > >functional (except for MST connectors which are dynamically registered).
> > >So the DDI allocation and with that connecting the PHY cannot fail here
> > >for a legacy connector/PHY. Instead of this the allocation could be
> > >moved to happen already in intel_tc_phy_ops::init for now, allocating a
> > >DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
> > >fails also fail the corresponding connector/encoder registration in
> > >intel_ddi_init(). The DDI would need to be released by
> > >intel_tc_port_cleanup().
> > 
> > Ah, I see.  Well, I guess for legacy connections, doing your suggestion
> > seems fine.
> > 
> > Is there any power management aspect that we should be aware here? Like,
> > some power well being disabled and causing the allocation to be "lost"
> > somehow.  Since this thing is in the TCSS, I think no display power
> > wells could cause that, right?
> 
> It would make sense to me that the allocations are preserved by the
> HW/FW across power transitions. If that's not the case then they should
> be restored by the driver.
> 
> > By the way, I wonder how we would handle things in the future when/if we
> > enable the dynamic DDI allocation thing.
> 
> In case of a DDI allocation failure, the modeset will still succeed, but
> the corresponding port/pipe will not get enabled.
> 
> > --
> > Gustavo Sousa
> > 
> > >
> > >>                  goto out_unblock_tccold;
> > >>  
> > >> +        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> > >> +                goto out_deallocate_ddi;
> > >> +
> > >>          xelpdp_tc_phy_take_ownership(tc, true);
> > >>  
> > >>          read_pin_configuration(tc);
> > >> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> > >>          xelpdp_tc_phy_take_ownership(tc, false);
> > >>          xelpdp_tc_phy_wait_for_tcss_power(tc, false);
> > >>  
> > >> +out_deallocate_ddi:
> > >> +        xe3p_tc_iom_allocate_ddi(tc, false);
> > >> +
> > >>  out_unblock_tccold:
> > >>          tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
> > >>  
> > >> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
> > >>  {
> > >>          switch (tc->mode) {
> > >>          case TC_PORT_LEGACY:
> > >> +                xe3p_tc_iom_allocate_ddi(tc, false);
> > >> +                fallthrough;
> > >>          case TC_PORT_DP_ALT:
> > >>                  xelpdp_tc_phy_take_ownership(tc, false);
> > >>                  xelpdp_tc_phy_enable_tcss_power(tc, false);
> > >> 
> > >> -- 
> > >> 2.51.0
> > >>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-15  1:22         ` Imre Deak
@ 2025-11-17 15:02           ` Gustavo Sousa
  2025-11-17 15:17             ` Imre Deak
  0 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-17 15:02 UTC (permalink / raw)
  To: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Imre Deak, Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi,
	Matt Atwood, Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

Quoting Imre Deak (2025-11-14 22:22:32-03:00)
>On Sat, Nov 15, 2025 at 02:40:24AM +0200, Imre Deak wrote:
>> On Fri, Nov 14, 2025 at 04:46:29PM -0300, Gustavo Sousa wrote:
>> > Quoting Imre Deak (2025-11-12 14:53:47-03:00)
>> > >On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
>> > >> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
>> > >> the DDI (TC ones) port to drive a legacy connection on the Type-C
>> > >> subsystem.  This allows better resource utilization, because now there
>> > >> is no need to statically reserve ports for legacy connectors on the
>> > >> Type-C subsystem.
>> > >> 
>> > >> That said, our driver is not yet ready for the dynamic allocation.
>> > >> Thus, as an incremental step, let's add the logic containing the
>> > >> required programming sequence for the allocation, but, instead of
>> > >> selecting the first available port, we try so use the 1:1 mapping
>> > >> expected by the driver today.
>> > >> 
>> > >> Bspec: 68954
>> > >> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> > >> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> > >> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> > >> ---
>> > >> 
>> > >> NOTE: This patch is still a WIP. There are some opens to resolve here.
>> > >> Nevertheless, I'm sending it here for early feedback.
>> > >> 
>> > >> For the HIP-index stuff, I have a local refactor started and need to
>> > >> finish it up and send it.
>> > >> 
>> > >> The other open is about concurrent calls to iom_dp_resource_lock().  It
>> > >> is likely that we need to have a software lock to prevent concurrent
>> > >> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
>> > >> ---
>> > >>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
>> > >>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
>> > >>  2 files changed, 169 insertions(+), 2 deletions(-)
>> > >> 
>> > >> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> > >> index 89ea0156ee06..0cf7d43ce210 100644
>> > >> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> > >> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> > >> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
>> > >>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
>> > >>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
>> > >>  
>> > >> +/*
>> > >> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
>> > >> + * We need to consolidate the definitions.
>> > >> + */
>> > >> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
>> > >> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
>> > >> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
>> > >> +
>> > >> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
>> > >> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
>> > >> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
>> > >> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
>> > >> +
>> > >> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
>> > >> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
>> > >> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> > >> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> > >> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
>> > >
>> > >It would be simpler to define the above without the shift, i.e. as 8 +
>> > >tc_port.
>> > 
>> > You mean something like this?
>> > 
>> > #define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))
>> > 
>> > ?
>> > 
>> > Yeah... Looking at the code, we wouldn't need to shift back when
>> > defining expected_consumer.
>> 
>> Yes.
>> 
>> > 
>> > >
>> > >> +
>> > >>  #define _TCSS_DDI_STATUS_1                        0x161500
>> > >>  #define _TCSS_DDI_STATUS_2                        0x161504
>> > >>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
>> > >> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
>> > >>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
>> > >>  
>> > >>  
>> > >> -
>> > >>  #endif /* __INTEL_DISPLAY_REGS_H__ */
>> > >> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
>> > >> index 7e17ca018748..3c333999bbe4 100644
>> > >> --- a/drivers/gpu/drm/i915/display/intel_tc.c
>> > >> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
>> > >> @@ -9,6 +9,7 @@
>> > >>  
>> > >>  #include "i915_reg.h"
>> > >>  #include "intel_atomic.h"
>> > >> +#include "intel_bios.h"
>> > >>  #include "intel_cx0_phy_regs.h"
>> > >>  #include "intel_ddi.h"
>> > >>  #include "intel_de.h"
>> > >> @@ -25,6 +26,9 @@
>> > >>  #include "intel_modeset_lock.h"
>> > >>  #include "intel_tc.h"
>> > >>  
>> > >> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
>> > >> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
>> > >
>> > >The above param names should make it clear how poll_timeout_us() uses
>> > >them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
>> > >retry_timeout), but probably even clearer to just drop the defines and
>> > >inline the values in the call.
>> > 
>> > Ack.  I going with the latter.
>> > 
>> > >
>> > >> +
>> > >>  enum tc_port_mode {
>> > >>          TC_PORT_DISCONNECTED,
>> > >>          TC_PORT_TBT_ALT,
>> > >> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
>> > >>          __tc_cold_unblock(tc, domain, tc_cold_wref);
>> > >>  }
>> > >>  
>> > >> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
>> > >> +{
>> > >> +        /*
>> > >> +         * IOM resource management registers live in the 2nd 4KB page of IOM
>> > >> +         * address space. So we need to configure HIP_INDEX_REG0 with the
>> > >> +         * correct index.
>> > >> +         *
>> > >> +         * FIXME: We need to have this and dekel PHY implementation using a
>> > >> +         * common abstraction to access registers on the HIP-indexed ranges, and
>> > >> +         * this function would then be dropped.
>> > >> +         */
>> > >> +        intel_de_rmw(display, HIP_INDEX_REG0,
>> > >> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
>> > >
>> > >This matches what intel_dkl_phy.c does, that one also taking the
>> > >required lock around the access. At one point the intel_dkl_phy
>> > >file/interface could be renamed to intel_tc_reg or similar accordingly.
>> > 
>> > I have already started a local series that introduces the "HIP-index
>> > based registers" abstraction.  I need to go back to finish it up.
>> > 
>> > The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
>> > functions specific to accessing registers behind the HIP-based ranges.
>> 
>> Using intel_hip_reg instead of intel_tc_reg is probably better, but I
>> still think the current interface should be just renamed, instead of
>> adding a new interface and making the current
>> intel_dkl_phy_read/write/rmw() use that new interface.
>> 
>> I went ahead and put the above together now:
>> https://github.com/ideak/linux/commits/hip-reg
>> 
>> > 
>> > To give an idea, here is a copy/paste of the kerneldoc I currently have
>> > in that WIP series:
>> > 
>> >   | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>> >   | new file mode 100644
>> >   | index 000000000000..ff2492b8275d
>> >   | --- /dev/null
>> >   | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>> >   | @@ -0,0 +1,110 @@
>> >   | +// SPDX-License-Identifier: MIT
>> >   | +/*
>> >   | + * Copyright (C) 2025 Intel Corporation
>> >   | + */
>> >   | +
>> >   | +/**
>> >   | + * DOC: Display HIP-indexed register access
>> >   | + *
>> >   | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
>> >   | + * configurations in the HIP_INDEX registers provided by the hardware.
>> >   | + *
>> >   | + * Usually each of the valid 4KB range in that space will be mapped to some IP
>> >   | + * block, providing access to registers of that IP. The HIP_INDEX registers
>> >   | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
>> >   | + * to access data that is beyond the initial 4KB block provided by the target
>> >   | + * IP.
>> >   | + *
>> >   | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
>> >   | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
>> >   | + * register file, we would need to set the index respective to
>> >   | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
>> >   | + * window, we would need to set the index to 1.
>> >   | + *
>> >   | + * For simple read, write or rmw operations on a single register, the
>> >   | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
>> >   | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
>> >   | + * and intel_hip_idx_unlock() internally.
>> >   | + *
>> >   | + * For other scenarios, then it is necessary to wrap the register accesses
>> >   | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
>> >   | + * use the MMIO functions provided by intel_de.h. For the latter, the function
>> >   | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
>> >   | + * correct reg argument to those functions.
>> >   | + */
>> >   | (...)
>> > 
>> > >
>> > >> +}
>> > >> +
>> > >> +/*
>> > >> + * FIXME: This function also needs to avoid concurrent accesses from the driver
>> > >> + * itself, possibly via a software lock.
>> > >> + */
>> > >> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
>> > >> +{
>> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> > >> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
>> > >> +        int ret;
>> > >> +
>> > >> +        iom_res_mgmt_prepare_reg_access(display);
>> > >> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
>> > >> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
>> > >
>> > >This happens to work, but it's more future proof/bspec conformant to
>> > >properly mask the requestor ID field when reading it back.
>> > 
>> > Agreed.
>> > 
>> > >
>> > >> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
>> > >> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
>> > >> +
>> > >> +        if (ret)
>> > >> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
>> > >> +                        tc->port_name);
>> > >> +
>> > >> +        return ret;
>> > >> +}
>> > >> +
>> > >> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
>> > >> +{
>> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> > >> +
>> > >> +        iom_res_mgmt_prepare_reg_access(display);
>> > >> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
>> > >> +}
>> > >> +
>> > >> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
>> > >> +{
>> > >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> > >> +        struct intel_digital_port *dig_port = tc->dig_port;
>> > >> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
>> > >> +        u32 val;
>> > >> +        u32 consumer;
>> > >> +        u32 expected_consumer;
>> > >> +        bool ret;
>> > >> +
>> > >> +        if (DISPLAY_VER(display) < 35)
>> > >> +                return true;
>> > >> +
>> > >> +        if (tc->mode != TC_PORT_LEGACY)
>> > >> +                return true;
>> > >> +
>> > >> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
>> > >
>> > >dedicated_external is stored separately in dig_port, why the "related"
>> > >dyn_port_over_tc flag isn't?
>> > 
>> > The only reason dedicated_external is stored is because VBT data is
>> > already freed by the time intel_encoder_is_tc() is called in the driver
>> > unbind path.  In the future we should fix the VBT lifetime issue in
>> > order to be able to drop the dedicated_external member of dig_port.
>> > 
>> > >
>> > >> +                return true;
>> > >> +
>> > >> +        if (iom_dp_resource_lock(tc))
>> > >> +                return false;
>> > >> +
>> > >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
>> > >> +
>> > >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
>> > >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> > >> +
>> > >> +        /*
>> > >> +         * Bspec instructs to select first available DDI, but our driver is not
>> > >> +         * ready for such dynamic allocation yet. For now, we force a "static"
>> > >> +         * allocation: map the physical port (where HPD happens) to the
>> > >> +         * encoder's DDI (logical TC port, represented by tc_port).
>> > >> +         */
>> > >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
>> > >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> 
>> One more thing occured to me: why can't this allocate any free DDI? IOW
>> does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
>> on which DDI gets allocated (or is there any other dependency on which
>> DDI got allocated)? AFAICS there is no such dependency and the above
>> address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
>> DDI. In that case any free DDI could be allocated here.
>
>Ok, checking this again, DDI_BUF_CTL etc. DDI register addresses will
>depend on the allocated DDI. So nvm the above, the mapping needs to
>stay 1:1 for now until all the DDI reg accesses are converted to index
>the registers with the allocated DDI index.

As far as I understand this, especially after talking with Windows
folks, the allocated DDI will define the port index for the whole
programming, including the registers used to program the PHY - and the
hardware would take care of routing to the correct PHY.

Thus, it appears we would need to do the allocation at hotplug time,
like saying "this PHY will be driven by DDI x".

One of the reasons I think we can't allocate a free DDI at the moment is
that the driver is expecting a 1:1 static mapping for HPD interations.
We will neeed to make the driver aware of the mapping in order to use
the correct encoder when handling HPD events.

--
Gustavo Sousa

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-17 15:02           ` Gustavo Sousa
@ 2025-11-17 15:17             ` Imre Deak
  2025-11-17 17:23               ` Gustavo Sousa
  0 siblings, 1 reply; 48+ messages in thread
From: Imre Deak @ 2025-11-17 15:17 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

On Mon, Nov 17, 2025 at 12:02:37PM -0300, Gustavo Sousa wrote:
> [...]
> >> > >> +        if (iom_dp_resource_lock(tc))
> >> > >> +                return false;
> >> > >> +
> >> > >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> >> > >> +
> >> > >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> >> > >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> > >> +
> >> > >> +        /*
> >> > >> +         * Bspec instructs to select first available DDI, but our driver is not
> >> > >> +         * ready for such dynamic allocation yet. For now, we force a "static"
> >> > >> +         * allocation: map the physical port (where HPD happens) to the
> >> > >> +         * encoder's DDI (logical TC port, represented by tc_port).
> >> > >> +         */
> >> > >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> >> > >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> 
> >> One more thing occured to me: why can't this allocate any free DDI? IOW
> >> does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
> >> on which DDI gets allocated (or is there any other dependency on which
> >> DDI got allocated)? AFAICS there is no such dependency and the above
> >> address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
> >> DDI. In that case any free DDI could be allocated here.
> >
> >Ok, checking this again, DDI_BUF_CTL etc. DDI register addresses will
> >depend on the allocated DDI. So nvm the above, the mapping needs to
> >stay 1:1 for now until all the DDI reg accesses are converted to index
> >the registers with the allocated DDI index.
> 
> As far as I understand this, especially after talking with Windows
> folks, the allocated DDI will define the port index for the whole
> programming, including the registers used to program the PHY - and the
> hardware would take care of routing to the correct PHY.

Correct, that's how I also understood it after "checking this again".

> Thus, it appears we would need to do the allocation at hotplug time,
> like saying "this PHY will be driven by DDI x".

To clarify, if the mapping is 1:1, as in this patch, the allocation can
be done statically during driver loading as discussed earlier. This is
the only way it will work atm, because the DDI allocation cannot fail
during runtime.

> One of the reasons I think we can't allocate a free DDI at the moment is
> that the driver is expecting a 1:1 static mapping for HPD interations.
> We will neeed to make the driver aware of the mapping in order to use
> the correct encoder when handling HPD events.

Again clarifying, that the above is true only for legacy connectors. IOW
for a TBT/DP-alt connector, where IOM does the DDI allocation, the HPD
IRQ delivered to the driver will be already according to the allocated
DDI. That is those connectors are _different_ wrt. to the mapping
requirement than the dynamic legacy connectors, for those TBT/DP-alt
connectors the DDI registers will be accessed based on the
tc_port/encoder->port to which the HPD IRQ is delivered.

> --
> Gustavo Sousa

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-15  0:40       ` Imre Deak
  2025-11-15  1:22         ` Imre Deak
@ 2025-11-17 15:33         ` Gustavo Sousa
  2025-11-17 16:01           ` Imre Deak
  1 sibling, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-17 15:33 UTC (permalink / raw)
  To: Imre Deak
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

Quoting Imre Deak (2025-11-14 21:40:24-03:00)
>On Fri, Nov 14, 2025 at 04:46:29PM -0300, Gustavo Sousa wrote:
>> Quoting Imre Deak (2025-11-12 14:53:47-03:00)
>> >On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
>> >> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
>> >> the DDI (TC ones) port to drive a legacy connection on the Type-C
>> >> subsystem.  This allows better resource utilization, because now there
>> >> is no need to statically reserve ports for legacy connectors on the
>> >> Type-C subsystem.
>> >> 
>> >> That said, our driver is not yet ready for the dynamic allocation.
>> >> Thus, as an incremental step, let's add the logic containing the
>> >> required programming sequence for the allocation, but, instead of
>> >> selecting the first available port, we try so use the 1:1 mapping
>> >> expected by the driver today.
>> >> 
>> >> Bspec: 68954
>> >> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> >> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
>> >> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
>> >> ---
>> >> 
>> >> NOTE: This patch is still a WIP. There are some opens to resolve here.
>> >> Nevertheless, I'm sending it here for early feedback.
>> >> 
>> >> For the HIP-index stuff, I have a local refactor started and need to
>> >> finish it up and send it.
>> >> 
>> >> The other open is about concurrent calls to iom_dp_resource_lock().  It
>> >> is likely that we need to have a software lock to prevent concurrent
>> >> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
>> >> ---
>> >>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
>> >>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
>> >>  2 files changed, 169 insertions(+), 2 deletions(-)
>> >> 
>> >> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> >> index 89ea0156ee06..0cf7d43ce210 100644
>> >> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
>> >> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
>> >> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
>> >>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
>> >>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
>> >>  
>> >> +/*
>> >> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
>> >> + * We need to consolidate the definitions.
>> >> + */
>> >> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
>> >> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
>> >> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
>> >> +
>> >> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
>> >> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
>> >> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
>> >> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
>> >> +
>> >> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
>> >> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
>> >> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> >> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
>> >> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
>> >
>> >It would be simpler to define the above without the shift, i.e. as 8 +
>> >tc_port.
>> 
>> You mean something like this?
>> 
>> #define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))
>> 
>> ?
>> 
>> Yeah... Looking at the code, we wouldn't need to shift back when
>> defining expected_consumer.
>
>Yes.
>
>> 
>> >
>> >> +
>> >>  #define _TCSS_DDI_STATUS_1                        0x161500
>> >>  #define _TCSS_DDI_STATUS_2                        0x161504
>> >>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
>> >> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
>> >>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
>> >>  
>> >>  
>> >> -
>> >>  #endif /* __INTEL_DISPLAY_REGS_H__ */
>> >> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
>> >> index 7e17ca018748..3c333999bbe4 100644
>> >> --- a/drivers/gpu/drm/i915/display/intel_tc.c
>> >> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
>> >> @@ -9,6 +9,7 @@
>> >>  
>> >>  #include "i915_reg.h"
>> >>  #include "intel_atomic.h"
>> >> +#include "intel_bios.h"
>> >>  #include "intel_cx0_phy_regs.h"
>> >>  #include "intel_ddi.h"
>> >>  #include "intel_de.h"
>> >> @@ -25,6 +26,9 @@
>> >>  #include "intel_modeset_lock.h"
>> >>  #include "intel_tc.h"
>> >>  
>> >> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
>> >> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
>> >
>> >The above param names should make it clear how poll_timeout_us() uses
>> >them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
>> >retry_timeout), but probably even clearer to just drop the defines and
>> >inline the values in the call.
>> 
>> Ack.  I going with the latter.
>> 
>> >
>> >> +
>> >>  enum tc_port_mode {
>> >>          TC_PORT_DISCONNECTED,
>> >>          TC_PORT_TBT_ALT,
>> >> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
>> >>          __tc_cold_unblock(tc, domain, tc_cold_wref);
>> >>  }
>> >>  
>> >> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
>> >> +{
>> >> +        /*
>> >> +         * IOM resource management registers live in the 2nd 4KB page of IOM
>> >> +         * address space. So we need to configure HIP_INDEX_REG0 with the
>> >> +         * correct index.
>> >> +         *
>> >> +         * FIXME: We need to have this and dekel PHY implementation using a
>> >> +         * common abstraction to access registers on the HIP-indexed ranges, and
>> >> +         * this function would then be dropped.
>> >> +         */
>> >> +        intel_de_rmw(display, HIP_INDEX_REG0,
>> >> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
>> >
>> >This matches what intel_dkl_phy.c does, that one also taking the
>> >required lock around the access. At one point the intel_dkl_phy
>> >file/interface could be renamed to intel_tc_reg or similar accordingly.
>> 
>> I have already started a local series that introduces the "HIP-index
>> based registers" abstraction.  I need to go back to finish it up.
>> 
>> The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
>> functions specific to accessing registers behind the HIP-based ranges.
>
>Using intel_hip_reg instead of intel_tc_reg is probably better, but I
>still think the current interface should be just renamed, instead of
>adding a new interface and making the current
>intel_dkl_phy_read/write/rmw() use that new interface.
>
>I went ahead and put the above together now:
>https://github.com/ideak/linux/commits/hip-reg

I didn't take a look yet; will do later.  But, since we are sharing,
here is a squashed and untested version of what I have in my local WIP:

https://gitlab.freedesktop.org/gustavo/kernel/-/commit/25d16a7302d9b1e9b214ccd26943fd7903d4ea11

--
Gustavo Sousa

>
>> 
>> To give an idea, here is a copy/paste of the kerneldoc I currently have
>> in that WIP series:
>> 
>>   | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>>   | new file mode 100644
>>   | index 000000000000..ff2492b8275d
>>   | --- /dev/null
>>   | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
>>   | @@ -0,0 +1,110 @@
>>   | +// SPDX-License-Identifier: MIT
>>   | +/*
>>   | + * Copyright (C) 2025 Intel Corporation
>>   | + */
>>   | +
>>   | +/**
>>   | + * DOC: Display HIP-indexed register access
>>   | + *
>>   | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
>>   | + * configurations in the HIP_INDEX registers provided by the hardware.
>>   | + *
>>   | + * Usually each of the valid 4KB range in that space will be mapped to some IP
>>   | + * block, providing access to registers of that IP. The HIP_INDEX registers
>>   | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
>>   | + * to access data that is beyond the initial 4KB block provided by the target
>>   | + * IP.
>>   | + *
>>   | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
>>   | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
>>   | + * register file, we would need to set the index respective to
>>   | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
>>   | + * window, we would need to set the index to 1.
>>   | + *
>>   | + * For simple read, write or rmw operations on a single register, the
>>   | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
>>   | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
>>   | + * and intel_hip_idx_unlock() internally.
>>   | + *
>>   | + * For other scenarios, then it is necessary to wrap the register accesses
>>   | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
>>   | + * use the MMIO functions provided by intel_de.h. For the latter, the function
>>   | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
>>   | + * correct reg argument to those functions.
>>   | + */
>>   | (...)
>> 
>> >
>> >> +}
>> >> +
>> >> +/*
>> >> + * FIXME: This function also needs to avoid concurrent accesses from the driver
>> >> + * itself, possibly via a software lock.
>> >> + */
>> >> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
>> >> +{
>> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> >> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
>> >> +        int ret;
>> >> +
>> >> +        iom_res_mgmt_prepare_reg_access(display);
>> >> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
>> >> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
>> >
>> >This happens to work, but it's more future proof/bspec conformant to
>> >properly mask the requestor ID field when reading it back.
>> 
>> Agreed.
>> 
>> >
>> >> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
>> >> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
>> >> +
>> >> +        if (ret)
>> >> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
>> >> +                        tc->port_name);
>> >> +
>> >> +        return ret;
>> >> +}
>> >> +
>> >> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
>> >> +{
>> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> >> +
>> >> +        iom_res_mgmt_prepare_reg_access(display);
>> >> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
>> >> +}
>> >> +
>> >> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
>> >> +{
>> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
>> >> +        struct intel_digital_port *dig_port = tc->dig_port;
>> >> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
>> >> +        u32 val;
>> >> +        u32 consumer;
>> >> +        u32 expected_consumer;
>> >> +        bool ret;
>> >> +
>> >> +        if (DISPLAY_VER(display) < 35)
>> >> +                return true;
>> >> +
>> >> +        if (tc->mode != TC_PORT_LEGACY)
>> >> +                return true;
>> >> +
>> >> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
>> >
>> >dedicated_external is stored separately in dig_port, why the "related"
>> >dyn_port_over_tc flag isn't?
>> 
>> The only reason dedicated_external is stored is because VBT data is
>> already freed by the time intel_encoder_is_tc() is called in the driver
>> unbind path.  In the future we should fix the VBT lifetime issue in
>> order to be able to drop the dedicated_external member of dig_port.
>> 
>> >
>> >> +                return true;
>> >> +
>> >> +        if (iom_dp_resource_lock(tc))
>> >> +                return false;
>> >> +
>> >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
>> >> +
>> >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
>> >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> >> +
>> >> +        /*
>> >> +         * Bspec instructs to select first available DDI, but our driver is not
>> >> +         * ready for such dynamic allocation yet. For now, we force a "static"
>> >> +         * allocation: map the physical port (where HPD happens) to the
>> >> +         * encoder's DDI (logical TC port, represented by tc_port).
>> >> +         */
>> >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
>> >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>
>One more thing occured to me: why can't this allocate any free DDI? IOW
>does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
>on which DDI gets allocated (or is there any other dependency on which
>DDI got allocated)? AFAICS there is no such dependency and the above
>address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
>DDI. In that case any free DDI could be allocated here.
>
>> >> +
>> >> +        if (allocate) {
>> >> +                struct intel_encoder *other_encoder;
>> >> +
>> >> +                /*
>> >> +                 * Check if this encoder's DDI is already allocated for another
>> >> +                 * physical port, which could have happened prior to the driver
>> >> +                 * taking over (e.g. GOP).
>> >> +                 */
>> >> +                for_each_intel_encoder(display->drm, other_encoder) {
>> >> +                        enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
>> >> +                        u32 other_consumer;
>> >> +
>> >> +                        if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
>> >> +                                continue;
>> >> +
>> >> +                        other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
>> >> +                        other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
>> >> +                        if (other_consumer == expected_consumer) {
>> >> +                                drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
>> >> +                                        tc->port_name, expected_consumer, val);
>> >> +                                ret = false;
>> >> +                                goto out_resource_unlock;
>> >> +                        }
>> >> +                }
>> >> +
>> >> +                if (consumer == 0) {
>> >> +                        /* DDI is free to use, let's allocate it. */
>> >> +                        val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
>> >> +                        val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
>> >> +                        intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
>> >> +                        ret = true;
>> >> +                } else if (consumer == expected_consumer) {
>> >> +                        /*
>> >> +                         * Nothing to do, as the expected "static" DDI allocation is
>> >> +                         * already in place.
>> >> +                         */
>> >> +                        ret = true;
>> >> +                } else {
>> >> +                        drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
>> >> +                                tc->port_name, consumer, val);
>> >> +                        ret = false;
>> >> +                }
>> >> +        } else {
>> >> +                drm_WARN_ON(display->drm, consumer != expected_consumer);
>> >> +                val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
>> >> +                intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
>> >> +                ret = true;
>> >> +        }
>> >> +
>> >> +out_resource_unlock:
>> >> +        iom_dp_resource_unlock(tc);
>> >> +
>> >> +        return ret;
>> >> +}
>> >> +
>> >>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>> >>  {
>> >>          tc->lock_wakeref = tc_cold_block(tc);
>> >> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>> >>                  return true;
>> >>          }
>> >>  
>> >> -        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
>> >> +        if (!xe3p_tc_iom_allocate_ddi(tc, true))
>> >
>> >This doesn't work. A connector registered to userspace must be always
>> >functional (except for MST connectors which are dynamically registered).
>> >So the DDI allocation and with that connecting the PHY cannot fail here
>> >for a legacy connector/PHY. Instead of this the allocation could be
>> >moved to happen already in intel_tc_phy_ops::init for now, allocating a
>> >DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
>> >fails also fail the corresponding connector/encoder registration in
>> >intel_ddi_init(). The DDI would need to be released by
>> >intel_tc_port_cleanup().
>> 
>> Ah, I see.  Well, I guess for legacy connections, doing your suggestion
>> seems fine.
>> 
>> Is there any power management aspect that we should be aware here? Like,
>> some power well being disabled and causing the allocation to be "lost"
>> somehow.  Since this thing is in the TCSS, I think no display power
>> wells could cause that, right?
>
>It would make sense to me that the allocations are preserved by the
>HW/FW across power transitions. If that's not the case then they should
>be restored by the driver.
>
>> By the way, I wonder how we would handle things in the future when/if we
>> enable the dynamic DDI allocation thing.
>
>In case of a DDI allocation failure, the modeset will still succeed, but
>the corresponding port/pipe will not get enabled.
>
>> --
>> Gustavo Sousa
>> 
>> >
>> >>                  goto out_unblock_tccold;
>> >>  
>> >> +        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
>> >> +                goto out_deallocate_ddi;
>> >> +
>> >>          xelpdp_tc_phy_take_ownership(tc, true);
>> >>  
>> >>          read_pin_configuration(tc);
>> >> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
>> >>          xelpdp_tc_phy_take_ownership(tc, false);
>> >>          xelpdp_tc_phy_wait_for_tcss_power(tc, false);
>> >>  
>> >> +out_deallocate_ddi:
>> >> +        xe3p_tc_iom_allocate_ddi(tc, false);
>> >> +
>> >>  out_unblock_tccold:
>> >>          tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
>> >>  
>> >> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
>> >>  {
>> >>          switch (tc->mode) {
>> >>          case TC_PORT_LEGACY:
>> >> +                xe3p_tc_iom_allocate_ddi(tc, false);
>> >> +                fallthrough;
>> >>          case TC_PORT_DP_ALT:
>> >>                  xelpdp_tc_phy_take_ownership(tc, false);
>> >>                  xelpdp_tc_phy_enable_tcss_power(tc, false);
>> >> 
>> >> -- 
>> >> 2.51.0
>> >>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-17 15:33         ` Gustavo Sousa
@ 2025-11-17 16:01           ` Imre Deak
  0 siblings, 0 replies; 48+ messages in thread
From: Imre Deak @ 2025-11-17 16:01 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: intel-xe, intel-gfx, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Jouni Högander, Juha-pekka Heikkila, Luca Coelho,
	Lucas De Marchi, Matt Atwood, Matt Roper, Ravi Kumar Vodapalli,
	Shekhar Chauhan, Vinod Govindapillai

On Mon, Nov 17, 2025 at 12:33:02PM -0300, Gustavo Sousa wrote:
> Quoting Imre Deak (2025-11-14 21:40:24-03:00)
> >On Fri, Nov 14, 2025 at 04:46:29PM -0300, Gustavo Sousa wrote:
> >> Quoting Imre Deak (2025-11-12 14:53:47-03:00)
> >> >On Fri, Nov 07, 2025 at 09:05:40PM -0300, Gustavo Sousa wrote:
> >> >> Xe3p_LPD has a new feature that allows the driver to allocate at runtime
> >> >> the DDI (TC ones) port to drive a legacy connection on the Type-C
> >> >> subsystem.  This allows better resource utilization, because now there
> >> >> is no need to statically reserve ports for legacy connectors on the
> >> >> Type-C subsystem.
> >> >> 
> >> >> That said, our driver is not yet ready for the dynamic allocation.
> >> >> Thus, as an incremental step, let's add the logic containing the
> >> >> required programming sequence for the allocation, but, instead of
> >> >> selecting the first available port, we try so use the 1:1 mapping
> >> >> expected by the driver today.
> >> >> 
> >> >> Bspec: 68954
> >> >> Co-developed-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> >> >> Signed-off-by: Dnyaneshwar Bhadane <dnyaneshwar.bhadane@intel.com>
> >> >> Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
> >> >> ---
> >> >> 
> >> >> NOTE: This patch is still a WIP. There are some opens to resolve here.
> >> >> Nevertheless, I'm sending it here for early feedback.
> >> >> 
> >> >> For the HIP-index stuff, I have a local refactor started and need to
> >> >> finish it up and send it.
> >> >> 
> >> >> The other open is about concurrent calls to iom_dp_resource_lock().  It
> >> >> is likely that we need to have a software lock to prevent concurrent
> >> >> access to IOM_DP_HW_RESOURCE_SEMAPHORE from our driver.
> >> >> ---
> >> >>  drivers/gpu/drm/i915/display/intel_display_regs.h |  20 ++-
> >> >>  drivers/gpu/drm/i915/display/intel_tc.c           | 151 +++++++++++++++++++++-
> >> >>  2 files changed, 169 insertions(+), 2 deletions(-)
> >> >> 
> >> >> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> >> index 89ea0156ee06..0cf7d43ce210 100644
> >> >> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> >> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> >> >> @@ -2908,6 +2908,25 @@ enum skl_power_gate {
> >> >>  #define   DP_PIN_ASSIGNMENT(idx, x)                ((x) << ((idx) * 4))
> >> >>  /* See enum intel_tc_pin_assignment for the pin assignment field values. */
> >> >>  
> >> >> +/*
> >> >> + * FIXME: There is also a definition for this register in intel_dkl_phy_regs.h.
> >> >> + * We need to consolidate the definitions.
> >> >> + */
> >> >> +#define HIP_INDEX_REG0                                _MMIO(0x1010a0)
> >> >> +#define   HIP_168_INDEX_MASK                        REG_GENMASK(3, 0)
> >> >> +#define   HIP_168_IOM_RES_MGMT                        REG_FIELD_PREP(HIP_168_INDEX_MASK, 0x1)
> >> >> +
> >> >> +#define IOM_DP_HW_RESOURCE_SEMAPHORE                _MMIO(0x168038)
> >> >> +#define   IOM_DP_HW_SEMLOCK                        REG_BIT(31)
> >> >> +#define   IOM_REQUESTOR_ID_MASK                        REG_GENMASK(3, 0)
> >> >> +#define   IOM_REQUESTOR_ID_DISPLAY_ENGINE        REG_FIELD_PREP(IOM_REQUESTOR_ID_MASK, 0x4)
> >> >> +
> >> >> +#define IOM_DP_RESOURCE_MNG                        _MMIO(0x16802c)
> >> >> +#define   IOM_DDI_CONSUMER_SHIFT(tc_port)        ((tc_port) * 4)
> >> >> +#define   IOM_DDI_CONSUMER_MASK(tc_port)        (0xf << IOM_DDI_CONSUMER_SHIFT(tc_port))
> >> >> +#define   IOM_DDI_CONSUMER(tc_port, x)                ((x) << IOM_DDI_CONSUMER_SHIFT(tc_port))
> >> >> +#define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        IOM_DDI_CONSUMER(tc_port, 0x8 + (tc_port))
> >> >
> >> >It would be simpler to define the above without the shift, i.e. as 8 +
> >> >tc_port.
> >> 
> >> You mean something like this?
> >> 
> >> #define   IOM_DDI_CONSUMER_STATIC_TC(tc_port)        (0x8 + (tc_port))
> >> 
> >> ?
> >> 
> >> Yeah... Looking at the code, we wouldn't need to shift back when
> >> defining expected_consumer.
> >
> >Yes.
> >
> >> 
> >> >
> >> >> +
> >> >>  #define _TCSS_DDI_STATUS_1                        0x161500
> >> >>  #define _TCSS_DDI_STATUS_2                        0x161504
> >> >>  #define TCSS_DDI_STATUS(tc)                        _MMIO(_PICK_EVEN(tc, \
> >> >> @@ -2946,5 +2965,4 @@ enum skl_power_gate {
> >> >>  #define   MTL_TRDPRE_MASK                REG_GENMASK(7, 0)
> >> >>  
> >> >>  
> >> >> -
> >> >>  #endif /* __INTEL_DISPLAY_REGS_H__ */
> >> >> diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
> >> >> index 7e17ca018748..3c333999bbe4 100644
> >> >> --- a/drivers/gpu/drm/i915/display/intel_tc.c
> >> >> +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> >> >> @@ -9,6 +9,7 @@
> >> >>  
> >> >>  #include "i915_reg.h"
> >> >>  #include "intel_atomic.h"
> >> >> +#include "intel_bios.h"
> >> >>  #include "intel_cx0_phy_regs.h"
> >> >>  #include "intel_ddi.h"
> >> >>  #include "intel_de.h"
> >> >> @@ -25,6 +26,9 @@
> >> >>  #include "intel_modeset_lock.h"
> >> >>  #include "intel_tc.h"
> >> >>  
> >> >> +#define IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US        10
> >> >> +#define IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US        10000
> >> >
> >> >The above param names should make it clear how poll_timeout_us() uses
> >> >them (i.e. stg like sleep vs. timeout instead of lock_timeout vs.
> >> >retry_timeout), but probably even clearer to just drop the defines and
> >> >inline the values in the call.
> >> 
> >> Ack.  I going with the latter.
> >> 
> >> >
> >> >> +
> >> >>  enum tc_port_mode {
> >> >>          TC_PORT_DISCONNECTED,
> >> >>          TC_PORT_TBT_ALT,
> >> >> @@ -1200,6 +1204,143 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
> >> >>          __tc_cold_unblock(tc, domain, tc_cold_wref);
> >> >>  }
> >> >>  
> >> >> +static void iom_res_mgmt_prepare_reg_access(struct intel_display *display)
> >> >> +{
> >> >> +        /*
> >> >> +         * IOM resource management registers live in the 2nd 4KB page of IOM
> >> >> +         * address space. So we need to configure HIP_INDEX_REG0 with the
> >> >> +         * correct index.
> >> >> +         *
> >> >> +         * FIXME: We need to have this and dekel PHY implementation using a
> >> >> +         * common abstraction to access registers on the HIP-indexed ranges, and
> >> >> +         * this function would then be dropped.
> >> >> +         */
> >> >> +        intel_de_rmw(display, HIP_INDEX_REG0,
> >> >> +                     HIP_168_INDEX_MASK, HIP_168_IOM_RES_MGMT);
> >> >
> >> >This matches what intel_dkl_phy.c does, that one also taking the
> >> >required lock around the access. At one point the intel_dkl_phy
> >> >file/interface could be renamed to intel_tc_reg or similar accordingly.
> >> 
> >> I have already started a local series that introduces the "HIP-index
> >> based registers" abstraction.  I need to go back to finish it up.
> >> 
> >> The basic idea is that both intel_dkl_phy.c and this IOM stuff would use
> >> functions specific to accessing registers behind the HIP-based ranges.
> >
> >Using intel_hip_reg instead of intel_tc_reg is probably better, but I
> >still think the current interface should be just renamed, instead of
> >adding a new interface and making the current
> >intel_dkl_phy_read/write/rmw() use that new interface.
> >
> >I went ahead and put the above together now:
> >https://github.com/ideak/linux/commits/hip-reg
> 
> I didn't take a look yet; will do later.  But, since we are sharing,
> here is a squashed and untested version of what I have in my local WIP:
> 
> https://gitlab.freedesktop.org/gustavo/kernel/-/commit/25d16a7302d9b1e9b214ccd26943fd7903d4ea11

I'm not sure if having a separate set of 

intel_hip_idx_reg_{read,write,rmw,posting_read}
and
intel_dkl_phy_{read,write,rmw,posting_read}

functions is justified. Then you'd also need to add the same set of
functions for IOM registers or any other HW block using the same HIP
register indexing.

Even when adding separate set of functions, I wouldn't reimplement
something that already exists, if the end result practically matches the
current implementation anyway. I'd still go with renaming the current
intel_dkl_phy_* interface to intel_hip_reg_*, adding then the DKL, etc.
set of functions as wrappers, as in:

https://github.com/ideak/linux/commit/e325c4d43e80f18

in the

https://github.com/ideak/linux/commits/hip-reg-dkl-phy-wrapper

branch.

> 
> --
> Gustavo Sousa
> 
> >
> >> 
> >> To give an idea, here is a copy/paste of the kerneldoc I currently have
> >> in that WIP series:
> >> 
> >>   | diff --git a/drivers/gpu/drm/i915/display/intel_hip_idx.c b/drivers/gpu/drm/i915/display/intel_hip_idx.c
> >>   | new file mode 100644
> >>   | index 000000000000..ff2492b8275d
> >>   | --- /dev/null
> >>   | +++ b/drivers/gpu/drm/i915/display/intel_hip_idx.c
> >>   | @@ -0,0 +1,110 @@
> >>   | +// SPDX-License-Identifier: MIT
> >>   | +/*
> >>   | + * Copyright (C) 2025 Intel Corporation
> >>   | + */
> >>   | +
> >>   | +/**
> >>   | + * DOC: Display HIP-indexed register access
> >>   | + *
> >>   | + * Display MMIO mapping for offsets in [0x168000,0x16ffff] are governed by
> >>   | + * configurations in the HIP_INDEX registers provided by the hardware.
> >>   | + *
> >>   | + * Usually each of the valid 4KB range in that space will be mapped to some IP
> >>   | + * block, providing access to registers of that IP. The HIP_INDEX registers
> >>   | + * expose an 8-bit index value for each 4KB range. Those indices provide a way
> >>   | + * to access data that is beyond the initial 4KB block provided by the target
> >>   | + * IP.
> >>   | + *
> >>   | + * As an example, say that the range [0x16a000,0x16afff] is mapped to some
> >>   | + * sub-IP that contains a 8KB register file. To access the initial 4KB of that
> >>   | + * register file, we would need to set the index respective to
> >>   | + * [0x16a000,0x16afff] in HIP_INDEX to 0; to access data in the second 4KB
> >>   | + * window, we would need to set the index to 1.
> >>   | + *
> >>   | + * For simple read, write or rmw operations on a single register, the
> >>   | + * functions intel_hip_idx_reg_read(), intel_hip_idx_reg_write() and
> >>   | + * intel_hip_idx_reg_rmw() can be used, which will call intel_hip_idx_lock()
> >>   | + * and intel_hip_idx_unlock() internally.
> >>   | + *
> >>   | + * For other scenarios, then it is necessary to wrap the register accesses
> >>   | + * with explicit calls to intel_hip_idx_lock() and intel_hip_idx_unlock(), and
> >>   | + * use the MMIO functions provided by intel_de.h. For the latter, the function
> >>   | + * intel_hip_idx_reg_to_i915_reg() needs to be used in order to provide the
> >>   | + * correct reg argument to those functions.
> >>   | + */
> >>   | (...)
> >> 
> >> >
> >> >> +}
> >> >> +
> >> >> +/*
> >> >> + * FIXME: This function also needs to avoid concurrent accesses from the driver
> >> >> + * itself, possibly via a software lock.
> >> >> + */
> >> >> +static int iom_dp_resource_lock(struct intel_tc_port *tc)
> >> >> +{
> >> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> >> +        u32 val = IOM_DP_HW_SEMLOCK | IOM_REQUESTOR_ID_DISPLAY_ENGINE;
> >> >> +        int ret;
> >> >> +
> >> >> +        iom_res_mgmt_prepare_reg_access(display);
> >> >> +        ret = poll_timeout_us(intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, val),
> >> >> +                              (intel_de_read(display, IOM_DP_HW_RESOURCE_SEMAPHORE) & val) == val,
> >> >
> >> >This happens to work, but it's more future proof/bspec conformant to
> >> >properly mask the requestor ID field when reading it back.
> >> 
> >> Agreed.
> >> 
> >> >
> >> >> +                              IOM_DP_RES_SEMAPHORE_LOCK_TIMEOUT_US,
> >> >> +                              IOM_DP_RES_SEMAPHORE_RETRY_TIMEOUT_US, false);
> >> >> +
> >> >> +        if (ret)
> >> >> +                drm_err(display->drm, "Port %s: timeout trying to lock IOM semaphore\n",
> >> >> +                        tc->port_name);
> >> >> +
> >> >> +        return ret;
> >> >> +}
> >> >> +
> >> >> +static void iom_dp_resource_unlock(struct intel_tc_port *tc)
> >> >> +{
> >> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> >> +
> >> >> +        iom_res_mgmt_prepare_reg_access(display);
> >> >> +        intel_de_write(display, IOM_DP_HW_RESOURCE_SEMAPHORE, IOM_REQUESTOR_ID_DISPLAY_ENGINE);
> >> >> +}
> >> >> +
> >> >> +static bool xe3p_tc_iom_allocate_ddi(struct intel_tc_port *tc, bool allocate)
> >> >> +{
> >> >> +        struct intel_display *display = to_intel_display(tc->dig_port);
> >> >> +        struct intel_digital_port *dig_port = tc->dig_port;
> >> >> +        enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
> >> >> +        u32 val;
> >> >> +        u32 consumer;
> >> >> +        u32 expected_consumer;
> >> >> +        bool ret;
> >> >> +
> >> >> +        if (DISPLAY_VER(display) < 35)
> >> >> +                return true;
> >> >> +
> >> >> +        if (tc->mode != TC_PORT_LEGACY)
> >> >> +                return true;
> >> >> +
> >> >> +        if (!intel_bios_encoder_supports_dyn_port_over_tc(dig_port->base.devdata))
> >> >
> >> >dedicated_external is stored separately in dig_port, why the "related"
> >> >dyn_port_over_tc flag isn't?
> >> 
> >> The only reason dedicated_external is stored is because VBT data is
> >> already freed by the time intel_encoder_is_tc() is called in the driver
> >> unbind path.  In the future we should fix the VBT lifetime issue in
> >> order to be able to drop the dedicated_external member of dig_port.
> >> 
> >> >
> >> >> +                return true;
> >> >> +
> >> >> +        if (iom_dp_resource_lock(tc))
> >> >> +                return false;
> >> >> +
> >> >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> >> >> +
> >> >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> >> >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> >> +
> >> >> +        /*
> >> >> +         * Bspec instructs to select first available DDI, but our driver is not
> >> >> +         * ready for such dynamic allocation yet. For now, we force a "static"
> >> >> +         * allocation: map the physical port (where HPD happens) to the
> >> >> +         * encoder's DDI (logical TC port, represented by tc_port).
> >> >> +         */
> >> >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> >> >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >
> >One more thing occured to me: why can't this allocate any free DDI? IOW
> >does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
> >on which DDI gets allocated (or is there any other dependency on which
> >DDI got allocated)? AFAICS there is no such dependency and the above
> >address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
> >DDI. In that case any free DDI could be allocated here.
> >
> >> >> +
> >> >> +        if (allocate) {
> >> >> +                struct intel_encoder *other_encoder;
> >> >> +
> >> >> +                /*
> >> >> +                 * Check if this encoder's DDI is already allocated for another
> >> >> +                 * physical port, which could have happened prior to the driver
> >> >> +                 * taking over (e.g. GOP).
> >> >> +                 */
> >> >> +                for_each_intel_encoder(display->drm, other_encoder) {
> >> >> +                        enum tc_port other_tc_port = intel_encoder_to_tc(other_encoder);
> >> >> +                        u32 other_consumer;
> >> >> +
> >> >> +                        if (tc_port == TC_PORT_NONE || other_tc_port == tc_port)
> >> >> +                                continue;
> >> >> +
> >> >> +                        other_consumer = val & IOM_DDI_CONSUMER_MASK(other_tc_port);
> >> >> +                        other_consumer >>= IOM_DDI_CONSUMER_SHIFT(other_tc_port);
> >> >> +                        if (other_consumer == expected_consumer) {
> >> >> +                                drm_err(display->drm, "Port %s: expected consumer %u already allocated another DDI; IOM_DP_RESOURCE_MNG=0x%08x\n",
> >> >> +                                        tc->port_name, expected_consumer, val);
> >> >> +                                ret = false;
> >> >> +                                goto out_resource_unlock;
> >> >> +                        }
> >> >> +                }
> >> >> +
> >> >> +                if (consumer == 0) {
> >> >> +                        /* DDI is free to use, let's allocate it. */
> >> >> +                        val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> >> >> +                        val |= IOM_DDI_CONSUMER(tc_port, expected_consumer);
> >> >> +                        intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> >> >> +                        ret = true;
> >> >> +                } else if (consumer == expected_consumer) {
> >> >> +                        /*
> >> >> +                         * Nothing to do, as the expected "static" DDI allocation is
> >> >> +                         * already in place.
> >> >> +                         */
> >> >> +                        ret = true;
> >> >> +                } else {
> >> >> +                        drm_err(display->drm, "Port %s: DDI already allocated for consumer %u; IOM_DP_RESOURCE_MNG=0x%08x\n",
> >> >> +                                tc->port_name, consumer, val);
> >> >> +                        ret = false;
> >> >> +                }
> >> >> +        } else {
> >> >> +                drm_WARN_ON(display->drm, consumer != expected_consumer);
> >> >> +                val &= ~IOM_DDI_CONSUMER_MASK(tc_port);
> >> >> +                intel_de_write(display, IOM_DP_RESOURCE_MNG, val);
> >> >> +                ret = true;
> >> >> +        }
> >> >> +
> >> >> +out_resource_unlock:
> >> >> +        iom_dp_resource_unlock(tc);
> >> >> +
> >> >> +        return ret;
> >> >> +}
> >> >> +
> >> >>  static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >> >>  {
> >> >>          tc->lock_wakeref = tc_cold_block(tc);
> >> >> @@ -1210,9 +1351,12 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >> >>                  return true;
> >> >>          }
> >> >>  
> >> >> -        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> >> >> +        if (!xe3p_tc_iom_allocate_ddi(tc, true))
> >> >
> >> >This doesn't work. A connector registered to userspace must be always
> >> >functional (except for MST connectors which are dynamically registered).
> >> >So the DDI allocation and with that connecting the PHY cannot fail here
> >> >for a legacy connector/PHY. Instead of this the allocation could be
> >> >moved to happen already in intel_tc_phy_ops::init for now, allocating a
> >> >DDI for a legacy PHY (intel_tc_port::legacy_port == true) and if that
> >> >fails also fail the corresponding connector/encoder registration in
> >> >intel_ddi_init(). The DDI would need to be released by
> >> >intel_tc_port_cleanup().
> >> 
> >> Ah, I see.  Well, I guess for legacy connections, doing your suggestion
> >> seems fine.
> >> 
> >> Is there any power management aspect that we should be aware here? Like,
> >> some power well being disabled and causing the allocation to be "lost"
> >> somehow.  Since this thing is in the TCSS, I think no display power
> >> wells could cause that, right?
> >
> >It would make sense to me that the allocations are preserved by the
> >HW/FW across power transitions. If that's not the case then they should
> >be restored by the driver.
> >
> >> By the way, I wonder how we would handle things in the future when/if we
> >> enable the dynamic DDI allocation thing.
> >
> >In case of a DDI allocation failure, the modeset will still succeed, but
> >the corresponding port/pipe will not get enabled.
> >
> >> --
> >> Gustavo Sousa
> >> 
> >> >
> >> >>                  goto out_unblock_tccold;
> >> >>  
> >> >> +        if (!xelpdp_tc_phy_enable_tcss_power(tc, true))
> >> >> +                goto out_deallocate_ddi;
> >> >> +
> >> >>          xelpdp_tc_phy_take_ownership(tc, true);
> >> >>  
> >> >>          read_pin_configuration(tc);
> >> >> @@ -1226,6 +1370,9 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
> >> >>          xelpdp_tc_phy_take_ownership(tc, false);
> >> >>          xelpdp_tc_phy_wait_for_tcss_power(tc, false);
> >> >>  
> >> >> +out_deallocate_ddi:
> >> >> +        xe3p_tc_iom_allocate_ddi(tc, false);
> >> >> +
> >> >>  out_unblock_tccold:
> >> >>          tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
> >> >>  
> >> >> @@ -1236,6 +1383,8 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
> >> >>  {
> >> >>          switch (tc->mode) {
> >> >>          case TC_PORT_LEGACY:
> >> >> +                xe3p_tc_iom_allocate_ddi(tc, false);
> >> >> +                fallthrough;
> >> >>          case TC_PORT_DP_ALT:
> >> >>                  xelpdp_tc_phy_take_ownership(tc, false);
> >> >>                  xelpdp_tc_phy_enable_tcss_power(tc, false);
> >> >> 
> >> >> -- 
> >> >> 2.51.0
> >> >>

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-17 15:17             ` Imre Deak
@ 2025-11-17 17:23               ` Gustavo Sousa
  2025-11-17 17:58                 ` Imre Deak
  0 siblings, 1 reply; 48+ messages in thread
From: Gustavo Sousa @ 2025-11-17 17:23 UTC (permalink / raw)
  To: Imre Deak
  Cc: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

Quoting Imre Deak (2025-11-17 12:17:48-03:00)
>On Mon, Nov 17, 2025 at 12:02:37PM -0300, Gustavo Sousa wrote:
>> [...]
>> >> > >> +        if (iom_dp_resource_lock(tc))
>> >> > >> +                return false;
>> >> > >> +
>> >> > >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
>> >> > >> +
>> >> > >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
>> >> > >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> >> > >> +
>> >> > >> +        /*
>> >> > >> +         * Bspec instructs to select first available DDI, but our driver is not
>> >> > >> +         * ready for such dynamic allocation yet. For now, we force a "static"
>> >> > >> +         * allocation: map the physical port (where HPD happens) to the
>> >> > >> +         * encoder's DDI (logical TC port, represented by tc_port).
>> >> > >> +         */
>> >> > >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
>> >> > >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
>> >> 
>> >> One more thing occured to me: why can't this allocate any free DDI? IOW
>> >> does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
>> >> on which DDI gets allocated (or is there any other dependency on which
>> >> DDI got allocated)? AFAICS there is no such dependency and the above
>> >> address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
>> >> DDI. In that case any free DDI could be allocated here.
>> >
>> >Ok, checking this again, DDI_BUF_CTL etc. DDI register addresses will
>> >depend on the allocated DDI. So nvm the above, the mapping needs to
>> >stay 1:1 for now until all the DDI reg accesses are converted to index
>> >the registers with the allocated DDI index.
>> 
>> As far as I understand this, especially after talking with Windows
>> folks, the allocated DDI will define the port index for the whole
>> programming, including the registers used to program the PHY - and the
>> hardware would take care of routing to the correct PHY.
>
>Correct, that's how I also understood it after "checking this again".
>
>> Thus, it appears we would need to do the allocation at hotplug time,
>> like saying "this PHY will be driven by DDI x".
>
>To clarify, if the mapping is 1:1, as in this patch, the allocation can
>be done statically during driver loading as discussed earlier. This is
>the only way it will work atm, because the DDI allocation cannot fail
>during runtime.

Two scenarios that come to mind about doing this on probe time:

  1) The driver could be loaded with nothing yet attached to the legacy
     connector.  However, I believe the TCSS doesn't require the
     connector to be attached for the allocation to work.  So, we are
     probably fine here.

  2) If the legacy connector is never used during the driver's lifetime,
     we are basically holding a resource that could have been used by a
     DP-alt/TBT connection.

For the dynamic feature (to be implemented in the future), how to you
see this?

  1) Should we allocate the DDI at HPD time and fail report the
     connector as disconnected on failure?
  2) Should we allocate the DDI as part of the atomic check phase and
     fail the modeset if we can't do it?
  3) Should we allocate the DDI as part of the atomic tail (hardware
     commit) and raise errors if the allocation fails?

Another question: once we implement the dynamic feature, this "allocate
on probe time" thing will have to go away, right?  In that case, we
would basically suffer the same runtime risks that we would be trying to
avoid, no?

Perhaps I'm missing something, but, if not: I wonder if doing the
"allocate on probe time" thing is really worth implementing, since it
will be a "temporary" thing that would be reverted later.  In that case,
we could try implementing the static allocation in the same place where
dynamic allocation would happen.

>
>> One of the reasons I think we can't allocate a free DDI at the moment is
>> that the driver is expecting a 1:1 static mapping for HPD interations.
>> We will neeed to make the driver aware of the mapping in order to use
>> the correct encoder when handling HPD events.
>
>Again clarifying, that the above is true only for legacy connectors. IOW
>for a TBT/DP-alt connector, where IOM does the DDI allocation, the HPD
>IRQ delivered to the driver will be already according to the allocated
>DDI. That is those connectors are _different_ wrt. to the mapping
>requirement than the dynamic legacy connectors, for those TBT/DP-alt
>connectors the DDI registers will be accessed based on the
>tc_port/encoder->port to which the HPD IRQ is delivered.

That's my understanding as well.

--
Gustavo Sousa

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

* Re: [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation
  2025-11-17 17:23               ` Gustavo Sousa
@ 2025-11-17 17:58                 ` Imre Deak
  0 siblings, 0 replies; 48+ messages in thread
From: Imre Deak @ 2025-11-17 17:58 UTC (permalink / raw)
  To: Gustavo Sousa
  Cc: Jouni Högander, Ankit Nautiyal, Dnyaneshwar Bhadane,
	Juha-pekka Heikkila, Luca Coelho, Lucas De Marchi, Matt Atwood,
	Matt Roper, Ravi Kumar Vodapalli, Shekhar Chauhan,
	Vinod Govindapillai, intel-gfx, intel-xe

On Mon, Nov 17, 2025 at 02:23:51PM -0300, Gustavo Sousa wrote:
> Quoting Imre Deak (2025-11-17 12:17:48-03:00)
> >On Mon, Nov 17, 2025 at 12:02:37PM -0300, Gustavo Sousa wrote:
> >> [...]
> >> >> > >> +        if (iom_dp_resource_lock(tc))
> >> >> > >> +                return false;
> >> >> > >> +
> >> >> > >> +        val = intel_de_read(display, IOM_DP_RESOURCE_MNG);
> >> >> > >> +
> >> >> > >> +        consumer = val & IOM_DDI_CONSUMER_MASK(tc_port);
> >> >> > >> +        consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> >> > >> +
> >> >> > >> +        /*
> >> >> > >> +         * Bspec instructs to select first available DDI, but our driver is not
> >> >> > >> +         * ready for such dynamic allocation yet. For now, we force a "static"
> >> >> > >> +         * allocation: map the physical port (where HPD happens) to the
> >> >> > >> +         * encoder's DDI (logical TC port, represented by tc_port).
> >> >> > >> +         */
> >> >> > >> +        expected_consumer = IOM_DDI_CONSUMER_STATIC_TC(tc_port);
> >> >> > >> +        expected_consumer >>= IOM_DDI_CONSUMER_SHIFT(tc_port);
> >> >> 
> >> >> One more thing occured to me: why can't this allocate any free DDI? IOW
> >> >> does the address of DDI_BUF_CTL (aka DDI_CTL_DE) used for tc_port depend
> >> >> on which DDI gets allocated (or is there any other dependency on which
> >> >> DDI got allocated)? AFAICS there is no such dependency and the above
> >> >> address would be DDI_BUF_CTL(encoder->port) regardless of the allocated
> >> >> DDI. In that case any free DDI could be allocated here.
> >> >
> >> >Ok, checking this again, DDI_BUF_CTL etc. DDI register addresses will
> >> >depend on the allocated DDI. So nvm the above, the mapping needs to
> >> >stay 1:1 for now until all the DDI reg accesses are converted to index
> >> >the registers with the allocated DDI index.
> >> 
> >> As far as I understand this, especially after talking with Windows
> >> folks, the allocated DDI will define the port index for the whole
> >> programming, including the registers used to program the PHY - and the
> >> hardware would take care of routing to the correct PHY.
> >
> >Correct, that's how I also understood it after "checking this again".
> >
> >> Thus, it appears we would need to do the allocation at hotplug time,
> >> like saying "this PHY will be driven by DDI x".
> >
> >To clarify, if the mapping is 1:1, as in this patch, the allocation can
> >be done statically during driver loading as discussed earlier. This is
> >the only way it will work atm, because the DDI allocation cannot fail
> >during runtime.
> 
> Two scenarios that come to mind about doing this on probe time:
> 
>   1) The driver could be loaded with nothing yet attached to the legacy
>      connector.  However, I believe the TCSS doesn't require the
>      connector to be attached for the allocation to work.  So, we are
>      probably fine here.
> 
>   2) If the legacy connector is never used during the driver's lifetime,
>      we are basically holding a resource that could have been used by a
>      DP-alt/TBT connection.

Yes, this is also the way how things work at the moment: a legacy
connector reserves a DDI whether or not a sink will be connected to it.
I think keeping that existing behavior for now is what makes sense.

> For the dynamic feature (to be implemented in the future), how to you
> see this?
> 
>   1) Should we allocate the DDI at HPD time and fail report the
>      connector as disconnected on failure?
>   2) Should we allocate the DDI as part of the atomic check phase and
>      fail the modeset if we can't do it?
>   3) Should we allocate the DDI as part of the atomic tail (hardware
>      commit) and raise errors if the allocation fails?

I think the only way for enabling the dynamic allocation of DDIs is to
do that whenever the PHY is used, i.e. when the PHY is connected via
intel_tc_port_lock() or intel_tc_port_get_link(). That's because even
AUX transfers for a detection need an allocated DDI. This is what the
patch is currently doing, however, that can be done only once the
remapping of a connector/encoder -> allocated DDI is in place and the
driver can also handle a modeset on a legacy connector for which the DDI
allocation fails.

> Another question: once we implement the dynamic feature, this "allocate
> on probe time" thing will have to go away, right? 

The allocation would simply have to moved back to happen during
connecting the PHY.

> In that case, we would basically suffer the same runtime risks that we
> would be trying to avoid, no?

No, then the driver will be able to handle a modeset for a legacy
connector without a DDI allocated to it.

> Perhaps I'm missing something, but, if not: I wonder if doing the
> "allocate on probe time" thing is really worth implementing, since it
> will be a "temporary" thing that would be reverted later.  In that case,
> we could try implementing the static allocation in the same place where
> dynamic allocation would happen.

I still think for now it makes sense to implement the allocate on probe
time thing, which is simple enough and provides what we have now (legacy
connectors keep a DDI reserved). Adding support for dynamic DDI
allocations will allow enabling 3 TBT DP tunnels instead of the current
2 DP tunnels for instance, but this requires a lot of changes affecting
current platforms as well. I think moving back the allocation to happen
during connecting the PHY - when the changes for that are in place -
would be also simple.

> >> One of the reasons I think we can't allocate a free DDI at the moment is
> >> that the driver is expecting a 1:1 static mapping for HPD interations.
> >> We will neeed to make the driver aware of the mapping in order to use
> >> the correct encoder when handling HPD events.
> >
> >Again clarifying, that the above is true only for legacy connectors. IOW
> >for a TBT/DP-alt connector, where IOM does the DDI allocation, the HPD
> >IRQ delivered to the driver will be already according to the allocated
> >DDI. That is those connectors are _different_ wrt. to the mapping
> >requirement than the dynamic legacy connectors, for those TBT/DP-alt
> >connectors the DDI registers will be accessed based on the
> >tc_port/encoder->port to which the HPD IRQ is delivered.
> 
> That's my understanding as well.
> 
> --
> Gustavo Sousa

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

end of thread, other threads:[~2025-11-17 17:58 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-08  0:05 [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 01/11] drm/i915/wm: Do not make latency values monotonic on Xe3 onward Gustavo Sousa
2025-11-12  3:46   ` Kandpal, Suraj
2025-11-12 12:45     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 02/11] drm/i915/vbt: Add fields dedicated_external and dyn_port_over_tc Gustavo Sousa
2025-11-11 16:02   ` Imre Deak
2025-11-11 16:15     ` Imre Deak
2025-11-12 13:00       ` Gustavo Sousa
2025-11-12 13:20         ` Imre Deak
2025-11-13 22:01           ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 03/11] drm/i915/power: Use intel_encoder_is_tc() Gustavo Sousa
2025-11-12 16:19   ` Imre Deak
2025-11-13 22:01     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 04/11] drm/i915/display: Handle dedicated external ports in intel_encoder_is_tc() Gustavo Sousa
2025-11-12 16:24   ` Imre Deak
2025-11-13 22:02     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 05/11] drm/i915/fbc: Add intel_fbc_id_for_pipe() Gustavo Sousa
2025-11-10 16:35   ` Matt Roper
2025-11-10 17:03     ` Ville Syrjälä
2025-11-10 22:18       ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 06/11] drm/i915/xe3p_lpd: Handle underrun debug bits Gustavo Sousa
2025-11-10 11:45   ` Jani Nikula
2025-11-11  0:23     ` Gustavo Sousa
2025-11-11 10:22       ` Jani Nikula
2025-11-11 12:22         ` Gustavo Sousa
2025-11-10 17:03   ` Ville Syrjälä
2025-11-10 23:42     ` Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 07/11] drm/i915/xe3p_lpd: Extend Type-C flow for static DDI allocation Gustavo Sousa
2025-11-12 17:53   ` Imre Deak
2025-11-14 19:46     ` Gustavo Sousa
2025-11-15  0:40       ` Imre Deak
2025-11-15  1:22         ` Imre Deak
2025-11-17 15:02           ` Gustavo Sousa
2025-11-17 15:17             ` Imre Deak
2025-11-17 17:23               ` Gustavo Sousa
2025-11-17 17:58                 ` Imre Deak
2025-11-17 15:33         ` Gustavo Sousa
2025-11-17 16:01           ` Imre Deak
2025-11-08  0:05 ` [PATCH v4 08/11] drm/i915/nvls: Add NVL-S display support Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 09/11] drm/i915/display: Use platform check in HAS_LT_PHY() Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 10/11] drm/i915/display: Move HAS_LT_PHY() to intel_display_device.h Gustavo Sousa
2025-11-08  0:05 ` [PATCH v4 11/11] drm/i915/display: Use HAS_LT_PHY() for LT PHY AUX power Gustavo Sousa
2025-11-08  0:15 ` [PATCH v4 00/11] drm/i915/display: Add initial support for Xe3p_LPD Gustavo Sousa
2025-11-08  1:52 ` ✗ CI.checkpatch: warning for drm/i915/display: Add initial support for Xe3p_LPD (rev4) Patchwork
2025-11-08  1:54 ` ✓ CI.KUnit: success " Patchwork
2025-11-08  2:09 ` ✗ CI.checksparse: warning " Patchwork
2025-11-08  2:31 ` ✗ Xe.CI.BAT: failure " Patchwork
2025-11-09  8:10 ` ✗ Xe.CI.Full: " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).