Skip to contentSkip to conversation

FAILED: patch "[PATCH] drm/i915/dp_mst: Fix configuring FEC for a disconnected" failed to apply to 6.12-stable tree

PATCH New [email protected] 2 participants 3 messages Sep 29

Subsystems (4)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x acbe9a3b60b9a6ace8ef11fe898f586251c84592
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092954-aliens-penalty-0786@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From acbe9a3b60b9a6ace8ef11fe898f586251c84592 Mon Sep 17 00:00:00 2001
From: Imre Deak <[email protected]>
Date: Mon, 7 Sep 2026 20:44:12 +0300
Subject: [PATCH] drm/i915/dp_mst: Fix configuring FEC for a disconnected
stream

During an atomic commit after all the MST stream CRTC state is computed the driver ensures that the FEC is configured the same way (enabled or disabled) for all the streams on a given MST topology's link. drm_dp_mst_port_downstream_of_parent() used to determine if a stream is downstream of an MST port will return false if the whole topology is disconnected, since in that case it can't verify that the port/ parent_port passed to it is in the given MST topology. This is a problem during the above FEC configuration check, since intel_dp_mst_check_dsc_change()->get_pipes_downstream_of_mst_ports() will not return all the stream CRTCs/pipes for the topology as expected. Since passing parent_port==NULL to get_pipes_downstream_of_mst_port() is meant to return all the streams for the given topology (i.e. mst_mgr) skip checking if an MST port is downstream of a parent port in this case.

This fixes a problem where the FEC configuration check explained above failed to ensure that all streams' FEC is configured the same way if the topology was disconnected, leading to a FEC state mismatch error.

drivers/gpu/drm/i915/display/intel_dp_mst.c +2 -1
index 57daed0b0b36..9e65b4a1c71d 100644
@@ -852,7 +852,8 @@ static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
 		if (&connector->mst.dp->mst.mgr != mst_mgr)
 			continue;
 
-		if (connector->mst.port != parent_port &&
+		if (parent_port &&
+		    connector->mst.port != parent_port &&
 		    !drm_dp_mst_port_downstream_of_parent(mst_mgr,
 							  connector->mst.port,
 							  parent_port))
maintainer
#1 lore raw

PATCH 1/2 drm/i915/mst: add mst sub-struct to struct intel_dp

From: Jani Nikula <[email protected]>

[ Upstream commit abf874a328a885592a6bfe6f7db463974e14b615 ]

Move active_mst_links, mst_encoders[], and mst_mgr members of struct intel_dp under an mst sub-struct to group mst related things together.

Rename them active_links, stream_encoders[] and mgr for clarity.

Note that is_mst and mst_detect are not included, as they're also relevant for non-mst. The sub-struct is for active mst.

[ Backport to 6.12: retain the stable MST implementations, i915
device references, bandwidth calculations and helper signatures. Update the corresponding field accesses in those implementations instead of importing newer upstream refactors.

Fold in the connector MST field grouping from aa389adeaa856 ("drm/i915/mst: add mst sub-struct to struct intel_connector"), including the stable-only users in link training and PSR. This provides connector->mst.dp and connector->mst.port as required by acbe9a3b60b9 ("drm/i915/dp_mst: Fix configuring FEC for a disconnected stream"), so that target applies unchanged. No functions or behavioral changes are introduced here. ]

Stable-dep-of: acbe9a3b60b9 ("drm/i915/dp_mst: Fix configuring FEC for a disconnected stream")

---
 .../gpu/drm/i915/display/intel_connector.c    |   4 +-
 drivers/gpu/drm/i915/display/intel_ddi.c      |   4 +-
 .../drm/i915/display/intel_display_debugfs.c  |   8 +-
 .../drm/i915/display/intel_display_types.h    |  18 +-
 drivers/gpu/drm/i915/display/intel_dp.c       |  36 ++--
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  |   6 +-
 .../drm/i915/display/intel_dp_link_training.c |   4 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 154 +++++++++---------
 drivers/gpu/drm/i915/display/intel_hdcp.c     |   8 +-
 drivers/gpu/drm/i915/display/intel_psr.c      |   2 +-
 10 files changed, 123 insertions(+), 121 deletions(-)
drivers/gpu/drm/i915/display/intel_connector.c +2 -2
index c65887870ddc2..6143a9625e5e2 100644
@@ -103,8 +103,8 @@ void intel_connector_destroy(struct drm_connector *connector)
 
 	drm_connector_cleanup(connector);
 
-	if (intel_connector->port)
-		drm_dp_mst_put_port_malloc(intel_connector->port);
+	if (intel_connector->mst.port)
+		drm_dp_mst_put_port_malloc(intel_connector->mst.port);
 
 	kfree(connector);
 }
drivers/gpu/drm/i915/display/intel_ddi.c +2 -2
index 5b24460c01341..0eace4d21d5da 100644
@@ -2585,7 +2585,7 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	 * Train Display Port" step.  Note that steps that are specific to
 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
-	 * us when active_mst_links==0, so any steps designated for "single
+	 * us when mst.active_links==0, so any steps designated for "single
 	 * stream or multi-stream master transcoder" can just be performed
 	 * unconditionally here.
 	 *
@@ -2674,7 +2674,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	 * Train Display Port" step.  Note that steps that are specific to
 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
-	 * us when active_mst_links==0, so any steps designated for "single
+	 * us when mst.active_links==0, so any steps designated for "single
 	 * stream or multi-stream master transcoder" can just be performed
 	 * unconditionally here.
 	 */
drivers/gpu/drm/i915/display/intel_display_debugfs.c +4 -4
index f5f618199d398..c6e98bb57827c 100644
@@ -275,7 +275,7 @@ static void intel_connector_info(struct seq_file *m,
 	switch (connector->connector_type) {
 	case DRM_MODE_CONNECTOR_DisplayPort:
 	case DRM_MODE_CONNECTOR_eDP:
-		if (intel_connector->mst_port)
+		if (intel_connector->mst.dp)
 			intel_dp_mst_info(m, intel_connector);
 		else
 			intel_dp_info(m, intel_connector);
@@ -288,7 +288,7 @@ static void intel_connector_info(struct seq_file *m,
 	}
 
 	seq_puts(m, "\tHDCP version: ");
-	if (intel_connector->mst_port) {
+	if (intel_connector->mst.dp) {
 		intel_hdcp_info(m, intel_connector, true);
 		seq_puts(m, "\tMST Hub HDCP version: ");
 	}
@@ -766,7 +766,7 @@ static int i915_dp_mst_info(struct seq_file *m, void *unused)
 		seq_printf(m, "MST Source Port [ENCODER:%d:%s]\n",
 			   dig_port->base.base.base.id,
 			   dig_port->base.base.name);
-		drm_dp_mst_dump_topology(m, &dig_port->dp.mst_mgr);
+		drm_dp_mst_dump_topology(m, &dig_port->dp.mst.mgr);
 	}
 	drm_connector_list_iter_end(&conn_iter);
 
@@ -1533,7 +1533,7 @@ void intel_connector_debugfs_add(struct intel_connector *connector)
 	}
 
 	if (DISPLAY_VER(i915) >= 11 &&
-	    ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst_port) ||
+	    ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst.dp) ||
 	     connector_type == DRM_MODE_CONNECTOR_eDP)) {
 		debugfs_create_file("i915_dsc_fec_support", 0644, root,
 				    connector, &i915_dsc_fec_support_fops);
drivers/gpu/drm/i915/display/intel_display_types.h +10 -8
index 992945b37190e..af44a9124bb05 100644
@@ -647,10 +647,6 @@ struct intel_connector {
 	   state of connector->polled in case hotplug storm detection changes it */
 	u8 polled;
 
-	struct drm_dp_mst_port *port;
-
-	struct intel_dp *mst_port;
-
 	bool force_bigjoiner_enable;
 
 	struct {
@@ -662,6 +658,11 @@ struct intel_connector {
 		u8 dsc_decompression_enabled:1;
 	} dp;
 
+	struct {
+		struct drm_dp_mst_port *port;
+		struct intel_dp *dp;
+	} mst;
+
 	/* Work struct to schedule a uevent on link train failure */
 	struct work_struct modeset_retry_work;
 
@@ -1832,7 +1833,6 @@ struct intel_dp {
 	struct intel_pps pps;
 
 	bool is_mst;
-	int active_mst_links;
 	enum drm_dp_mst_mode mst_detect;
 
 	/* connector directly attached - won't be use for modeset in mst world */
@@ -1842,9 +1842,11 @@ struct intel_dp {
 	struct drm_dp_tunnel *tunnel;
 	bool tunnel_suspended:1;
 
-	/* mst connector list */
-	struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES];
-	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct {
+		struct intel_dp_mst_encoder *stream_encoders[I915_MAX_PIPES];
+		struct drm_dp_mst_topology_mgr mgr;
+		int active_links;
+	} mst;
 
 	u32 (*get_aux_clock_divider)(struct intel_dp *dp, int index);
 	/*
drivers/gpu/drm/i915/display/intel_dp.c +18 -18
index bb5a2a40b64c6..63c335d3d9ce8 100644
@@ -1290,7 +1290,7 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
 	if (!HAS_DSC(i915))
 		return false;
 
-	if (connector->mst_port && !HAS_DSC_MST(i915))
+	if (connector->mst.dp && !HAS_DSC_MST(i915))
 		return false;
 
 	if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
@@ -3016,7 +3016,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
 		if (!conn_state->base.crtc)
 			continue;
 
-		if (connector->mst_port == intel_dp)
+		if (connector->mst.dp == intel_dp)
 			intel_dp_queue_modeset_retry_work(connector);
 	}
 }
@@ -3236,8 +3236,8 @@ intel_dp_sink_set_dsc_passthrough(const struct intel_connector *connector,
 				  bool enable)
 {
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
-	struct drm_dp_aux *aux = connector->port ?
-				 connector->port->passthrough_aux : NULL;
+	struct drm_dp_aux *aux = connector->mst.port ?
+				 connector->mst.port->passthrough_aux : NULL;
 
 	if (!aux)
 		return;
@@ -3264,7 +3264,7 @@ static int intel_dp_dsc_aux_ref_count(struct intel_atomic_state *state,
 	 * On SST the decompression AUX device won't be shared, each connector
 	 * uses for this its own AUX targeting the sink device.
 	 */
-	if (!connector->mst_port)
+	if (!connector->mst.dp)
 		return connector->dp.dsc_decompression_enabled ? 1 : 0;
 
 	for_each_oldnew_connector_in_state(&state->base, _connector_iter,
@@ -3272,7 +3272,7 @@ static int intel_dp_dsc_aux_ref_count(struct intel_atomic_state *state,
 		const struct intel_connector *
 			connector_iter = to_intel_connector(_connector_iter);
 
-		if (connector_iter->mst_port != connector->mst_port)
+		if (connector_iter->mst.dp != connector->mst.dp)
 			continue;
 
 		if (!connector_iter->dp.dsc_decompression_enabled)
@@ -4291,7 +4291,7 @@ intel_dp_mst_configure(struct intel_dp *intel_dp)
 	if (intel_dp->is_mst)
 		intel_dp_mst_prepare_probe(intel_dp);
 
-	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, intel_dp->is_mst);
 
 	/* Avoid stale info on the next detect cycle. */
 	intel_dp->mst_detect = DRM_DP_SST;
@@ -4306,9 +4306,9 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp)
 		return;
 
 	drm_dbg_kms(&i915->drm, "MST device may have disappeared %d vs %d\n",
-		    intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+		    intel_dp->is_mst, intel_dp->mst.mgr.mst_state);
 	intel_dp->is_mst = false;
-	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, intel_dp->is_mst);
 }
 
 static bool
@@ -5154,7 +5154,7 @@ intel_dp_mst_hpd_irq(struct intel_dp *intel_dp, u8 *esi, u8 *ack)
 {
 	bool handled = false;
 
-	drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst_mgr, esi, ack, &handled);
+	drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst.mgr, esi, ack, &handled);
 
 	if (esi[1] & DP_CP_IRQ) {
 		intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
@@ -5203,7 +5203,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 	bool link_ok = true;
 	bool reprobe_needed = false;
 
-	drm_WARN_ON_ONCE(&i915->drm, intel_dp->active_mst_links < 0);
+	drm_WARN_ON_ONCE(&i915->drm, intel_dp->mst.active_links < 0);
 
 	for (;;) {
 		u8 esi[4] = {};
@@ -5219,7 +5219,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 
 		drm_dbg_kms(&i915->drm, "DPRX ESI: %4ph\n", esi);
 
-		if (intel_dp->active_mst_links > 0 && link_ok &&
+		if (intel_dp->mst.active_links > 0 && link_ok &&
 		    esi[3] & LINK_STATUS_CHANGED) {
 			if (!intel_dp_mst_link_status(intel_dp))
 				link_ok = false;
@@ -5242,7 +5242,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 			drm_dbg_kms(&i915->drm, "Failed to ack ESI\n");
 
 		if (ack[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY))
-			drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst_mgr);
+			drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst.mgr);
 	}
 
 	if (!link_ok || intel_dp->link.force_retrain)
@@ -5340,7 +5340,7 @@ static bool intel_dp_has_connector(struct intel_dp *intel_dp,
 
 	/* MST */
 	for_each_pipe(i915, pipe) {
-		encoder = &intel_dp->mst_encoders[pipe]->base;
+		encoder = &intel_dp->mst.stream_encoders[pipe]->base;
 		if (conn_state->best_encoder == &encoder->base)
 			return true;
 	}
@@ -6421,7 +6421,7 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
 		return ret;
 
 	if (intel_dp_mst_source_support(intel_dp)) {
-		ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst_mgr);
+		ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst.mgr);
 		if (ret)
 			return ret;
 	}
@@ -7000,7 +7000,7 @@ void intel_dp_mst_suspend(struct drm_i915_private *dev_priv)
 			continue;
 
 		if (intel_dp->is_mst)
-			drm_dp_mst_topology_mgr_suspend(&intel_dp->mst_mgr);
+			drm_dp_mst_topology_mgr_suspend(&intel_dp->mst.mgr);
 	}
 }
 
@@ -7023,11 +7023,11 @@ void intel_dp_mst_resume(struct drm_i915_private *dev_priv)
 		if (!intel_dp_mst_source_support(intel_dp))
 			continue;
 
-		ret = drm_dp_mst_topology_mgr_resume(&intel_dp->mst_mgr,
+		ret = drm_dp_mst_topology_mgr_resume(&intel_dp->mst.mgr,
 						     true);
 		if (ret) {
 			intel_dp->is_mst = false;
-			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr,
 							false);
 		}
 	}
drivers/gpu/drm/i915/display/intel_dp_hdcp.c +3 -3
index 3425b36431431..c31b78255d22c 100644
@@ -702,10 +702,10 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector,
 
 	*hdcp_capable = false;
 	*hdcp2_capable = false;
-	if (!connector->mst_port)
+	if (!connector->mst.dp)
 		return -EINVAL;
 
-	aux = &connector->port->aux;
+	aux = &connector->mst.port->aux;
 	ret =  _intel_dp_hdcp2_get_capability(aux, hdcp2_capable);
 	if (ret)
 		drm_dbg_kms(&i915->drm,
@@ -881,7 +881,7 @@ int intel_dp_hdcp_init(struct intel_digital_port *dig_port,
 	if (!is_hdcp_supported(dev_priv, port))
 		return 0;
 
-	if (intel_connector->mst_port)
+	if (intel_connector->mst.dp)
 		return intel_hdcp_init(intel_connector, dig_port,
 				       &intel_dp_mst_hdcp_shim);
 	else if (!intel_dp_is_edp(intel_dp))
drivers/gpu/drm/i915/display/intel_dp_link_training.c +2 -2
index 5d8f93d4cdc6a..e112f9b4a89ef 100644
@@ -1692,8 +1692,8 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
 
 static struct intel_dp *intel_connector_to_intel_dp(struct intel_connector *connector)
 {
-	if (connector->mst_port)
-		return connector->mst_port;
+	if (connector->mst.dp)
+		return connector->mst.dp;
 	else
 		return enc_to_intel_dp(intel_attached_encoder(connector));
 }
drivers/gpu/drm/i915/display/intel_dp_mst.c +77 -77

484 lines not on this page · raw message

drivers/gpu/drm/i915/display/intel_hdcp.c +4 -4
index ccc48dc146892..fb4aa8e05bafd 100644
@@ -62,13 +62,13 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state,
 	int vcpi = 0;
 
 	/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
-	if (!connector->port)
+	if (!connector->mst.port)
 		return 0;
-	mgr = connector->port->mgr;
+	mgr = connector->mst.port->mgr;
 
 	drm_modeset_lock(&mgr->base.lock, state->base.acquire_ctx);
 	mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
-	payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
+	payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port);
 	if (drm_WARN_ON(mgr->dev, !payload))
 		goto out;
 
@@ -137,7 +137,7 @@ intel_hdcp_required_content_stream(struct intel_atomic_state *state,
 		data->k++;
 
 		/* if there is only one active stream */
-		if (dig_port->dp.active_mst_links <= 1)
+		if (dig_port->dp.mst.active_links <= 1)
 			break;
 	}
 	drm_connector_list_iter_end(&conn_iter);
drivers/gpu/drm/i915/display/intel_psr.c +1 -1
index 5173f5759ce88..c9f71d4f2320d 100644
@@ -3928,7 +3928,7 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector)
 	/* TODO: Add support for MST connectors as well. */
 	if ((connector->base.connector_type != DRM_MODE_CONNECTOR_eDP &&
 	     connector->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) ||
-	    connector->mst_port)
+	    connector->mst.dp)
 		return;
 
 	debugfs_create_file("i915_psr_sink_status", 0444, root,
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/2 drm/i915/dp_mst: Fix configuring FEC for a disconnected stream

From: Imre Deak <[email protected]>

[ Upstream commit acbe9a3b60b9a6ace8ef11fe898f586251c84592 ]

During an atomic commit after all the MST stream CRTC state is computed the driver ensures that the FEC is configured the same way (enabled or disabled) for all the streams on a given MST topology's link. drm_dp_mst_port_downstream_of_parent() used to determine if a stream is downstream of an MST port will return false if the whole topology is disconnected, since in that case it can't verify that the port/ parent_port passed to it is in the given MST topology. This is a problem during the above FEC configuration check, since intel_dp_mst_check_dsc_change()->get_pipes_downstream_of_mst_ports() will not return all the stream CRTCs/pipes for the topology as expected. Since passing parent_port==NULL to get_pipes_downstream_of_mst_port() is meant to return all the streams for the given topology (i.e. mst_mgr) skip checking if an MST port is downstream of a parent port in this case.

This fixes a problem where the FEC configuration check explained above failed to ensure that all streams' FEC is configured the same way if the topology was disconnected, leading to a FEC state mismatch error.

---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/display/intel_dp_mst.c +2 -1
index 4e66fade6301e..5d5d8adcfb6af 100644
@@ -739,7 +739,8 @@ static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
 		if (&connector->mst.dp->mst.mgr != mst_mgr)
 			continue;
 
-		if (connector->mst.port != parent_port &&
+		if (parent_port &&
+		    connector->mst.port != parent_port &&
 		    !drm_dp_mst_port_downstream_of_parent(mst_mgr,
 							  connector->mst.port,
 							  parent_port))
Signature · 1 line
2.53.0