All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
@ 2023-01-31 15:05 Imre Deak
  2023-01-31 15:05   ` Imre Deak
                   ` (19 more replies)
  0 siblings, 20 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

This is v2 of [1], addressing the review comments from Ville. It also
adds HW state verification for MST encoders and a workaround for a
payload allocation problem in a DELL monitor's MST hub I noticed during
testing.

Tested on HSW, ICL, ADLP.

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

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Lyude Paul <lyude@redhat.com> 

Imre Deak (17):
  drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs
  drm/display/dp_mst: Handle old/new payload states in
    drm_dp_remove_payload()
  drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
  drm/i915/dp_mst: Fix payload removal during output disabling
  drm/display/dp_mst: Fix the payload VCPI check in
    drm_dp_mst_dump_topology()
  drm/display/dp_mst: Sanitize payload iteration in
    drm_dp_mst_dump_topology()
  drm/i915: Factor out helpers for modesetting CRTCs and connectors
  drm/i915/dp_mst: Move getting the MST topology state earlier to
    connector check
  drm/display/dp_mst: Add a helper to verify the MST payload state
  drm/i915/dp_mst: Verify the MST state of modesetted outputs
  drm/display/dp_mst: Add helpers to query for payload allocation errors
  drm/display/dp_mst: Add helpers to query payload allocation properties
  drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition
  drm/display/dp_mst: Factor out a helper to reset the payload table
  drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem
  drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation
    problem
  drm/i915/dp_mst: Verify the HW state of MST encoders

 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |   2 +-
 drivers/gpu/drm/display/drm_dp_helper.c       |   2 +
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 354 ++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_atomic.c   | 140 +++++++
 drivers/gpu/drm/i915/display/intel_atomic.h   |   8 +
 drivers/gpu/drm/i915/display/intel_cdclk.c    |   2 +-
 drivers/gpu/drm/i915/display/intel_ddi.c      |  91 ++++-
 drivers/gpu/drm/i915/display/intel_display.c  |  59 +--
 drivers/gpu/drm/i915/display/intel_display.h  |   2 -
 .../drm/i915/display/intel_display_types.h    |  19 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  43 +--
 drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 270 +++++++++++--
 drivers/gpu/drm/i915/display/intel_dp_mst.h   |   9 +
 .../drm/i915/display/intel_modeset_verify.c   |   2 +
 drivers/gpu/drm/i915/display/skl_watermark.c  |   2 +-
 drivers/gpu/drm/i915/i915_reg.h               |   6 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |   2 +-
 include/drm/display/drm_dp.h                  |   5 +
 include/drm/display/drm_dp_helper.h           |   8 +
 include/drm/display/drm_dp_mst_helper.h       |  34 +-
 21 files changed, 878 insertions(+), 183 deletions(-)

-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 01/17] drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable

Add the MST topology for a CRTC to the atomic state if the driver
needs to force a modeset on the CRTC after the encoder compute config
functions are called.

Later the MST encoder's disable hook also adds the state, but that isn't
guaranteed to work (since in that hook getting the state may fail, which
can't be handled there). This should fix that, while a later patch fixes
the use of the MST state in the disable hook.

v2: Add missing forward struct declartions, caught by hdrtest.
v3: Factor out intel_dp_mst_add_topology_state_for_connector() used
    later in the patchset.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> # v2
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 61 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h  |  4 ++
 3 files changed, 69 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 166662ade593c..38106cf63b3b9 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5936,6 +5936,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 		if (ret)
 			return ret;
 
+		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
+		if (ret)
+			return ret;
+
 		ret = intel_atomic_add_affected_planes(state, crtc);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 8b0e4defa3f10..f3cb12dcfe0a7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1223,3 +1223,64 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state)
 	return crtc_state->mst_master_transcoder != INVALID_TRANSCODER &&
 	       crtc_state->mst_master_transcoder != crtc_state->cpu_transcoder;
 }
+
+/**
+ * intel_dp_mst_add_topology_state_for_connector - add MST topology state for a connector
+ * @state: atomic state
+ * @connector: connector to add the state for
+ * @crtc: the CRTC @connector is attached to
+ *
+ * Add the MST topology state for @connector to @state.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+static int
+intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
+					      struct intel_connector *connector,
+					      struct intel_crtc *crtc)
+{
+	struct drm_dp_mst_topology_state *mst_state;
+
+	if (!connector->mst_port)
+		return 0;
+
+	mst_state = drm_atomic_get_mst_topology_state(&state->base,
+						      &connector->mst_port->mst_mgr);
+	if (IS_ERR(mst_state))
+		return PTR_ERR(mst_state);
+
+	mst_state->pending_crtc_mask |= drm_crtc_mask(&crtc->base);
+
+	return 0;
+}
+
+/**
+ * intel_dp_mst_add_topology_state_for_crtc - add MST topology state for a CRTC
+ * @state: atomic state
+ * @crtc: CRTC to add the state for
+ *
+ * Add the MST topology state for @crtc to @state.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
+					     struct intel_crtc *crtc)
+{
+	struct drm_connector *_connector;
+	struct drm_connector_state *conn_state;
+	int i;
+
+	for_each_new_connector_in_state(&state->base, _connector, conn_state, i) {
+		struct intel_connector *connector = to_intel_connector(_connector);
+		int ret;
+
+		if (conn_state->crtc != &crtc->base)
+			continue;
+
+		ret = intel_dp_mst_add_topology_state_for_connector(state, connector, crtc);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index f7301de6cdfb3..f1815bb722672 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -8,6 +8,8 @@
 
 #include <linux/types.h>
 
+struct intel_atomic_state;
+struct intel_crtc;
 struct intel_crtc_state;
 struct intel_digital_port;
 struct intel_dp;
@@ -18,5 +20,7 @@ int intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port);
 bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
+int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
+					     struct intel_crtc *crtc);
 
 #endif /* __INTEL_DP_MST_H__ */
-- 
2.37.1


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

* [PATCH v2 01/17] drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Lyude Paul, Ville Syrjälä, stable

Add the MST topology for a CRTC to the atomic state if the driver
needs to force a modeset on the CRTC after the encoder compute config
functions are called.

Later the MST encoder's disable hook also adds the state, but that isn't
guaranteed to work (since in that hook getting the state may fail, which
can't be handled there). This should fix that, while a later patch fixes
the use of the MST state in the disable hook.

v2: Add missing forward struct declartions, caught by hdrtest.
v3: Factor out intel_dp_mst_add_topology_state_for_connector() used
    later in the patchset.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> # v2
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 61 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h  |  4 ++
 3 files changed, 69 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 166662ade593c..38106cf63b3b9 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5936,6 +5936,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
 		if (ret)
 			return ret;
 
+		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
+		if (ret)
+			return ret;
+
 		ret = intel_atomic_add_affected_planes(state, crtc);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 8b0e4defa3f10..f3cb12dcfe0a7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1223,3 +1223,64 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state)
 	return crtc_state->mst_master_transcoder != INVALID_TRANSCODER &&
 	       crtc_state->mst_master_transcoder != crtc_state->cpu_transcoder;
 }
+
+/**
+ * intel_dp_mst_add_topology_state_for_connector - add MST topology state for a connector
+ * @state: atomic state
+ * @connector: connector to add the state for
+ * @crtc: the CRTC @connector is attached to
+ *
+ * Add the MST topology state for @connector to @state.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+static int
+intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
+					      struct intel_connector *connector,
+					      struct intel_crtc *crtc)
+{
+	struct drm_dp_mst_topology_state *mst_state;
+
+	if (!connector->mst_port)
+		return 0;
+
+	mst_state = drm_atomic_get_mst_topology_state(&state->base,
+						      &connector->mst_port->mst_mgr);
+	if (IS_ERR(mst_state))
+		return PTR_ERR(mst_state);
+
+	mst_state->pending_crtc_mask |= drm_crtc_mask(&crtc->base);
+
+	return 0;
+}
+
+/**
+ * intel_dp_mst_add_topology_state_for_crtc - add MST topology state for a CRTC
+ * @state: atomic state
+ * @crtc: CRTC to add the state for
+ *
+ * Add the MST topology state for @crtc to @state.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
+					     struct intel_crtc *crtc)
+{
+	struct drm_connector *_connector;
+	struct drm_connector_state *conn_state;
+	int i;
+
+	for_each_new_connector_in_state(&state->base, _connector, conn_state, i) {
+		struct intel_connector *connector = to_intel_connector(_connector);
+		int ret;
+
+		if (conn_state->crtc != &crtc->base)
+			continue;
+
+		ret = intel_dp_mst_add_topology_state_for_connector(state, connector, crtc);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index f7301de6cdfb3..f1815bb722672 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -8,6 +8,8 @@
 
 #include <linux/types.h>
 
+struct intel_atomic_state;
+struct intel_crtc;
 struct intel_crtc_state;
 struct intel_digital_port;
 struct intel_dp;
@@ -18,5 +20,7 @@ int intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port);
 bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
+int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
+					     struct intel_crtc *crtc);
 
 #endif /* __INTEL_DP_MST_H__ */
-- 
2.37.1


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

* [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
  2023-01-31 15:05   ` Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (17 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx
  Cc: Karol Herbst, dri-devel, stable, Ben Skeggs, Wayne Lin, Alex Deucher

Atm, drm_dp_remove_payload() uses the same payload state to both get the
vc_start_slot required for the payload removal DPCD message and to
deduct time_slots from vc_start_slot of all payloads after the one being
removed.

The above isn't always correct, as vc_start_slot must be the up-to-date
version contained in the new payload state, but time_slots must be the
one used when the payload was previously added, contained in the old
payload state. The new payload's time_slots can change vs. the old one
if the current atomic commit changes the corresponding mode.

This patch let's drivers pass the old and new payload states to
drm_dp_remove_payload(), but keeps these the same for now in all drivers
not to change the behavior. A follow-up i915 patch will pass in that
driver the correct old and new states to the function.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Karol Herbst <kherbst@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Wayne Lin <Wayne.Lin@amd.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
 include/drm/display/drm_dp_mst_helper.h       |  3 ++-
 5 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a50319fc42b11..180d3893b68da 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 	if (enable)
 		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
 	else
-		drm_dp_remove_payload(mst_mgr, mst_state, payload);
+		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
 
 	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
 	 * AUX message. The sequence is slot 1-63 allocated sequence for each
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 847c10aa2098c..1990ff5dc7ddd 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  * drm_dp_remove_payload() - Remove an MST payload
  * @mgr: Manager to use.
  * @mst_state: The MST atomic state
- * @payload: The payload to write
+ * @old_payload: The payload with its old state
+ * @new_payload: The payload to write
  *
  * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
  * the starting time slots of all other payloads which would have been shifted towards the start of
@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  */
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload)
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload)
 {
 	struct drm_dp_mst_atomic_payload *pos;
 	bool send_remove = false;
 
 	/* We failed to make the payload, so nothing to do */
-	if (payload->vc_start_slot == -1)
+	if (new_payload->vc_start_slot == -1)
 		return;
 
 	mutex_lock(&mgr->lock);
-	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
+	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
 	mutex_unlock(&mgr->lock);
 
 	if (send_remove)
-		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
+		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
 	else
 		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
-			    payload->vcpi);
+			    new_payload->vcpi);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
-		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
-			pos->vc_start_slot -= payload->time_slots;
+		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
+			pos->vc_start_slot -= old_payload->time_slots;
 	}
-	payload->vc_start_slot = -1;
+	new_payload->vc_start_slot = -1;
 
 	mgr->payload_count--;
-	mgr->next_start_slot -= payload->time_slots;
+	mgr->next_start_slot -= old_payload->time_slots;
 
-	if (payload->delete)
-		drm_dp_mst_put_port_malloc(payload->port);
+	if (new_payload->delete)
+		drm_dp_mst_put_port_malloc(new_payload->port);
 }
 EXPORT_SYMBOL(drm_dp_remove_payload);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 		to_intel_connector(old_conn_state->connector);
 	struct drm_dp_mst_topology_state *mst_state =
 		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	struct drm_dp_mst_atomic_payload *payload =
+		drm_atomic_get_mst_payload_state(mst_state, connector->port);
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 
 	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	intel_hdcp_disable(intel_mst->connector);
 
 	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
+			      payload, payload);
 
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index edcb2529b4025..ed9d374147b8d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
 
 	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
 	if (msto->disabled) {
-		drm_dp_remove_payload(mgr, mst_state, payload);
+		drm_dp_remove_payload(mgr, mst_state, payload, payload);
 
 		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
 	} else {
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 41fd8352ab656..f5eb9aa152b14 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 			     struct drm_dp_mst_atomic_payload *payload);
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload);
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload);
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx
  Cc: Karol Herbst, dri-devel, stable, Ben Skeggs, Wayne Lin,
	Alex Deucher, Harry Wentland

Atm, drm_dp_remove_payload() uses the same payload state to both get the
vc_start_slot required for the payload removal DPCD message and to
deduct time_slots from vc_start_slot of all payloads after the one being
removed.

The above isn't always correct, as vc_start_slot must be the up-to-date
version contained in the new payload state, but time_slots must be the
one used when the payload was previously added, contained in the old
payload state. The new payload's time_slots can change vs. the old one
if the current atomic commit changes the corresponding mode.

This patch let's drivers pass the old and new payload states to
drm_dp_remove_payload(), but keeps these the same for now in all drivers
not to change the behavior. A follow-up i915 patch will pass in that
driver the correct old and new states to the function.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Karol Herbst <kherbst@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Wayne Lin <Wayne.Lin@amd.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
 include/drm/display/drm_dp_mst_helper.h       |  3 ++-
 5 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a50319fc42b11..180d3893b68da 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 	if (enable)
 		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
 	else
-		drm_dp_remove_payload(mst_mgr, mst_state, payload);
+		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
 
 	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
 	 * AUX message. The sequence is slot 1-63 allocated sequence for each
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 847c10aa2098c..1990ff5dc7ddd 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  * drm_dp_remove_payload() - Remove an MST payload
  * @mgr: Manager to use.
  * @mst_state: The MST atomic state
- * @payload: The payload to write
+ * @old_payload: The payload with its old state
+ * @new_payload: The payload to write
  *
  * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
  * the starting time slots of all other payloads which would have been shifted towards the start of
@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  */
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload)
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload)
 {
 	struct drm_dp_mst_atomic_payload *pos;
 	bool send_remove = false;
 
 	/* We failed to make the payload, so nothing to do */
-	if (payload->vc_start_slot == -1)
+	if (new_payload->vc_start_slot == -1)
 		return;
 
 	mutex_lock(&mgr->lock);
-	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
+	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
 	mutex_unlock(&mgr->lock);
 
 	if (send_remove)
-		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
+		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
 	else
 		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
-			    payload->vcpi);
+			    new_payload->vcpi);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
-		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
-			pos->vc_start_slot -= payload->time_slots;
+		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
+			pos->vc_start_slot -= old_payload->time_slots;
 	}
-	payload->vc_start_slot = -1;
+	new_payload->vc_start_slot = -1;
 
 	mgr->payload_count--;
-	mgr->next_start_slot -= payload->time_slots;
+	mgr->next_start_slot -= old_payload->time_slots;
 
-	if (payload->delete)
-		drm_dp_mst_put_port_malloc(payload->port);
+	if (new_payload->delete)
+		drm_dp_mst_put_port_malloc(new_payload->port);
 }
 EXPORT_SYMBOL(drm_dp_remove_payload);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 		to_intel_connector(old_conn_state->connector);
 	struct drm_dp_mst_topology_state *mst_state =
 		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	struct drm_dp_mst_atomic_payload *payload =
+		drm_atomic_get_mst_payload_state(mst_state, connector->port);
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 
 	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	intel_hdcp_disable(intel_mst->connector);
 
 	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
+			      payload, payload);
 
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index edcb2529b4025..ed9d374147b8d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
 
 	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
 	if (msto->disabled) {
-		drm_dp_remove_payload(mgr, mst_state, payload);
+		drm_dp_remove_payload(mgr, mst_state, payload, payload);
 
 		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
 	} else {
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 41fd8352ab656..f5eb9aa152b14 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 			     struct drm_dp_mst_atomic_payload *payload);
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload);
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload);
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx
  Cc: Lyude Paul, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

Atm, drm_dp_remove_payload() uses the same payload state to both get the
vc_start_slot required for the payload removal DPCD message and to
deduct time_slots from vc_start_slot of all payloads after the one being
removed.

The above isn't always correct, as vc_start_slot must be the up-to-date
version contained in the new payload state, but time_slots must be the
one used when the payload was previously added, contained in the old
payload state. The new payload's time_slots can change vs. the old one
if the current atomic commit changes the corresponding mode.

This patch let's drivers pass the old and new payload states to
drm_dp_remove_payload(), but keeps these the same for now in all drivers
not to change the behavior. A follow-up i915 patch will pass in that
driver the correct old and new states to the function.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Karol Herbst <kherbst@redhat.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Wayne Lin <Wayne.Lin@amd.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
 drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
 include/drm/display/drm_dp_mst_helper.h       |  3 ++-
 5 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a50319fc42b11..180d3893b68da 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 	if (enable)
 		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
 	else
-		drm_dp_remove_payload(mst_mgr, mst_state, payload);
+		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
 
 	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
 	 * AUX message. The sequence is slot 1-63 allocated sequence for each
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 847c10aa2098c..1990ff5dc7ddd 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  * drm_dp_remove_payload() - Remove an MST payload
  * @mgr: Manager to use.
  * @mst_state: The MST atomic state
- * @payload: The payload to write
+ * @old_payload: The payload with its old state
+ * @new_payload: The payload to write
  *
  * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
  * the starting time slots of all other payloads which would have been shifted towards the start of
@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
  */
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload)
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload)
 {
 	struct drm_dp_mst_atomic_payload *pos;
 	bool send_remove = false;
 
 	/* We failed to make the payload, so nothing to do */
-	if (payload->vc_start_slot == -1)
+	if (new_payload->vc_start_slot == -1)
 		return;
 
 	mutex_lock(&mgr->lock);
-	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
+	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
 	mutex_unlock(&mgr->lock);
 
 	if (send_remove)
-		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
+		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
 	else
 		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
-			    payload->vcpi);
+			    new_payload->vcpi);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
-		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
-			pos->vc_start_slot -= payload->time_slots;
+		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
+			pos->vc_start_slot -= old_payload->time_slots;
 	}
-	payload->vc_start_slot = -1;
+	new_payload->vc_start_slot = -1;
 
 	mgr->payload_count--;
-	mgr->next_start_slot -= payload->time_slots;
+	mgr->next_start_slot -= old_payload->time_slots;
 
-	if (payload->delete)
-		drm_dp_mst_put_port_malloc(payload->port);
+	if (new_payload->delete)
+		drm_dp_mst_put_port_malloc(new_payload->port);
 }
 EXPORT_SYMBOL(drm_dp_remove_payload);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 		to_intel_connector(old_conn_state->connector);
 	struct drm_dp_mst_topology_state *mst_state =
 		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	struct drm_dp_mst_atomic_payload *payload =
+		drm_atomic_get_mst_payload_state(mst_state, connector->port);
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 
 	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	intel_hdcp_disable(intel_mst->connector);
 
 	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
+			      payload, payload);
 
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index edcb2529b4025..ed9d374147b8d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
 
 	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
 	if (msto->disabled) {
-		drm_dp_remove_payload(mgr, mst_state, payload);
+		drm_dp_remove_payload(mgr, mst_state, payload, payload);
 
 		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
 	} else {
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 41fd8352ab656..f5eb9aa152b14 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 			     struct drm_dp_mst_atomic_payload *payload);
 void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
-			   struct drm_dp_mst_atomic_payload *payload);
+			   const struct drm_dp_mst_atomic_payload *old_payload,
+			   struct drm_dp_mst_atomic_payload *new_payload);
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [PATCH v2 03/17] drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
  2023-01-31 15:05   ` Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (17 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel, stable

Add a function to get the old MST topology state, required by a
follow-up i915 patch.

While at it clarify the code comment of
drm_atomic_get_new_mst_topology_state() and add _new prefix
to the new state pointer to remind about its difference from the old
state.

v2: Use old_/new_ prefixes for the state pointers. (Ville)

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 33 ++++++++++++++++---
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 1990ff5dc7ddd..38dab76ae69ea 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5364,28 +5364,53 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
 }
 EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
 
+/**
+ * drm_atomic_get_old_mst_topology_state: get old MST topology state in atomic state, if any
+ * @state: global atomic state
+ * @mgr: MST topology manager, also the private object in this case
+ *
+ * This function wraps drm_atomic_get_old_private_obj_state() passing in the MST atomic
+ * state vtable so that the private object state returned is that of a MST
+ * topology object.
+ *
+ * Returns:
+ *
+ * The old MST topology state, or NULL if there's no topology state for this MST mgr
+ * in the global atomic state
+ */
+struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_private_state *old_priv_state =
+		drm_atomic_get_old_private_obj_state(state, &mgr->base);
+
+	return old_priv_state ? to_dp_mst_topology_state(old_priv_state) : NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_mst_topology_state);
+
 /**
  * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
  * @state: global atomic state
  * @mgr: MST topology manager, also the private object in this case
  *
- * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
+ * This function wraps drm_atomic_get_new_private_obj_state() passing in the MST atomic
  * state vtable so that the private object state returned is that of a MST
  * topology object.
  *
  * Returns:
  *
- * The MST topology state, or NULL if there's no topology state for this MST mgr
+ * The new MST topology state, or NULL if there's no topology state for this MST mgr
  * in the global atomic state
  */
 struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr)
 {
-	struct drm_private_state *priv_state =
+	struct drm_private_state *new_priv_state =
 		drm_atomic_get_new_private_obj_state(state, &mgr->base);
 
-	return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
+	return new_priv_state ? to_dp_mst_topology_state(new_priv_state) : NULL;
 }
 EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index f5eb9aa152b14..32c764fb9cb56 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -868,6 +868,9 @@ struct drm_dp_mst_topology_state *
 drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
 				  struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr);
+struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_atomic_payload *
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 03/17] drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel, stable

Add a function to get the old MST topology state, required by a
follow-up i915 patch.

While at it clarify the code comment of
drm_atomic_get_new_mst_topology_state() and add _new prefix
to the new state pointer to remind about its difference from the old
state.

v2: Use old_/new_ prefixes for the state pointers. (Ville)

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 33 ++++++++++++++++---
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 1990ff5dc7ddd..38dab76ae69ea 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5364,28 +5364,53 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
 }
 EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
 
+/**
+ * drm_atomic_get_old_mst_topology_state: get old MST topology state in atomic state, if any
+ * @state: global atomic state
+ * @mgr: MST topology manager, also the private object in this case
+ *
+ * This function wraps drm_atomic_get_old_private_obj_state() passing in the MST atomic
+ * state vtable so that the private object state returned is that of a MST
+ * topology object.
+ *
+ * Returns:
+ *
+ * The old MST topology state, or NULL if there's no topology state for this MST mgr
+ * in the global atomic state
+ */
+struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_private_state *old_priv_state =
+		drm_atomic_get_old_private_obj_state(state, &mgr->base);
+
+	return old_priv_state ? to_dp_mst_topology_state(old_priv_state) : NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_mst_topology_state);
+
 /**
  * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
  * @state: global atomic state
  * @mgr: MST topology manager, also the private object in this case
  *
- * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
+ * This function wraps drm_atomic_get_new_private_obj_state() passing in the MST atomic
  * state vtable so that the private object state returned is that of a MST
  * topology object.
  *
  * Returns:
  *
- * The MST topology state, or NULL if there's no topology state for this MST mgr
+ * The new MST topology state, or NULL if there's no topology state for this MST mgr
  * in the global atomic state
  */
 struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr)
 {
-	struct drm_private_state *priv_state =
+	struct drm_private_state *new_priv_state =
 		drm_atomic_get_new_private_obj_state(state, &mgr->base);
 
-	return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
+	return new_priv_state ? to_dp_mst_topology_state(new_priv_state) : NULL;
 }
 EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index f5eb9aa152b14..32c764fb9cb56 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -868,6 +868,9 @@ struct drm_dp_mst_topology_state *
 drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
 				  struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr);
+struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_atomic_payload *
-- 
2.37.1


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

* [PATCH v2 03/17] drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Lyude Paul, Ville Syrjälä, stable, dri-devel

Add a function to get the old MST topology state, required by a
follow-up i915 patch.

While at it clarify the code comment of
drm_atomic_get_new_mst_topology_state() and add _new prefix
to the new state pointer to remind about its difference from the old
state.

v2: Use old_/new_ prefixes for the state pointers. (Ville)

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 33 ++++++++++++++++---
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 1990ff5dc7ddd..38dab76ae69ea 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5364,28 +5364,53 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
 }
 EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
 
+/**
+ * drm_atomic_get_old_mst_topology_state: get old MST topology state in atomic state, if any
+ * @state: global atomic state
+ * @mgr: MST topology manager, also the private object in this case
+ *
+ * This function wraps drm_atomic_get_old_private_obj_state() passing in the MST atomic
+ * state vtable so that the private object state returned is that of a MST
+ * topology object.
+ *
+ * Returns:
+ *
+ * The old MST topology state, or NULL if there's no topology state for this MST mgr
+ * in the global atomic state
+ */
+struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct drm_private_state *old_priv_state =
+		drm_atomic_get_old_private_obj_state(state, &mgr->base);
+
+	return old_priv_state ? to_dp_mst_topology_state(old_priv_state) : NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_mst_topology_state);
+
 /**
  * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
  * @state: global atomic state
  * @mgr: MST topology manager, also the private object in this case
  *
- * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
+ * This function wraps drm_atomic_get_new_private_obj_state() passing in the MST atomic
  * state vtable so that the private object state returned is that of a MST
  * topology object.
  *
  * Returns:
  *
- * The MST topology state, or NULL if there's no topology state for this MST mgr
+ * The new MST topology state, or NULL if there's no topology state for this MST mgr
  * in the global atomic state
  */
 struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr)
 {
-	struct drm_private_state *priv_state =
+	struct drm_private_state *new_priv_state =
 		drm_atomic_get_new_private_obj_state(state, &mgr->base);
 
-	return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
+	return new_priv_state ? to_dp_mst_topology_state(new_priv_state) : NULL;
 }
 EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index f5eb9aa152b14..32c764fb9cb56 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -868,6 +868,9 @@ struct drm_dp_mst_topology_state *
 drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
 				  struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *
+drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
+				      struct drm_dp_mst_topology_mgr *mgr);
+struct drm_dp_mst_topology_state *
 drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
 				      struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_atomic_payload *
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 04/17] drm/i915/dp_mst: Fix payload removal during output disabling
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable

Use the correct old/new topology and payload states in
intel_mst_disable_dp(). So far drm_atomic_get_mst_topology_state() it
used returned either the old state, in case the state was added already
earlier during the atomic check phase or otherwise the new state (but
the latter could fail, which can't be handled in the enable/disable
hooks). After the first patch in the patchset, the state should always
get added already during the check phase, so here we can get the
old/new states without a failure.

drm_dp_remove_payload() should use time_slots from the old payload state
and vc_start_slot in the new one. It should update the new payload
states to reflect the sink's current payload table after the payload is
removed. Pass the new topology state and the old and new payload states
accordingly.

This also fixes a problem where the payload allocations for multiple MST
streams on the same link got inconsistent after a few commits, as
during payload removal the old instead of the new payload state got
updated, so the subsequent enabling sequence and commits used a stale
payload state.

v2: Constify the old payload state pointer. (Ville)

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index dc4e5ff1dbb31..054a009e800d7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -524,10 +524,14 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	struct intel_dp *intel_dp = &dig_port->dp;
 	struct intel_connector *connector =
 		to_intel_connector(old_conn_state->connector);
-	struct drm_dp_mst_topology_state *mst_state =
-		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
-	struct drm_dp_mst_atomic_payload *payload =
-		drm_atomic_get_mst_payload_state(mst_state, connector->port);
+	struct drm_dp_mst_topology_state *old_mst_state =
+		drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	struct drm_dp_mst_topology_state *new_mst_state =
+		drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	const struct drm_dp_mst_atomic_payload *old_payload =
+		drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
+	struct drm_dp_mst_atomic_payload *new_payload =
+		drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 
 	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -535,8 +539,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 
 	intel_hdcp_disable(intel_mst->connector);
 
-	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-			      payload, payload);
+	drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
+			      old_payload, new_payload);
 
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
-- 
2.37.1


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

* [PATCH v2 04/17] drm/i915/dp_mst: Fix payload removal during output disabling
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Lyude Paul, Ville Syrjälä, stable

Use the correct old/new topology and payload states in
intel_mst_disable_dp(). So far drm_atomic_get_mst_topology_state() it
used returned either the old state, in case the state was added already
earlier during the atomic check phase or otherwise the new state (but
the latter could fail, which can't be handled in the enable/disable
hooks). After the first patch in the patchset, the state should always
get added already during the check phase, so here we can get the
old/new states without a failure.

drm_dp_remove_payload() should use time_slots from the old payload state
and vc_start_slot in the new one. It should update the new payload
states to reflect the sink's current payload table after the payload is
removed. Pass the new topology state and the old and new payload states
accordingly.

This also fixes a problem where the payload allocations for multiple MST
streams on the same link got inconsistent after a few commits, as
during payload removal the old instead of the new payload state got
updated, so the subsequent enabling sequence and commits used a stale
payload state.

v2: Constify the old payload state pointer. (Ville)

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org # 6.1
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index dc4e5ff1dbb31..054a009e800d7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -524,10 +524,14 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	struct intel_dp *intel_dp = &dig_port->dp;
 	struct intel_connector *connector =
 		to_intel_connector(old_conn_state->connector);
-	struct drm_dp_mst_topology_state *mst_state =
-		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
-	struct drm_dp_mst_atomic_payload *payload =
-		drm_atomic_get_mst_payload_state(mst_state, connector->port);
+	struct drm_dp_mst_topology_state *old_mst_state =
+		drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	struct drm_dp_mst_topology_state *new_mst_state =
+		drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+	const struct drm_dp_mst_atomic_payload *old_payload =
+		drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
+	struct drm_dp_mst_atomic_payload *new_payload =
+		drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 
 	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -535,8 +539,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 
 	intel_hdcp_disable(intel_mst->connector);
 
-	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
-			      payload, payload);
+	drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
+			      old_payload, new_payload);
 
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
-- 
2.37.1


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

* [PATCH v2 05/17] drm/display/dp_mst: Fix the payload VCPI check in drm_dp_mst_dump_topology()
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Fix an off-by-one error in the VCPI check in drm_dp_mst_dump_topology().

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 38dab76ae69ea..8787df19f428b 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4772,7 +4772,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 		list_for_each_entry(payload, &state->payloads, next) {
 			char name[14];
 
-			if (payload->vcpi != i || payload->delete)
+			if (payload->vcpi != i + 1 || payload->delete)
 				continue;
 
 			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 05/17] drm/display/dp_mst: Fix the payload VCPI check in drm_dp_mst_dump_topology()
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Fix an off-by-one error in the VCPI check in drm_dp_mst_dump_topology().

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 38dab76ae69ea..8787df19f428b 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4772,7 +4772,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 		list_for_each_entry(payload, &state->payloads, next) {
 			char name[14];
 
-			if (payload->vcpi != i || payload->delete)
+			if (payload->vcpi != i + 1 || payload->delete)
 				continue;
 
 			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (4 preceding siblings ...)
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-01-31 23:14   ` Lyude Paul
  2023-02-03 12:22   ` Ville Syrjälä
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 07/17] drm/i915: Factor out helpers for modesetting CRTCs and connectors Imre Deak
                   ` (13 subsequent siblings)
  19 siblings, 2 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

Simplify the loop iterating the payloads by using a helper to get a
payload by its VCPI (keeping the list VCPI sorted). This also removes
the assumption that the biggest VCPI matches the number of payloads
(even though this holds now).

Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 45 ++++++++++++-------
 1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 8787df19f428b..0c04b96ae614c 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4737,6 +4737,18 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
 	kfree(mst_edid);
 }
 
+static struct drm_dp_mst_atomic_payload *
+get_payload_by_vcpi(struct drm_dp_mst_topology_state *mst_state, int vcpi)
+{
+	struct drm_dp_mst_atomic_payload *payload;
+
+	list_for_each_entry(payload, &mst_state->payloads, next)
+		if (payload->vcpi == vcpi)
+			return payload;
+
+	return NULL;
+}
+
 /**
  * drm_dp_mst_dump_topology(): dump topology to seq file.
  * @m: seq_file to dump output to
@@ -4748,7 +4760,6 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 			      struct drm_dp_mst_topology_mgr *mgr)
 {
 	struct drm_dp_mst_topology_state *state;
-	struct drm_dp_mst_atomic_payload *payload;
 	int i, ret;
 
 	mutex_lock(&mgr->lock);
@@ -4768,24 +4779,24 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 		   state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
 
 	seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc |     sink name     |\n");
-	for (i = 0; i < mgr->max_payloads; i++) {
-		list_for_each_entry(payload, &state->payloads, next) {
-			char name[14];
+	for_each_set_bit(i, (unsigned long *)&state->payload_mask,
+			 BITS_PER_TYPE(state->payload_mask)) {
+		const struct drm_dp_mst_atomic_payload *payload = get_payload_by_vcpi(state, i + 1);
+		char name[14];
 
-			if (payload->vcpi != i + 1 || payload->delete)
-				continue;
+		if (payload->delete)
+			continue;
 
-			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
-			seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
-				   i,
-				   payload->port->port_num,
-				   payload->vcpi,
-				   payload->vc_start_slot,
-				   payload->vc_start_slot + payload->time_slots - 1,
-				   payload->pbn,
-				   payload->dsc_enabled ? "Y" : "N",
-				   (*name != 0) ? name : "Unknown");
-		}
+		fetch_monitor_name(mgr, payload->port, name, sizeof(name));
+		seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
+			   i,
+			   payload->port->port_num,
+			   payload->vcpi,
+			   payload->vc_start_slot,
+			   payload->vc_start_slot + payload->time_slots - 1,
+			   payload->pbn,
+			   payload->dsc_enabled ? "Y" : "N",
+			   (*name != 0) ? name : "Unknown");
 	}
 
 	seq_printf(m, "\n*** DPCD Info ***\n");
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 07/17] drm/i915: Factor out helpers for modesetting CRTCs and connectors
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (5 preceding siblings ...)
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration " Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 08/17] drm/i915/dp_mst: Move getting the MST topology state earlier to connector check Imre Deak
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

Factor out and add the functions to intel_atomic.c to modeset pipes or
connectors. These can be used in a few places, also making it a bit
clearer where modeset forcing is needed.

After this patch the MST topology state for modesetted CRTCs is added
already in the connector's atomic check function, but that shouldn't
matter since the state would be added later anyway in the encoders'
compute config function. Also the crtc_state->update_pipe flag will be
reset for CRTCs modesetted from a connector check function, but this
should be ok, since the flag can get set only later in
intel_crtc_check_fastset().

v2: Use intel_dp_mst_add_topology_state_for_connector() when modesetting
    a connector, to avoid iterating connectors redundantly.

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

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index a9a3f3715279d..0f1c5b9c9a826 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -38,6 +38,7 @@
 #include "intel_atomic.h"
 #include "intel_cdclk.h"
 #include "intel_display_types.h"
+#include "intel_dp_mst.h"
 #include "intel_global_state.h"
 #include "intel_hdcp.h"
 #include "intel_psr.h"
@@ -613,3 +614,137 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 
 	return to_intel_crtc_state(crtc_state);
 }
+
+static int modeset_pipe(struct intel_atomic_state *state,
+			struct intel_crtc *crtc, const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct intel_crtc_state *crtc_state;
+
+	drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
+		    crtc->base.base.id, crtc->base.name, reason);
+
+	crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	crtc_state->uapi.mode_changed = true;
+	crtc_state->update_pipe = false;
+
+	return intel_atomic_add_affected_planes(state, crtc);
+}
+
+/**
+ * intel_atomic_modeset_connector - add a connector to the atomic state, force modeset on its CRTC if any
+ * @state: atomic state
+ * @connector: connector to add the state for
+ * @reason: the reason why the connector needs to be added
+ *
+ * Add the @connector to the atomic state with its CRTC state and force a modeset
+ * on the CRTC if any.
+ *
+ * This function can be called only before computing the new plane states.
+ *
+ * Returns 0 in case of success, a negative error code on failure.
+ */
+int intel_atomic_modeset_connector(struct intel_atomic_state *state,
+				   struct intel_connector *connector, const char *reason)
+{
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
+	struct drm_connector_state *conn_state;
+	struct intel_crtc *crtc;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Full modeset due to %s\n",
+		    connector->base.base.id, connector->base.name, reason);
+
+	conn_state = drm_atomic_get_connector_state(&state->base, &connector->base);
+	if (IS_ERR(conn_state))
+		return PTR_ERR(conn_state);
+
+	if (!conn_state->crtc)
+		return 0;
+
+	crtc = to_intel_crtc(conn_state->crtc);
+
+	ret = intel_dp_mst_add_topology_state_for_connector(state, connector, crtc);
+	if (ret)
+		return ret;
+
+	return modeset_pipe(state, crtc, reason);
+}
+
+/**
+ * intel_atomic_modeset_pipe - add a CRTC to the atomic state, force modeset on it
+ * @state: atomic state
+ * @crtc: CRTC to add the state for
+ * @reason: the reason why the CRTC needs to be added
+ *
+ * Add @crtc to the atomic state with all its connector and plane dependencies and
+ * force modeset on it.
+ *
+ * This function can be called only before computing the new plane states.
+ *
+ * Returns 0 in case of success, a negative error code on failure.
+ */
+int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
+			      struct intel_crtc *crtc, const char *reason)
+{
+	int ret;
+
+	ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base);
+	if (ret)
+		return ret;
+
+	ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
+	if (ret)
+		return ret;
+
+	return modeset_pipe(state, crtc, reason);
+}
+
+/**
+ * intel_atomic_modeset_all_pipes - add all active CRTCs to the atomic state, force modeset on them
+ * @state: atomic state
+ * @reason: the reason why the CRTCs need to be added
+ *
+ * Add all the CRTCs to the atomic state and if active also add their connector and plane
+ * dependencies and force a modeset on the CRTC.
+ *
+ * This function can be called only after computing the new plane states.
+ *
+ * Returns 0 in case of success, a negative error code on failure.
+ */
+int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
+				   const char *reason)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+	struct intel_crtc *crtc;
+
+	/*
+	 * Add all pipes to the state, and force
+	 * a modeset on all the active ones.
+	 */
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
+		struct intel_crtc_state *crtc_state;
+		int ret;
+
+		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		if (!crtc_state->hw.active ||
+		    intel_crtc_needs_modeset(crtc_state))
+			continue;
+
+		ret = intel_atomic_modeset_pipe(state, crtc, reason);
+		if (ret)
+			return ret;
+
+		crtc_state->update_planes |= crtc_state->active_planes;
+		crtc_state->async_flip_planes = 0;
+		crtc_state->do_async_flip = false;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
index 1dc439983dd94..84295d388e3cb 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic.h
@@ -56,4 +56,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 			       struct intel_crtc *intel_crtc,
 			       struct intel_crtc_state *crtc_state);
 
+int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
+			      struct intel_crtc *crtc, const char *reason);
+int intel_atomic_modeset_connector(struct intel_atomic_state *state,
+				   struct intel_connector *connector, const char *reason);
+int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
+				   const char *reason);
+
 #endif /* __INTEL_ATOMIC_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 82da76b586edb..4c8c9b6f8cfcb 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2930,7 +2930,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
 	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
 					     &new_cdclk_state->actual)) {
 		/* All pipes must be switched off while we change the cdclk. */
-		ret = intel_modeset_all_pipes(state, "CDCLK change");
+		ret = intel_atomic_modeset_all_pipes(state, "CDCLK change");
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 38106cf63b3b9..36269ae34075e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5903,55 +5903,6 @@ intel_verify_planes(struct intel_atomic_state *state)
 			     plane_state->uapi.visible);
 }
 
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	struct intel_crtc *crtc;
-
-	/*
-	 * Add all pipes to the state, and force
-	 * a modeset on all the active ones.
-	 */
-	for_each_intel_crtc(&dev_priv->drm, crtc) {
-		struct intel_crtc_state *crtc_state;
-		int ret;
-
-		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-
-		if (!crtc_state->hw.active ||
-		    intel_crtc_needs_modeset(crtc_state))
-			continue;
-
-		drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
-			    crtc->base.base.id, crtc->base.name, reason);
-
-		crtc_state->uapi.mode_changed = true;
-		crtc_state->update_pipe = false;
-
-		ret = drm_atomic_add_affected_connectors(&state->base,
-							 &crtc->base);
-		if (ret)
-			return ret;
-
-		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
-		if (ret)
-			return ret;
-
-		ret = intel_atomic_add_affected_planes(state, crtc);
-		if (ret)
-			return ret;
-
-		crtc_state->update_planes |= crtc_state->active_planes;
-		crtc_state->async_flip_planes = 0;
-		crtc_state->do_async_flip = false;
-	}
-
-	return 0;
-}
-
 void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -6671,15 +6622,7 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
 	for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, modeset_pipes) {
 		int ret;
 
-		crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
-
-		crtc_state->uapi.mode_changed = true;
-
-		ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base);
-		if (ret)
-			return ret;
-
-		ret = intel_atomic_add_affected_planes(state, crtc);
+		ret = intel_atomic_modeset_pipe(state, crtc, "big joiner");
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index cb6f520cc575f..69528018428ea 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -537,8 +537,6 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915);
 void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915);
 void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915);
 void intel_display_resume(struct drm_device *dev);
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
-			    const char *reason);
 void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
 					  struct intel_power_domain_mask *old_domains);
 void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 62cbab7402e93..501163c5c590d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4914,35 +4914,17 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct drm_connector_list_iter conn_iter;
-	struct drm_connector *connector;
+	struct intel_connector *connector;
 	int ret = 0;
 
 	drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
-	drm_for_each_connector_iter(connector, &conn_iter) {
-		struct drm_connector_state *conn_state;
-		struct intel_crtc_state *crtc_state;
-		struct intel_crtc *crtc;
-
-		if (!connector->has_tile ||
-		    connector->tile_group->id != tile_group_id)
-			continue;
-
-		conn_state = drm_atomic_get_connector_state(&state->base,
-							    connector);
-		if (IS_ERR(conn_state)) {
-			ret = PTR_ERR(conn_state);
-			break;
-		}
-
-		crtc = to_intel_crtc(conn_state->crtc);
-
-		if (!crtc)
+	for_each_intel_connector_iter(connector, &conn_iter) {
+		if (!connector->base.has_tile ||
+		    connector->base.tile_group->id != tile_group_id)
 			continue;
 
-		crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
-		crtc_state->uapi.mode_changed = true;
-
-		ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
+		ret = intel_atomic_modeset_connector(state, connector,
+						     "connector tile group");
 		if (ret)
 			break;
 	}
@@ -4973,13 +4955,7 @@ static int intel_modeset_affected_transcoders(struct intel_atomic_state *state,
 		if (!(transcoders & BIT(crtc_state->cpu_transcoder)))
 			continue;
 
-		crtc_state->uapi.mode_changed = true;
-
-		ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base);
-		if (ret)
-			return ret;
-
-		ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
+		ret = intel_atomic_modeset_pipe(state, crtc, "port syncing");
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 054a009e800d7..ca55b87bd8f3a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -434,35 +434,14 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
 
 	drm_connector_list_iter_begin(&dev_priv->drm, &connector_list_iter);
 	for_each_intel_connector_iter(connector_iter, &connector_list_iter) {
-		struct intel_digital_connector_state *conn_iter_state;
-		struct intel_crtc_state *crtc_state;
-		struct intel_crtc *crtc;
-
 		if (connector_iter->mst_port != connector->mst_port ||
 		    connector_iter == connector)
 			continue;
 
-		conn_iter_state = intel_atomic_get_digital_connector_state(state,
-									   connector_iter);
-		if (IS_ERR(conn_iter_state)) {
-			ret = PTR_ERR(conn_iter_state);
-			break;
-		}
-
-		if (!conn_iter_state->base.crtc)
-			continue;
-
-		crtc = to_intel_crtc(conn_iter_state->base.crtc);
-		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
-		if (IS_ERR(crtc_state)) {
-			ret = PTR_ERR(crtc_state);
-			break;
-		}
-
-		ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
+		ret = intel_atomic_modeset_connector(state, connector_iter,
+						     "MST master transcoder");
 		if (ret)
 			break;
-		crtc_state->uapi.mode_changed = true;
 	}
 	drm_connector_list_iter_end(&connector_list_iter);
 
@@ -1240,7 +1219,7 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state)
  *
  * Returns 0 on success, negative error code on failure.
  */
-static int
+int
 intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
 					      struct intel_connector *connector,
 					      struct intel_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index f1815bb722672..cd0ae661dc20b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 
 struct intel_atomic_state;
+struct intel_connector;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_digital_port;
@@ -22,5 +23,8 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
 bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
 int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 					     struct intel_crtc *crtc);
+int intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
+						  struct intel_connector *connector,
+						  struct intel_crtc *crtc);
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 261cdab390b48..7bf95b3a6eb22 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2483,7 +2483,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
 
 		if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
 			/* TODO: Implement vblank synchronized MBUS joining changes */
-			ret = intel_modeset_all_pipes(state, "MBUS joining change");
+			ret = intel_atomic_modeset_all_pipes(state, "MBUS joining change");
 			if (ret)
 				return ret;
 		}
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 08/17] drm/i915/dp_mst: Move getting the MST topology state earlier to connector check
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (6 preceding siblings ...)
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 07/17] drm/i915: Factor out helpers for modesetting CRTCs and connectors Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

Atm, the MST topology state for modesetted CRTCs may get added only in
the encoder's compute config function. To make this more consistent with
other encoders add these states already earlier in the connector atomic
check function and just get the new MST state in the encoder's compute
config function which shouldn't fail.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 23 ++++++++++++++-------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index ca55b87bd8f3a..421a0f8c28229 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -66,9 +66,9 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
 	int bpp, slots = -EINVAL;
 	int ret = 0;
 
-	mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr);
-	if (IS_ERR(mst_state))
-		return PTR_ERR(mst_state);
+	mst_state = drm_atomic_get_new_mst_topology_state(state, &intel_dp->mst_mgr);
+	if (drm_WARN_ON(&i915->drm, !mst_state))
+		return -EINVAL;
 
 	crtc_state->lane_count = limits->max_lane_count;
 	crtc_state->port_clock = limits->max_rate;
@@ -254,11 +254,9 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
 	u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ?
 		DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B;
 
-	topology_state = drm_atomic_get_mst_topology_state(conn_state->state, mgr);
-	if (IS_ERR(topology_state)) {
-		drm_dbg_kms(&i915->drm, "slot update failed\n");
-		return PTR_ERR(topology_state);
-	}
+	topology_state = drm_atomic_get_new_mst_topology_state(conn_state->state, mgr);
+	if (drm_WARN_ON(&i915->drm, !topology_state))
+		return -EINVAL;
 
 	drm_dp_mst_update_slots(topology_state, link_coding_cap);
 
@@ -465,6 +463,15 @@ intel_dp_mst_atomic_check(struct drm_connector *connector,
 	if (ret)
 		return ret;
 
+	if (intel_connector_needs_modeset(state, &intel_connector->base)) {
+		struct drm_dp_mst_topology_state *mst_state;
+
+		mst_state = drm_atomic_get_mst_topology_state(&state->base,
+							      &intel_connector->mst_port->mst_mgr);
+		if (IS_ERR(mst_state))
+			return PTR_ERR(mst_state);
+	}
+
 	return drm_dp_atomic_release_time_slots(&state->base,
 						&intel_connector->mst_port->mst_mgr,
 						intel_connector->port);
-- 
2.37.1


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

* [PATCH v2 09/17] drm/display/dp_mst: Add a helper to verify the MST payload state
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add a function drivers can use to verify the MST payload state tracking
and compare this to the sink's payload table.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 169 ++++++++++++++++++
 include/drm/display/drm_dp.h                  |   3 +
 include/drm/display/drm_dp_mst_helper.h       |   3 +
 3 files changed, 175 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 0c04b96ae614c..e57dd16955d52 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4847,6 +4847,175 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 }
 EXPORT_SYMBOL(drm_dp_mst_dump_topology);
 
+static bool verify_mst_payload_state(struct drm_dp_mst_topology_state *mst_state)
+{
+	struct drm_dp_mst_topology_mgr *mgr = mst_state->mgr;
+	struct drm_dp_mst_atomic_payload *payload;
+	int payload_count = 0;
+	u64 time_slot_mask = 0;
+	u32 vcpi_mask = 0;
+	int last_set;
+
+	if (BITS_PER_TYPE(time_slot_mask) < mst_state->total_avail_slots)
+		return false;
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		u64 mask;
+
+		if (payload->vc_start_slot == -1)
+			continue;
+
+		if (!payload->time_slots)
+			return false;
+
+		if (payload->vc_start_slot < mst_state->start_slot)
+			return false;
+
+		if (payload->vc_start_slot + payload->time_slots - mst_state->start_slot >
+		    mst_state->total_avail_slots)
+			return false;
+
+		mask = GENMASK_ULL(payload->vc_start_slot + payload->time_slots - 1,
+				   payload->vc_start_slot);
+
+		if (time_slot_mask & mask)
+			return false;
+
+		time_slot_mask |= mask;
+
+		if (payload->vcpi < 1 ||
+		    payload->vcpi & ~DP_PAYLOAD_ID_MASK ||
+		    payload->vcpi > BITS_PER_TYPE(vcpi_mask))
+			return false;
+		if (BIT(payload->vcpi - 1) & vcpi_mask)
+			return false;
+		vcpi_mask |= BIT(payload->vcpi - 1);
+
+		payload_count++;
+	}
+
+	if (payload_count != mgr->payload_count)
+		return false;
+
+	last_set = fls64(time_slot_mask);
+
+	if (last_set &&
+	    GENMASK_ULL(last_set - 1, mst_state->start_slot) != time_slot_mask)
+		return false;
+
+	if (max(mst_state->start_slot, mgr->next_start_slot) !=
+	    max_t(int, mst_state->start_slot, last_set))
+		return false;
+
+	return true;
+}
+
+static int get_payload_table_vcpi(const u8 *table, int slot)
+{
+	if (slot == 0)
+		return FIELD_GET(DP_PAYLOAD_ID_SLOT0_5_0_MASK, table[0]) |
+		       (FIELD_GET(DP_PAYLOAD_ID_SLOT0_6, table[1]) << 6);
+	else
+		return FIELD_GET(DP_PAYLOAD_ID_MASK, table[slot]);
+}
+
+static bool verify_mst_payload_table(struct drm_dp_mst_topology_state *mst_state,
+				     const u8 *payload_table)
+{
+	struct drm_dp_mst_topology_mgr *mgr = mst_state->mgr;
+	struct drm_dp_mst_atomic_payload *payload;
+	int i;
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		if (payload->vc_start_slot == -1)
+			continue;
+
+		if (payload->vc_start_slot + payload->time_slots > DP_PAYLOAD_TABLE_SIZE)
+			return false;
+
+		for (i = 0; i < payload->time_slots; i++)
+			if (get_payload_table_vcpi(payload_table,
+						   payload->vc_start_slot + i) != payload->vcpi)
+				return false;
+	}
+
+	for (i = max(mgr->next_start_slot, mst_state->start_slot);
+	     i < DP_PAYLOAD_TABLE_SIZE;
+	     i++) {
+		if (get_payload_table_vcpi(payload_table, i) != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void print_mst_payload_state(struct drm_dp_mst_topology_mgr *mgr,
+				    struct drm_dp_mst_topology_state *mst_state,
+				    const u8 *payload_table)
+{
+	struct drm_dp_mst_atomic_payload *payload;
+	int i = 0;
+
+	drm_dbg(mgr->dev,
+		"Payload state: start_slot %d total_avail_slots %d next_start_slot %d payload_count %d\n",
+		mst_state->start_slot, mst_state->total_avail_slots,
+		mgr->next_start_slot, mgr->payload_count);
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		drm_dbg(mgr->dev,
+			"  Payload#%d: port %p VCPI %d delete %d vc_start_slot %d time_slots %d\n",
+			i, payload->port, payload->vcpi,
+			payload->delete, payload->vc_start_slot, payload->time_slots);
+		i++;
+	}
+
+	if (!payload_table)
+		return;
+
+	drm_dbg(mgr->dev, "Payload table:\n");
+	print_hex_dump(KERN_DEBUG, "  Ptbl ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       payload_table, DP_PAYLOAD_TABLE_SIZE, false);
+}
+
+/**
+ * drm_dp_mst_verify_payload_state - Verify the atomic state for payloads and the related sink payload table
+ * @state: atomic state
+ * @mgr: manager to verify the state for
+ * @verify_sink: %true if the sink payload table needs to be verified as well
+ *
+ * Verify @mgr's atomic state tracking all its payloads and optionally the
+ * related sink payload table.
+ */
+void drm_dp_mst_verify_payload_state(struct drm_atomic_state *state,
+				     struct drm_dp_mst_topology_mgr *mgr,
+				     bool verify_sink)
+{
+	struct drm_dp_mst_topology_state *mst_state;
+	u8 payload_table[DP_PAYLOAD_TABLE_SIZE];
+
+	mst_state = drm_atomic_get_new_mst_topology_state(state, mgr);
+	if (drm_WARN_ON(mgr->dev, !mst_state))
+		return;
+
+	if (drm_WARN_ON(mgr->dev, !verify_mst_payload_state(mst_state))) {
+		print_mst_payload_state(mgr, mst_state, NULL);
+		return;
+	}
+
+	if (!verify_sink)
+		return;
+
+	if (!dump_dp_payload_table(mgr, payload_table))
+		return;
+
+	if (!verify_mst_payload_table(mst_state, payload_table)) {
+		drm_err(mgr->dev, "MST payload state mismatches payload table\n");
+		print_mst_payload_state(mgr, mst_state, payload_table);
+	}
+}
+EXPORT_SYMBOL(drm_dp_mst_verify_payload_state);
+
 static void drm_dp_tx_work(struct work_struct *work)
 {
 	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 632376c291db6..bcc5183188a68 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -925,9 +925,12 @@
 #define DP_PAYLOAD_TABLE_UPDATE_STATUS      0x2c0   /* 1.2 MST */
 # define DP_PAYLOAD_TABLE_UPDATED           (1 << 0)
 # define DP_PAYLOAD_ACT_HANDLED             (1 << 1)
+# define DP_PAYLOAD_ID_SLOT0_5_0_MASK	    (0x3f << 2)
 
 #define DP_VC_PAYLOAD_ID_SLOT_1             0x2c1   /* 1.2 MST */
 /* up to ID_SLOT_63 at 0x2ff */
+# define DP_PAYLOAD_ID_SLOT0_6		    (1 << 7)
+# define DP_PAYLOAD_ID_MASK		    0x7f
 
 /* Source Device-specific */
 #define DP_SOURCE_OUI			    0x300
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 32c764fb9cb56..44c6710ebf315 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -848,6 +848,9 @@ int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
 void drm_dp_mst_dump_topology(struct seq_file *m,
 			      struct drm_dp_mst_topology_mgr *mgr);
+void drm_dp_mst_verify_payload_state(struct drm_atomic_state *state,
+				     struct drm_dp_mst_topology_mgr *mgr,
+				     bool verify_sink);
 
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int __must_check
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 09/17] drm/display/dp_mst: Add a helper to verify the MST payload state
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add a function drivers can use to verify the MST payload state tracking
and compare this to the sink's payload table.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 169 ++++++++++++++++++
 include/drm/display/drm_dp.h                  |   3 +
 include/drm/display/drm_dp_mst_helper.h       |   3 +
 3 files changed, 175 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 0c04b96ae614c..e57dd16955d52 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4847,6 +4847,175 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 }
 EXPORT_SYMBOL(drm_dp_mst_dump_topology);
 
+static bool verify_mst_payload_state(struct drm_dp_mst_topology_state *mst_state)
+{
+	struct drm_dp_mst_topology_mgr *mgr = mst_state->mgr;
+	struct drm_dp_mst_atomic_payload *payload;
+	int payload_count = 0;
+	u64 time_slot_mask = 0;
+	u32 vcpi_mask = 0;
+	int last_set;
+
+	if (BITS_PER_TYPE(time_slot_mask) < mst_state->total_avail_slots)
+		return false;
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		u64 mask;
+
+		if (payload->vc_start_slot == -1)
+			continue;
+
+		if (!payload->time_slots)
+			return false;
+
+		if (payload->vc_start_slot < mst_state->start_slot)
+			return false;
+
+		if (payload->vc_start_slot + payload->time_slots - mst_state->start_slot >
+		    mst_state->total_avail_slots)
+			return false;
+
+		mask = GENMASK_ULL(payload->vc_start_slot + payload->time_slots - 1,
+				   payload->vc_start_slot);
+
+		if (time_slot_mask & mask)
+			return false;
+
+		time_slot_mask |= mask;
+
+		if (payload->vcpi < 1 ||
+		    payload->vcpi & ~DP_PAYLOAD_ID_MASK ||
+		    payload->vcpi > BITS_PER_TYPE(vcpi_mask))
+			return false;
+		if (BIT(payload->vcpi - 1) & vcpi_mask)
+			return false;
+		vcpi_mask |= BIT(payload->vcpi - 1);
+
+		payload_count++;
+	}
+
+	if (payload_count != mgr->payload_count)
+		return false;
+
+	last_set = fls64(time_slot_mask);
+
+	if (last_set &&
+	    GENMASK_ULL(last_set - 1, mst_state->start_slot) != time_slot_mask)
+		return false;
+
+	if (max(mst_state->start_slot, mgr->next_start_slot) !=
+	    max_t(int, mst_state->start_slot, last_set))
+		return false;
+
+	return true;
+}
+
+static int get_payload_table_vcpi(const u8 *table, int slot)
+{
+	if (slot == 0)
+		return FIELD_GET(DP_PAYLOAD_ID_SLOT0_5_0_MASK, table[0]) |
+		       (FIELD_GET(DP_PAYLOAD_ID_SLOT0_6, table[1]) << 6);
+	else
+		return FIELD_GET(DP_PAYLOAD_ID_MASK, table[slot]);
+}
+
+static bool verify_mst_payload_table(struct drm_dp_mst_topology_state *mst_state,
+				     const u8 *payload_table)
+{
+	struct drm_dp_mst_topology_mgr *mgr = mst_state->mgr;
+	struct drm_dp_mst_atomic_payload *payload;
+	int i;
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		if (payload->vc_start_slot == -1)
+			continue;
+
+		if (payload->vc_start_slot + payload->time_slots > DP_PAYLOAD_TABLE_SIZE)
+			return false;
+
+		for (i = 0; i < payload->time_slots; i++)
+			if (get_payload_table_vcpi(payload_table,
+						   payload->vc_start_slot + i) != payload->vcpi)
+				return false;
+	}
+
+	for (i = max(mgr->next_start_slot, mst_state->start_slot);
+	     i < DP_PAYLOAD_TABLE_SIZE;
+	     i++) {
+		if (get_payload_table_vcpi(payload_table, i) != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void print_mst_payload_state(struct drm_dp_mst_topology_mgr *mgr,
+				    struct drm_dp_mst_topology_state *mst_state,
+				    const u8 *payload_table)
+{
+	struct drm_dp_mst_atomic_payload *payload;
+	int i = 0;
+
+	drm_dbg(mgr->dev,
+		"Payload state: start_slot %d total_avail_slots %d next_start_slot %d payload_count %d\n",
+		mst_state->start_slot, mst_state->total_avail_slots,
+		mgr->next_start_slot, mgr->payload_count);
+
+	list_for_each_entry(payload, &mst_state->payloads, next) {
+		drm_dbg(mgr->dev,
+			"  Payload#%d: port %p VCPI %d delete %d vc_start_slot %d time_slots %d\n",
+			i, payload->port, payload->vcpi,
+			payload->delete, payload->vc_start_slot, payload->time_slots);
+		i++;
+	}
+
+	if (!payload_table)
+		return;
+
+	drm_dbg(mgr->dev, "Payload table:\n");
+	print_hex_dump(KERN_DEBUG, "  Ptbl ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       payload_table, DP_PAYLOAD_TABLE_SIZE, false);
+}
+
+/**
+ * drm_dp_mst_verify_payload_state - Verify the atomic state for payloads and the related sink payload table
+ * @state: atomic state
+ * @mgr: manager to verify the state for
+ * @verify_sink: %true if the sink payload table needs to be verified as well
+ *
+ * Verify @mgr's atomic state tracking all its payloads and optionally the
+ * related sink payload table.
+ */
+void drm_dp_mst_verify_payload_state(struct drm_atomic_state *state,
+				     struct drm_dp_mst_topology_mgr *mgr,
+				     bool verify_sink)
+{
+	struct drm_dp_mst_topology_state *mst_state;
+	u8 payload_table[DP_PAYLOAD_TABLE_SIZE];
+
+	mst_state = drm_atomic_get_new_mst_topology_state(state, mgr);
+	if (drm_WARN_ON(mgr->dev, !mst_state))
+		return;
+
+	if (drm_WARN_ON(mgr->dev, !verify_mst_payload_state(mst_state))) {
+		print_mst_payload_state(mgr, mst_state, NULL);
+		return;
+	}
+
+	if (!verify_sink)
+		return;
+
+	if (!dump_dp_payload_table(mgr, payload_table))
+		return;
+
+	if (!verify_mst_payload_table(mst_state, payload_table)) {
+		drm_err(mgr->dev, "MST payload state mismatches payload table\n");
+		print_mst_payload_state(mgr, mst_state, payload_table);
+	}
+}
+EXPORT_SYMBOL(drm_dp_mst_verify_payload_state);
+
 static void drm_dp_tx_work(struct work_struct *work)
 {
 	struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index 632376c291db6..bcc5183188a68 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -925,9 +925,12 @@
 #define DP_PAYLOAD_TABLE_UPDATE_STATUS      0x2c0   /* 1.2 MST */
 # define DP_PAYLOAD_TABLE_UPDATED           (1 << 0)
 # define DP_PAYLOAD_ACT_HANDLED             (1 << 1)
+# define DP_PAYLOAD_ID_SLOT0_5_0_MASK	    (0x3f << 2)
 
 #define DP_VC_PAYLOAD_ID_SLOT_1             0x2c1   /* 1.2 MST */
 /* up to ID_SLOT_63 at 0x2ff */
+# define DP_PAYLOAD_ID_SLOT0_6		    (1 << 7)
+# define DP_PAYLOAD_ID_MASK		    0x7f
 
 /* Source Device-specific */
 #define DP_SOURCE_OUI			    0x300
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 32c764fb9cb56..44c6710ebf315 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -848,6 +848,9 @@ int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
 void drm_dp_mst_dump_topology(struct seq_file *m,
 			      struct drm_dp_mst_topology_mgr *mgr);
+void drm_dp_mst_verify_payload_state(struct drm_atomic_state *state,
+				     struct drm_dp_mst_topology_mgr *mgr,
+				     bool verify_sink);
 
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int __must_check
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 10/17] drm/i915/dp_mst: Verify the MST state of modesetted outputs
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (8 preceding siblings ...)
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

Verify the MST state after disabling/enabling outputs during an atomic
commit.

v2: Iterate through the connectors in each MST topology to prepare
    for a follow-up patch adding HW state verification.

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

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 36269ae34075e..7976658771ab3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7539,8 +7539,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 	intel_check_cpu_fifo_underruns(dev_priv);
 	intel_check_pch_fifo_underruns(dev_priv);
 
-	if (state->modeset)
+	if (state->modeset) {
 		intel_verify_planes(state);
+		intel_dp_mst_verify_state(state);
+	}
 
 	intel_sagv_post_plane_update(state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 501163c5c590d..d6b0ef38f6563 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4085,7 +4085,7 @@ static int intel_dp_prep_link_retrain(struct intel_dp *intel_dp,
 	return ret;
 }
 
-static bool intel_dp_is_connected(struct intel_dp *intel_dp)
+bool intel_dp_is_connected(struct intel_dp *intel_dp)
 {
 	struct intel_connector *connector = intel_dp->attached_connector;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index ef39e4f7a329e..1294384840190 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -102,6 +102,7 @@ void intel_read_dp_sdp(struct intel_encoder *encoder,
 		       struct intel_crtc_state *crtc_state,
 		       unsigned int type);
 bool intel_digital_port_connected(struct intel_encoder *encoder);
+bool intel_dp_is_connected(struct intel_dp *intel_dp);
 int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
 u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
 				u32 link_clock, u32 lane_count,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 421a0f8c28229..08222fc6c5ecd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1276,3 +1276,40 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 
 	return 0;
 }
+
+/**
+ * intel_dp_mst_verify_state - Verify the MST state for all connectors in the atomic state
+ * @state: atomic state
+ *
+ * Verify the MST SW and sink state for all modesetted MST connectors in @state.
+ */
+void intel_dp_mst_verify_state(struct intel_atomic_state *state)
+{
+	struct drm_dp_mst_topology_state *mst_state;
+	struct drm_dp_mst_topology_mgr *mgr;
+	int i;
+
+	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
+		struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+		struct drm_connector *_connector;
+		struct drm_connector_state *_conn_state;
+		bool mst_needs_modeset = false;
+
+		for_each_new_connector_in_state(&state->base, _connector, _conn_state, i) {
+			struct intel_connector *connector = to_intel_connector(_connector);
+
+			if (!connector->mst_port ||
+			    !intel_connector_needs_modeset(state, &connector->base))
+				continue;
+
+			mst_needs_modeset = true;
+
+			break;
+		}
+
+		if (!mst_needs_modeset)
+			continue;
+
+		drm_dp_mst_verify_payload_state(&state->base, mgr, intel_dp_is_connected(intel_dp));
+	}
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index cd0ae661dc20b..74633390c280c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -26,5 +26,6 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 int intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
 						  struct intel_connector *connector,
 						  struct intel_crtc *crtc);
+void intel_dp_mst_verify_state(struct intel_atomic_state *state);
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 842d70f0dfd2a..45f0d9789ef8e 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -13,6 +13,7 @@
 #include "intel_crtc_state_dump.h"
 #include "intel_display.h"
 #include "intel_display_types.h"
+#include "intel_dp_mst.h"
 #include "intel_fdi.h"
 #include "intel_modeset_verify.h"
 #include "intel_snps_phy.h"
@@ -244,4 +245,5 @@ void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
 	verify_encoder_state(dev_priv, state);
 	verify_connector_state(state, NULL);
 	intel_shared_dpll_verify_disabled(dev_priv);
+	intel_dp_mst_verify_state(state);
 }
-- 
2.37.1


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

* [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add a way for drivers to query if allocating time slots for any payloads
in a given MST topology failed. This is needed by a follow-up i915 patch
verifying the SW vs. HW state of the MST topology.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 35 ++++++++++++++++---
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e57dd16955d52..f2081f3fad0da 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3306,15 +3306,14 @@ int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
 			     struct drm_dp_mst_atomic_payload *payload)
 {
 	struct drm_dp_mst_port *port;
-	int ret;
+	int ret = 0;
 
 	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
 	if (!port) {
 		drm_dbg_kms(mgr->dev,
 			    "VCPI %d for port %p not in topology, not creating a payload\n",
 			    payload->vcpi, payload->port);
-		payload->vc_start_slot = -1;
-		return 0;
+		goto alloc_fail;
 	}
 
 	if (mgr->payload_count == 0)
@@ -3327,14 +3326,21 @@ int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
 	if (ret < 0) {
 		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
 			 payload->port, ret);
-		payload->vc_start_slot = -1;
-		return ret;
+		goto alloc_fail;
 	}
 
+	payload->alloc_failed = false;
+
 	mgr->payload_count++;
 	mgr->next_start_slot += payload->time_slots;
 
 	return 0;
+
+alloc_fail:
+	payload->vc_start_slot = -1;
+	payload->alloc_failed = true;
+
+	return ret;
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part1);
 
@@ -3423,6 +3429,25 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part2);
 
+/**
+ * drm_dp_mst_has_payload_alloc_errors - Query for payload allocation errors
+ * @mst_state: The MST atomic state
+ *
+ * Returns %true if the allocation of any of the payloads in @mst_state
+ * failed, %false otherwise.
+ */
+bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state)
+{
+	struct drm_dp_mst_atomic_payload *pos;
+
+	list_for_each_entry(pos, &mst_state->payloads, next)
+		if (pos->alloc_failed)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL(drm_dp_mst_has_payload_alloc_errors);
+
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port,
 				 int offset, int size, u8 *bytes)
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 44c6710ebf315..53b251b264e89 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -568,6 +568,8 @@ struct drm_dp_mst_atomic_payload {
 	bool delete : 1;
 	/** @dsc_enabled: Whether or not this payload has DSC enabled */
 	bool dsc_enabled : 1;
+	/** @alloc_failed: Whether or not allocating this payload failed */
+	bool alloc_failed : 1;
 
 	/** @next: The list node for this payload */
 	struct list_head next;
@@ -843,6 +845,7 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
+bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add a way for drivers to query if allocating time slots for any payloads
in a given MST topology failed. This is needed by a follow-up i915 patch
verifying the SW vs. HW state of the MST topology.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 35 ++++++++++++++++---
 include/drm/display/drm_dp_mst_helper.h       |  3 ++
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e57dd16955d52..f2081f3fad0da 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3306,15 +3306,14 @@ int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
 			     struct drm_dp_mst_atomic_payload *payload)
 {
 	struct drm_dp_mst_port *port;
-	int ret;
+	int ret = 0;
 
 	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
 	if (!port) {
 		drm_dbg_kms(mgr->dev,
 			    "VCPI %d for port %p not in topology, not creating a payload\n",
 			    payload->vcpi, payload->port);
-		payload->vc_start_slot = -1;
-		return 0;
+		goto alloc_fail;
 	}
 
 	if (mgr->payload_count == 0)
@@ -3327,14 +3326,21 @@ int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
 	if (ret < 0) {
 		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
 			 payload->port, ret);
-		payload->vc_start_slot = -1;
-		return ret;
+		goto alloc_fail;
 	}
 
+	payload->alloc_failed = false;
+
 	mgr->payload_count++;
 	mgr->next_start_slot += payload->time_slots;
 
 	return 0;
+
+alloc_fail:
+	payload->vc_start_slot = -1;
+	payload->alloc_failed = true;
+
+	return ret;
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part1);
 
@@ -3423,6 +3429,25 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part2);
 
+/**
+ * drm_dp_mst_has_payload_alloc_errors - Query for payload allocation errors
+ * @mst_state: The MST atomic state
+ *
+ * Returns %true if the allocation of any of the payloads in @mst_state
+ * failed, %false otherwise.
+ */
+bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state)
+{
+	struct drm_dp_mst_atomic_payload *pos;
+
+	list_for_each_entry(pos, &mst_state->payloads, next)
+		if (pos->alloc_failed)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL(drm_dp_mst_has_payload_alloc_errors);
+
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port,
 				 int offset, int size, u8 *bytes)
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 44c6710ebf315..53b251b264e89 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -568,6 +568,8 @@ struct drm_dp_mst_atomic_payload {
 	bool delete : 1;
 	/** @dsc_enabled: Whether or not this payload has DSC enabled */
 	bool dsc_enabled : 1;
+	/** @alloc_failed: Whether or not allocating this payload failed */
+	bool alloc_failed : 1;
 
 	/** @next: The list node for this payload */
 	struct list_head next;
@@ -843,6 +845,7 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
+bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [PATCH v2 12/17] drm/display/dp_mst: Add helpers to query payload allocation properties
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add helper functions to query the virtual channel and time slots for a
payload and the current payload count and total allocated time slots in
an MST topology. These are needed by a follow-up i915 patch verifying
the SW vs. HW state of the MST topology.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 36 +++++++++++++++++++
 include/drm/display/drm_dp_mst_helper.h       | 21 +++++++++++
 2 files changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index f2081f3fad0da..47605f67578ad 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3448,6 +3448,42 @@ bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state
 }
 EXPORT_SYMBOL(drm_dp_mst_has_payload_alloc_errors);
 
+/**
+ * drm_dp_mst_payload_vchannel - Return the DP virtual channel for a payload
+ * @mst_state: The MST atomic state containing @payload
+ * @payload: The payload to get the virtual channel for
+ *
+ * Return the DP virtual channel for @payload. The virtual channel is a
+ * contiguous range of MST Transmission Units on the DP main lanes between
+ * the source DPTX and the first downstream MST hub DPRX. Accordingly the
+ * channel is determined by the payload's position on the payload list
+ * ordered by VC start slot.
+ *
+ * Returns the 0-based virtual channel of @payload if it's in @mst_state with
+ * its time slots being allocated, or -1 otherwise.
+ */
+int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
+				const struct drm_dp_mst_atomic_payload *payload)
+{
+	struct drm_dp_mst_atomic_payload *pos;
+	int vc = 0;
+	bool found = false;
+
+	list_for_each_entry(pos, &mst_state->payloads, next) {
+		if (pos->vc_start_slot == -1)
+			continue;
+
+		if (pos == payload)
+			found = true;
+
+		if (pos->vc_start_slot < payload->vc_start_slot)
+			vc++;
+	}
+
+	return found ? vc : -1;
+}
+EXPORT_SYMBOL(drm_dp_mst_payload_vchannel);
+
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port,
 				 int offset, int size, u8 *bytes)
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 53b251b264e89..bb7c595096fed 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -846,6 +846,27 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
 bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
+int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
+				const struct drm_dp_mst_atomic_payload *payload);
+
+static inline int
+drm_dp_mst_payload_count(const struct drm_dp_mst_topology_state *mst_state)
+{
+	return mst_state->mgr->payload_count;
+}
+
+static inline int
+drm_dp_mst_allocated_time_slots(const struct drm_dp_mst_topology_state *mst_state)
+{
+	return drm_dp_mst_payload_count(mst_state) ?
+		mst_state->mgr->next_start_slot - mst_state->start_slot : 0;
+}
+
+static inline int
+drm_dp_mst_payload_time_slots(const struct drm_dp_mst_atomic_payload *payload)
+{
+	return payload->time_slots;
+}
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 12/17] drm/display/dp_mst: Add helpers to query payload allocation properties
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add helper functions to query the virtual channel and time slots for a
payload and the current payload count and total allocated time slots in
an MST topology. These are needed by a follow-up i915 patch verifying
the SW vs. HW state of the MST topology.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 36 +++++++++++++++++++
 include/drm/display/drm_dp_mst_helper.h       | 21 +++++++++++
 2 files changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index f2081f3fad0da..47605f67578ad 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3448,6 +3448,42 @@ bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state
 }
 EXPORT_SYMBOL(drm_dp_mst_has_payload_alloc_errors);
 
+/**
+ * drm_dp_mst_payload_vchannel - Return the DP virtual channel for a payload
+ * @mst_state: The MST atomic state containing @payload
+ * @payload: The payload to get the virtual channel for
+ *
+ * Return the DP virtual channel for @payload. The virtual channel is a
+ * contiguous range of MST Transmission Units on the DP main lanes between
+ * the source DPTX and the first downstream MST hub DPRX. Accordingly the
+ * channel is determined by the payload's position on the payload list
+ * ordered by VC start slot.
+ *
+ * Returns the 0-based virtual channel of @payload if it's in @mst_state with
+ * its time slots being allocated, or -1 otherwise.
+ */
+int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
+				const struct drm_dp_mst_atomic_payload *payload)
+{
+	struct drm_dp_mst_atomic_payload *pos;
+	int vc = 0;
+	bool found = false;
+
+	list_for_each_entry(pos, &mst_state->payloads, next) {
+		if (pos->vc_start_slot == -1)
+			continue;
+
+		if (pos == payload)
+			found = true;
+
+		if (pos->vc_start_slot < payload->vc_start_slot)
+			vc++;
+	}
+
+	return found ? vc : -1;
+}
+EXPORT_SYMBOL(drm_dp_mst_payload_vchannel);
+
 static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port,
 				 int offset, int size, u8 *bytes)
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 53b251b264e89..bb7c595096fed 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -846,6 +846,27 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
 bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
+int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
+				const struct drm_dp_mst_atomic_payload *payload);
+
+static inline int
+drm_dp_mst_payload_count(const struct drm_dp_mst_topology_state *mst_state)
+{
+	return mst_state->mgr->payload_count;
+}
+
+static inline int
+drm_dp_mst_allocated_time_slots(const struct drm_dp_mst_topology_state *mst_state)
+{
+	return drm_dp_mst_payload_count(mst_state) ?
+		mst_state->mgr->next_start_slot - mst_state->start_slot : 0;
+}
+
+static inline int
+drm_dp_mst_payload_time_slots(const struct drm_dp_mst_atomic_payload *payload)
+{
+	return payload->time_slots;
+}
 
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.37.1


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

* [PATCH v2 13/17] drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

In a follow-up workaround for a payload allocation problem the driver
uses DP_PAYLOAD_TABLE_SIZE to determine when the workaround is needed,
so export the definition.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 --
 include/drm/display/drm_dp.h                  | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 47605f67578ad..d0e929df7d088 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4771,8 +4771,6 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
 	}
 }
 
-#define DP_PAYLOAD_TABLE_SIZE		64
-
 static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
 				  char *buf)
 {
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index bcc5183188a68..8f18f66ff5bc3 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -932,6 +932,8 @@
 # define DP_PAYLOAD_ID_SLOT0_6		    (1 << 7)
 # define DP_PAYLOAD_ID_MASK		    0x7f
 
+#define DP_PAYLOAD_TABLE_SIZE		    64
+
 /* Source Device-specific */
 #define DP_SOURCE_OUI			    0x300
 
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 13/17] drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

In a follow-up workaround for a payload allocation problem the driver
uses DP_PAYLOAD_TABLE_SIZE to determine when the workaround is needed,
so export the definition.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 --
 include/drm/display/drm_dp.h                  | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 47605f67578ad..d0e929df7d088 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -4771,8 +4771,6 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
 	}
 }
 
-#define DP_PAYLOAD_TABLE_SIZE		64
-
 static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
 				  char *buf)
 {
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index bcc5183188a68..8f18f66ff5bc3 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -932,6 +932,8 @@
 # define DP_PAYLOAD_ID_SLOT0_6		    (1 << 7)
 # define DP_PAYLOAD_ID_MASK		    0x7f
 
+#define DP_PAYLOAD_TABLE_SIZE		    64
+
 /* Source Device-specific */
 #define DP_SOURCE_OUI			    0x300
 
-- 
2.37.1


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

* [PATCH v2 14/17] drm/display/dp_mst: Factor out a helper to reset the payload table
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

A follow-up patch adds a workaround for a payload allocation problem in
a DELL monitor. For this the driver needs to reset the payload table in
the monitor's MST hub, factor out a helper to do this.

While at it use DP_PAYLOAD_TABLE_SIZE in the reset command, instead of
open coding it.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 8 +++++++-
 include/drm/display/drm_dp_mst_helper.h       | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index d0e929df7d088..eb170389cf9bc 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3429,6 +3429,12 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part2);
 
+int drm_dp_mst_reset_payload_table(struct drm_dp_mst_topology_mgr *mgr)
+{
+	return drm_dp_dpcd_write_payload(mgr, 0, 0, DP_PAYLOAD_TABLE_SIZE - 1);
+}
+EXPORT_SYMBOL(drm_dp_mst_reset_payload_table);
+
 /**
  * drm_dp_mst_has_payload_alloc_errors - Query for payload allocation errors
  * @mst_state: The MST atomic state
@@ -3699,7 +3705,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 			goto out_unlock;
 
 		/* Write reset payload */
-		drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f);
+		drm_dp_mst_reset_payload_table(mgr);
 
 		queue_work(system_long_wq, &mgr->work);
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index bb7c595096fed..2d15399df2950 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -845,6 +845,7 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
+int drm_dp_mst_reset_payload_table(struct drm_dp_mst_topology_mgr *mgr);
 bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
 int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
 				const struct drm_dp_mst_atomic_payload *payload);
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 14/17] drm/display/dp_mst: Factor out a helper to reset the payload table
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

A follow-up patch adds a workaround for a payload allocation problem in
a DELL monitor. For this the driver needs to reset the payload table in
the monitor's MST hub, factor out a helper to do this.

While at it use DP_PAYLOAD_TABLE_SIZE in the reset command, instead of
open coding it.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 8 +++++++-
 include/drm/display/drm_dp_mst_helper.h       | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index d0e929df7d088..eb170389cf9bc 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3429,6 +3429,12 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
 }
 EXPORT_SYMBOL(drm_dp_add_payload_part2);
 
+int drm_dp_mst_reset_payload_table(struct drm_dp_mst_topology_mgr *mgr)
+{
+	return drm_dp_dpcd_write_payload(mgr, 0, 0, DP_PAYLOAD_TABLE_SIZE - 1);
+}
+EXPORT_SYMBOL(drm_dp_mst_reset_payload_table);
+
 /**
  * drm_dp_mst_has_payload_alloc_errors - Query for payload allocation errors
  * @mst_state: The MST atomic state
@@ -3699,7 +3705,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 			goto out_unlock;
 
 		/* Write reset payload */
-		drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f);
+		drm_dp_mst_reset_payload_table(mgr);
 
 		queue_work(system_long_wq, &mgr->work);
 
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index bb7c595096fed..2d15399df2950 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -845,6 +845,7 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 			   struct drm_dp_mst_topology_state *mst_state,
 			   const struct drm_dp_mst_atomic_payload *old_payload,
 			   struct drm_dp_mst_atomic_payload *new_payload);
+int drm_dp_mst_reset_payload_table(struct drm_dp_mst_topology_mgr *mgr);
 bool drm_dp_mst_has_payload_alloc_errors(const struct drm_dp_mst_topology_state *mst_state);
 int drm_dp_mst_payload_vchannel(const struct drm_dp_mst_topology_state *mst_state,
 				const struct drm_dp_mst_atomic_payload *payload);
-- 
2.37.1


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

* [PATCH v2 15/17] drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
@ 2023-01-31 15:05   ` Imre Deak
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
                     ` (18 subsequent siblings)
  19 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

The DELL P2715Q monitor's MST hub has a payload allocation problem,
where the VCPI used to reserve the last two time slots (at position
0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
later payload configurations. To work around the problem in a follow-up
patch the driver needs to reset the payload table after all payloads
have been freed; add a quirk the driver can use to detect the monitor
and apply the WA if needed.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_helper.c | 2 ++
 include/drm/display/drm_dp_helper.h     | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 16565a0a5da6d..e2cf4b4fe11ea 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2244,6 +2244,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
 	{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
 	/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */
 	{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
+	/* DELL P2715Q MST payload table must be reset after the two last payload slots get allocated. */
+	{ OUI(0x00, 0xe0, 0x4c), DEVICE_ID('D', 'p', '1', '.', '2', 0), true, BIT(DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA) },
 };
 
 #undef OUI
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index ab55453f2d2cd..fcd445921ec9d 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -620,6 +620,14 @@ enum drm_dp_quirk {
 	 * the DP_MAX_LINK_RATE register reporting a lower max multiplier.
 	 */
 	DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS,
+	/**
+	 * @DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA:
+	 *
+	 * An bug in the MST branch device's payload allocation logic requires
+	 * the payload table to be reset after its last two payload slots get
+	 * allocated.
+	 */
+	DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA,
 };
 
 /**
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 15/17] drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem
@ 2023-01-31 15:05   ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

The DELL P2715Q monitor's MST hub has a payload allocation problem,
where the VCPI used to reserve the last two time slots (at position
0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
later payload configurations. To work around the problem in a follow-up
patch the driver needs to reset the payload table after all payloads
have been freed; add a quirk the driver can use to detect the monitor
and apply the WA if needed.

Cc: Lyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/display/drm_dp_helper.c | 2 ++
 include/drm/display/drm_dp_helper.h     | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 16565a0a5da6d..e2cf4b4fe11ea 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2244,6 +2244,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
 	{ OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
 	/* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */
 	{ OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
+	/* DELL P2715Q MST payload table must be reset after the two last payload slots get allocated. */
+	{ OUI(0x00, 0xe0, 0x4c), DEVICE_ID('D', 'p', '1', '.', '2', 0), true, BIT(DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA) },
 };
 
 #undef OUI
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index ab55453f2d2cd..fcd445921ec9d 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -620,6 +620,14 @@ enum drm_dp_quirk {
 	 * the DP_MAX_LINK_RATE register reporting a lower max multiplier.
 	 */
 	DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS,
+	/**
+	 * @DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA:
+	 *
+	 * An bug in the MST branch device's payload allocation logic requires
+	 * the payload table to be reset after its last two payload slots get
+	 * allocated.
+	 */
+	DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA,
 };
 
 /**
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (14 preceding siblings ...)
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-01-31 22:47   ` Lyude Paul
  2023-01-31 23:43   ` Lyude Paul
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders Imre Deak
                   ` (3 subsequent siblings)
  19 siblings, 2 replies; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

The DELL P2715Q monitor's MST hub has a payload allocation problem,
where the VCPI used to reserve the last two time slots (at position
0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
later payload configurations.

The problem results at least in streams reusing older VCPIs to stay
blank on the screen and the payload table containing bogus VCPIs
(repeating the one earlier used to reserve the 0x3e, 0x3f slots) after
the last reservered slot.

To work around the problem detect this monitor and the condition for the
problem (when the last two slots get allocated in a commit), force a
full modeset of the MST topology in the subsequent commit and reset the
payload table during the latter commit after all payloads have been
freed.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_atomic.c   | 13 +++--
 drivers/gpu/drm/i915/display/intel_atomic.h   |  3 +-
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  5 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 48 +++++++++++++++++--
 5 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 0f1c5b9c9a826..04e5f0e0fffa6 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -616,7 +616,8 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 }
 
 static int modeset_pipe(struct intel_atomic_state *state,
-			struct intel_crtc *crtc, const char *reason)
+			struct intel_crtc *crtc, const char *reason,
+			bool allow_fastset)
 {
 	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct intel_crtc_state *crtc_state;
@@ -629,6 +630,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
 		return PTR_ERR(crtc_state);
 
 	crtc_state->uapi.mode_changed = true;
+	if (!allow_fastset)
+		crtc_state->uapi.connectors_changed = true;
 	crtc_state->update_pipe = false;
 
 	return intel_atomic_add_affected_planes(state, crtc);
@@ -639,6 +642,7 @@ static int modeset_pipe(struct intel_atomic_state *state,
  * @state: atomic state
  * @connector: connector to add the state for
  * @reason: the reason why the connector needs to be added
+ * @allow_fastset: allow a fastset
  *
  * Add the @connector to the atomic state with its CRTC state and force a modeset
  * on the CRTC if any.
@@ -648,7 +652,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
  * Returns 0 in case of success, a negative error code on failure.
  */
 int intel_atomic_modeset_connector(struct intel_atomic_state *state,
-				   struct intel_connector *connector, const char *reason)
+				   struct intel_connector *connector, const char *reason,
+				   bool allow_fastset)
 {
 	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct drm_connector_state *conn_state;
@@ -671,7 +676,7 @@ int intel_atomic_modeset_connector(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
-	return modeset_pipe(state, crtc, reason);
+	return modeset_pipe(state, crtc, reason, allow_fastset);
 }
 
 /**
@@ -700,7 +705,7 @@ int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
-	return modeset_pipe(state, crtc, reason);
+	return modeset_pipe(state, crtc, reason, true);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
index 84295d388e3cb..7778aea8a09fe 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.h
+++ b/drivers/gpu/drm/i915/display/intel_atomic.h
@@ -59,7 +59,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
 			      struct intel_crtc *crtc, const char *reason);
 int intel_atomic_modeset_connector(struct intel_atomic_state *state,
-				   struct intel_connector *connector, const char *reason);
+				   struct intel_connector *connector, const char *reason,
+				   bool allow_fastset);
 int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
 				   const char *reason);
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 9ccae7a460200..06d51d2b5e0d6 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1656,6 +1656,7 @@ struct intel_dp {
 	bool has_audio;
 	bool reset_link_params;
 	bool use_max_params;
+	bool mst_reset_payload_table;
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
 	u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index d6b0ef38f6563..c157bcd976103 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4689,6 +4689,8 @@ intel_dp_detect(struct drm_connector *connector,
 		memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
 		memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
 
+		intel_dp->mst_reset_payload_table = false;
+
 		if (intel_dp->is_mst) {
 			drm_dbg_kms(&dev_priv->drm,
 				    "MST device may have disappeared %d vs %d\n",
@@ -4924,7 +4926,8 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
 			continue;
 
 		ret = intel_atomic_modeset_connector(state, connector,
-						     "connector tile group");
+						     "connector tile group",
+						     true);
 		if (ret)
 			break;
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 08222fc6c5ecd..a9bb339e41987 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -422,9 +422,10 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct drm_connector_list_iter connector_list_iter;
 	struct intel_connector *connector_iter;
+	bool reset_payload_table = connector->mst_port->mst_reset_payload_table;
 	int ret = 0;
 
-	if (DISPLAY_VER(dev_priv) < 12)
+	if (DISPLAY_VER(dev_priv) < 12 && !reset_payload_table)
 		return  0;
 
 	if (!intel_connector_needs_modeset(state, &connector->base))
@@ -437,7 +438,8 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
 			continue;
 
 		ret = intel_atomic_modeset_connector(state, connector_iter,
-						     "MST master transcoder");
+						     "MST master transcoder",
+						     !reset_payload_table);
 		if (ret)
 			break;
 	}
@@ -531,6 +533,41 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
 }
 
+static void detect_payload_allocation_bug(const struct drm_dp_mst_topology_state *mst_state,
+					  const struct intel_connector *connector,
+					  struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+	if (!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA))
+		return;
+
+	if (drm_dp_mst_allocated_time_slots(mst_state) < DP_PAYLOAD_TABLE_SIZE - 2)
+		return;
+
+	drm_dbg(&i915->drm,
+		"[CONNECTOR:%d:%s] Payload table allocation bug detected\n",
+		connector->base.base.id, connector->base.name);
+
+	intel_dp->mst_reset_payload_table = true;
+}
+
+static void payload_allocation_bug_wa(const struct intel_connector *connector,
+				      struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+	if (!intel_dp->mst_reset_payload_table)
+		return;
+
+	drm_dbg(&i915->drm,
+		"[CONNECTOR:%d:%s] Resetting payload table due to allocation bug\n",
+		connector->base.base.id, connector->base.name);
+
+	drm_dp_mst_reset_payload_table(&intel_dp->mst_mgr);
+	intel_dp->mst_reset_payload_table = false;
+}
+
 static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
 				      struct intel_encoder *encoder,
 				      const struct intel_crtc_state *old_crtc_state,
@@ -594,10 +631,13 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
 
 
 	intel_mst->connector = NULL;
-	if (last_mst_stream)
+	if (last_mst_stream) {
 		dig_port->base.post_disable(state, &dig_port->base,
 						  old_crtc_state, NULL);
 
+		payload_allocation_bug_wa(connector, intel_dp);
+	}
+
 	drm_dbg_kms(&dev_priv->drm, "active links %d\n",
 		    intel_dp->active_mst_links);
 }
@@ -662,6 +702,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
 		drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
 			connector->base.name, ret);
 
+	detect_payload_allocation_bug(mst_state, connector, intel_dp);
+
 	/*
 	 * Before Gen 12 this is not done as part of
 	 * dig_port->base.pre_enable() and should be done here. For
-- 
2.37.1


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

* [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (15 preceding siblings ...)
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q " Imre Deak
@ 2023-01-31 15:05 ` Imre Deak
  2023-02-01  9:41   ` Jani Nikula
  2023-01-31 15:27 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Patchwork
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 70+ messages in thread
From: Imre Deak @ 2023-01-31 15:05 UTC (permalink / raw)
  To: intel-gfx

Read out and verify an MST encoder's HW state after any of the
MST connectors driven by the encoder is modeset.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c      | 91 +++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
 .../drm/i915/display/intel_display_types.h    | 18 ++++
 drivers/gpu/drm/i915/display/intel_dp_mst.c   | 68 +++++++++++++-
 drivers/gpu/drm/i915/display/intel_dp_mst.h   |  2 +-
 .../drm/i915/display/intel_modeset_verify.c   |  2 +-
 drivers/gpu/drm/i915/i915_reg.h               |  6 +-
 7 files changed, 173 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 254559abedfba..6acda4d357af3 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -661,13 +661,23 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
 	return ret;
 }
 
+static enum transcoder get_transcoder_for_pipe(const struct intel_encoder *encoder,
+					       enum pipe pipe)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+	if (HAS_TRANSCODER(i915, TRANSCODER_EDP) && encoder->port == PORT_A)
+		return TRANSCODER_EDP;
+	else
+		return (enum transcoder) pipe;
+}
+
 bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 {
 	struct drm_device *dev = intel_connector->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
 	int type = intel_connector->base.connector_type;
-	enum port port = encoder->port;
 	enum transcoder cpu_transcoder;
 	intel_wakeref_t wakeref;
 	enum pipe pipe = 0;
@@ -684,10 +694,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 		goto out;
 	}
 
-	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
-		cpu_transcoder = TRANSCODER_EDP;
-	else
-		cpu_transcoder = (enum transcoder) pipe;
+	cpu_transcoder = get_transcoder_for_pipe(encoder, pipe);
 
 	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
 
@@ -2155,17 +2162,29 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
 		return DP_TP_CTL(encoder->port);
 }
 
-i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
-			    const struct intel_crtc_state *crtc_state)
+static i915_reg_t __dp_tp_status_reg(struct intel_encoder *encoder,
+				     enum transcoder transcoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
 	if (DISPLAY_VER(dev_priv) >= 12)
-		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
+		return TGL_DP_TP_STATUS(transcoder);
 	else
 		return DP_TP_STATUS(encoder->port);
 }
 
+i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
+			    const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum transcoder transcoder = INVALID_TRANSCODER;
+
+	if (DISPLAY_VER(dev_priv) >= 12)
+		transcoder = tgl_dp_tp_transcoder(crtc_state);
+
+	return __dp_tp_status_reg(encoder, transcoder);
+}
+
 static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
 							  const struct intel_crtc_state *crtc_state,
 							  bool enable)
@@ -3500,6 +3519,61 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
 	intel_audio_codec_get_config(encoder, pipe_config);
 }
 
+static bool intel_ddi_get_hw_mst_state(struct intel_encoder *encoder,
+				       struct intel_encoder_mst_state *state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	enum transcoder transcoder;
+	u8 vc_pipe_mask = 0;
+	u8 pipe_mask;
+	bool is_mst;
+	u32 dp_status;
+	bool in_mst_mode;
+	int vc;
+
+	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
+	if (!is_mst || !pipe_mask)
+		return false;
+
+	transcoder = get_transcoder_for_pipe(encoder, ffs(pipe_mask) - 1);
+	dp_status = intel_de_read(i915, __dp_tp_status_reg(encoder, transcoder));
+
+	in_mst_mode = REG_FIELD_GET(DP_TP_STATUS_MODE_STATUS_MST, dp_status);
+	if (drm_WARN_ON(&i915->drm, !in_mst_mode))
+		return false;
+
+	state->num_mst_streams = REG_FIELD_GET(DP_TP_STATUS_NUM_STREAMS_ENABLED, dp_status);
+	drm_WARN_ON(&i915->drm, state->num_mst_streams == 0 ||
+				state->num_mst_streams > ARRAY_SIZE(state->mst_stream));
+
+	for (vc = 0; vc < ARRAY_SIZE(state->mst_stream); vc++) {
+		struct intel_crtc *crtc;
+		struct intel_link_m_n m_n;
+
+		if (vc >= state->num_mst_streams) {
+			state->mst_stream[vc].pipe = INVALID_PIPE;
+			state->mst_stream[vc].tu = 0;
+			continue;
+		}
+
+		state->mst_stream[vc].pipe = (dp_status & DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)) >>
+					     DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc);
+
+		drm_WARN_ON(&i915->drm, vc_pipe_mask & BIT(state->mst_stream[vc].pipe));
+		vc_pipe_mask |= BIT(state->mst_stream[vc].pipe);
+
+		transcoder = get_transcoder_for_pipe(encoder, state->mst_stream[vc].pipe);
+		crtc = intel_crtc_for_pipe(i915, state->mst_stream[vc].pipe);
+
+		intel_cpu_transcoder_get_m1_n1(crtc, transcoder, &m_n);
+		state->mst_stream[vc].tu = m_n.tu;
+	}
+
+	drm_WARN_ON(&i915->drm, vc_pipe_mask != pipe_mask);
+
+	return true;
+}
+
 void intel_ddi_get_clock(struct intel_encoder *encoder,
 			 struct intel_crtc_state *crtc_state,
 			 struct intel_shared_dpll *pll)
@@ -4384,6 +4458,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 	encoder->post_disable = intel_ddi_post_disable;
 	encoder->update_pipe = intel_ddi_update_pipe;
 	encoder->get_hw_state = intel_ddi_get_hw_state;
+	encoder->get_hw_mst_state = intel_ddi_get_hw_mst_state;
 	encoder->sync_state = intel_ddi_sync_state;
 	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
 	encoder->suspend = intel_ddi_encoder_suspend;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 7976658771ab3..8b2b7a30b1b01 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7541,7 +7541,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	if (state->modeset) {
 		intel_verify_planes(state);
-		intel_dp_mst_verify_state(state);
+		intel_dp_mst_verify_state(state, true);
 	}
 
 	intel_sagv_post_plane_update(state);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 06d51d2b5e0d6..066a1b956b0ba 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -151,6 +151,18 @@ enum intel_hotplug_state {
 	INTEL_HOTPLUG_RETRY,
 };
 
+struct intel_encoder_mst_state {
+	/**
+	 *  TODO: move the encoder state from intel_crtc_state to here, and
+	 *  make this a generic encoder state.
+	 */
+	u8 num_mst_streams;
+	struct {
+		u8 pipe;
+		u8 tu;
+	} mst_stream[I915_MAX_PIPES];
+};
+
 struct intel_encoder {
 	struct drm_encoder base;
 
@@ -213,6 +225,12 @@ struct intel_encoder {
 	 * be set correctly before calling this function. */
 	void (*get_config)(struct intel_encoder *,
 			   struct intel_crtc_state *pipe_config);
+	/**
+	 * Determine if the encoder is active in MST mode and if so
+	 * read out the corresponding HW state.
+	 */
+	bool (*get_hw_mst_state)(struct intel_encoder *encoder,
+				 struct intel_encoder_mst_state *mst_state);
 
 	/*
 	 * Optional hook called during init/resume to sync any state
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index a9bb339e41987..5bc18450b09c6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1322,23 +1322,55 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 /**
  * intel_dp_mst_verify_state - Verify the MST state for all connectors in the atomic state
  * @state: atomic state
+ * @connectors_enabled: %true if called after the modeset's enabling
+ *                      %false if called after the disabling sequence
  *
  * Verify the MST SW and sink state for all modesetted MST connectors in @state.
  */
-void intel_dp_mst_verify_state(struct intel_atomic_state *state)
+void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled)
 {
+	struct drm_i915_private *i915 = to_i915(state->base.dev);
 	struct drm_dp_mst_topology_state *mst_state;
 	struct drm_dp_mst_topology_mgr *mgr;
 	int i;
 
 	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
 		struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+		struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+		struct intel_encoder_mst_state hw_state;
 		struct drm_connector *_connector;
 		struct drm_connector_state *_conn_state;
 		bool mst_needs_modeset = false;
+		bool has_alloc_errors = drm_dp_mst_has_payload_alloc_errors(mst_state);
+		int i;
+
+		if (!encoder->get_hw_mst_state(encoder, &hw_state)) {
+			drm_WARN_ON(&i915->drm, drm_dp_mst_payload_count(mst_state));
+			continue;
+		}
+
+		/*
+		 * The streams for which the payload allocation has failed got
+		 * still enabled in the HW. In that case check only for an
+		 * upper bound of mgr->payload_count here and skip the MST payload
+		 * vs. HW state check later, since those will not match.
+		 */
+		if (!has_alloc_errors)
+			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams !=
+						drm_dp_mst_payload_count(mst_state));
+		else
+			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams <
+						drm_dp_mst_payload_count(mst_state));
 
 		for_each_new_connector_in_state(&state->base, _connector, _conn_state, i) {
 			struct intel_connector *connector = to_intel_connector(_connector);
+			struct intel_digital_connector_state *conn_state;
+			struct intel_crtc *crtc;
+			struct intel_crtc_state *crtc_state = NULL;
+			struct drm_dp_mst_atomic_payload *payload;
+			enum pipe pipe;
+			int sw_vc;
+			int tu;
 
 			if (!connector->mst_port ||
 			    !intel_connector_needs_modeset(state, &connector->base))
@@ -1346,7 +1378,39 @@ void intel_dp_mst_verify_state(struct intel_atomic_state *state)
 
 			mst_needs_modeset = true;
 
-			break;
+			if (has_alloc_errors)
+				break;
+
+			payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
+			if (drm_WARN_ON(&i915->drm, !payload))
+				continue;
+
+			conn_state = to_intel_digital_connector_state(_conn_state);
+			crtc = conn_state->base.crtc ? to_intel_crtc(conn_state->base.crtc) : NULL;
+			if (crtc)
+				crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+
+			if (connectors_enabled && crtc_state && crtc_state->hw.active) {
+				pipe = crtc->pipe;
+				tu = drm_dp_mst_payload_time_slots(payload);
+				drm_WARN_ON(&i915->drm, crtc_state->dp_m_n.tu != tu);
+			} else {
+				pipe = INVALID_PIPE;
+				tu = 0;
+			}
+
+			sw_vc = drm_dp_mst_payload_vchannel(mst_state, payload);
+			if (sw_vc < 0) {
+				drm_WARN_ON(&i915->drm, pipe != INVALID_PIPE);
+				drm_WARN_ON(&i915->drm, tu != 0);
+			} else {
+				if (drm_WARN_ON(&i915->drm,
+						sw_vc >= ARRAY_SIZE(hw_state.mst_stream)))
+					continue;
+
+				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].pipe != pipe);
+				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].tu != tu);
+			}
 		}
 
 		if (!mst_needs_modeset)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index 74633390c280c..53367b6a1ba39 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -26,6 +26,6 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
 int intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
 						  struct intel_connector *connector,
 						  struct intel_crtc *crtc);
-void intel_dp_mst_verify_state(struct intel_atomic_state *state);
+void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled);
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 45f0d9789ef8e..caf541b562e54 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -245,5 +245,5 @@ void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
 	verify_encoder_state(dev_priv, state);
 	verify_connector_state(state, NULL);
 	intel_shared_dpll_verify_disabled(dev_priv);
-	intel_dp_mst_verify_state(state);
+	intel_dp_mst_verify_state(state, false);
 }
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 596efc940ee70..6a406c9daa042 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6818,10 +6818,10 @@ enum skl_power_gate {
 #define  DP_TP_STATUS_IDLE_DONE			(1 << 25)
 #define  DP_TP_STATUS_ACT_SENT			(1 << 24)
 #define  DP_TP_STATUS_MODE_STATUS_MST		(1 << 23)
+#define  DP_TP_STATUS_NUM_STREAMS_ENABLED	(7 << 16)
 #define  DP_TP_STATUS_AUTOTRAIN_DONE		(1 << 12)
-#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC2	(3 << 8)
-#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC1	(3 << 4)
-#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC0	(3 << 0)
+#define  DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc)	((vc) * 4)
+#define  DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)	(3 << DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc))
 
 /* DDI Buffer Control */
 #define _DDI_BUF_CTL_A				0x64000
-- 
2.37.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (16 preceding siblings ...)
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders Imre Deak
@ 2023-01-31 15:27 ` Patchwork
  2023-01-31 15:59 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
  2023-01-31 20:42 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  19 siblings, 0 replies; 70+ messages in thread
From: Patchwork @ 2023-01-31 15:27 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
URL   : https://patchwork.freedesktop.org/series/113527/
State : warning

== Summary ==

Error: dim checkpatch failed
dff29428fcc0 drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs
7472ebf37845 drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
ccd1b92b1d94 drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
e96169030cbe drm/i915/dp_mst: Fix payload removal during output disabling
741b71cc0b20 drm/display/dp_mst: Fix the payload VCPI check in drm_dp_mst_dump_topology()
38e31e9f11fe drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
69b8d995079a drm/i915: Factor out helpers for modesetting CRTCs and connectors
-:65: WARNING:LONG_LINE_COMMENT: line length of 105 exceeds 100 columns
#65: FILE: drivers/gpu/drm/i915/display/intel_atomic.c:638:
+ * intel_atomic_modeset_connector - add a connector to the atomic state, force modeset on its CRTC if any

total: 0 errors, 1 warnings, 0 checks, 365 lines checked
52a77ab96f52 drm/i915/dp_mst: Move getting the MST topology state earlier to connector check
9a8d477f349f drm/display/dp_mst: Add a helper to verify the MST payload state
-:158: WARNING:LONG_LINE_COMMENT: line length of 108 exceeds 100 columns
#158: FILE: drivers/gpu/drm/display/drm_dp_mst_topology.c:4982:
+ * drm_dp_mst_verify_payload_state - Verify the atomic state for payloads and the related sink payload table

total: 0 errors, 1 warnings, 0 checks, 196 lines checked
56897c31415e drm/i915/dp_mst: Verify the MST state of modesetted outputs
44abb28c2317 drm/display/dp_mst: Add helpers to query for payload allocation errors
f1d761b8bc7e drm/display/dp_mst: Add helpers to query payload allocation properties
da362ee0830a drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition
a8aa6c80169d drm/display/dp_mst: Factor out a helper to reset the payload table
a80bbf962d64 drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem
-:31: WARNING:LONG_LINE_COMMENT: line length of 105 exceeds 100 columns
#31: FILE: drivers/gpu/drm/display/drm_dp_helper.c:2247:
+	/* DELL P2715Q MST payload table must be reset after the two last payload slots get allocated. */

-:32: WARNING:LONG_LINE: line length of 126 exceeds 100 columns
#32: FILE: drivers/gpu/drm/display/drm_dp_helper.c:2248:
+	{ OUI(0x00, 0xe0, 0x4c), DEVICE_ID('D', 'p', '1', '.', '2', 0), true, BIT(DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA) },

total: 0 errors, 2 warnings, 0 checks, 22 lines checked
07c714f2b343 drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
91a26c6b6652 drm/i915/dp_mst: Verify the HW state of MST encoders
-:31: CHECK:SPACING: No space is necessary after a cast
#31: FILE: drivers/gpu/drm/i915/display/intel_ddi.c:672:
+		return (enum transcoder) pipe;

-:118: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#118: FILE: drivers/gpu/drm/i915/display/intel_ddi.c:3547:
+	drm_WARN_ON(&i915->drm, state->num_mst_streams == 0 ||
+				state->num_mst_streams > ARRAY_SIZE(state->mst_stream));

total: 0 errors, 0 warnings, 2 checks, 295 lines checked



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

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (17 preceding siblings ...)
  2023-01-31 15:27 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Patchwork
@ 2023-01-31 15:59 ` Patchwork
  2023-01-31 20:42 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  19 siblings, 0 replies; 70+ messages in thread
From: Patchwork @ 2023-01-31 15:59 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

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

== Series Details ==

Series: drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
URL   : https://patchwork.freedesktop.org/series/113527/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_12674 -> Patchwork_113527v1
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (27 -> 26)
------------------------------

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

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

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

### IGT changes ###

#### Issues hit ####

  * igt@fbdev@write:
    - fi-blb-e6850:       [PASS][1] -> [SKIP][2] ([fdo#109271]) +4 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/fi-blb-e6850/igt@fbdev@write.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-blb-e6850/igt@fbdev@write.html

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

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

  * igt@i915_selftest@live@execlists:
    - fi-bsw-n3050:       [PASS][5] -> [ABORT][6] ([i915#7911])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/fi-bsw-n3050/igt@i915_selftest@live@execlists.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-bsw-n3050/igt@i915_selftest@live@execlists.html
    - fi-kbl-soraka:      NOTRUN -> [INCOMPLETE][7] ([i915#7156])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-kbl-soraka/igt@i915_selftest@live@execlists.html

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-apl-guc:         [PASS][8] -> [DMESG-FAIL][9] ([i915#5334])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/fi-apl-guc/igt@i915_selftest@live@gt_heartbeat.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-apl-guc/igt@i915_selftest@live@gt_heartbeat.html

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

  * igt@kms_chamelium_frames@hdmi-crc-fast:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][11] ([fdo#109271]) +15 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-kbl-soraka/igt@kms_chamelium_frames@hdmi-crc-fast.html

  
#### Possible fixes ####

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions:
    - fi-bsw-n3050:       [FAIL][12] ([i915#6298]) -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/fi-bsw-n3050/igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/fi-bsw-n3050/igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions.html

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

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1886]: https://gitlab.freedesktop.org/drm/intel/issues/1886
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5334]: https://gitlab.freedesktop.org/drm/intel/issues/5334
  [i915#6298]: https://gitlab.freedesktop.org/drm/intel/issues/6298
  [i915#7156]: https://gitlab.freedesktop.org/drm/intel/issues/7156
  [i915#7699]: https://gitlab.freedesktop.org/drm/intel/issues/7699
  [i915#7911]: https://gitlab.freedesktop.org/drm/intel/issues/7911
  [i915#7981]: https://gitlab.freedesktop.org/drm/intel/issues/7981


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

  * Linux: CI_DRM_12674 -> Patchwork_113527v1

  CI-20190529: 20190529
  CI_DRM_12674: abcd161e6541aaf1e5c23e16019d02905c0e50fd @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_7143: c7b12dcc460fc2348e1fa7f4dcb791bb82e29e44 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_113527v1: abcd161e6541aaf1e5c23e16019d02905c0e50fd @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

98e5868f0bb7 drm/i915/dp_mst: Verify the HW state of MST encoders
0dab6f2988c0 drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
2e410267390f drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem
577a8e99d46b drm/display/dp_mst: Factor out a helper to reset the payload table
16de7503f040 drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition
c26bc2b0de20 drm/display/dp_mst: Add helpers to query payload allocation properties
a688dcdcd843 drm/display/dp_mst: Add helpers to query for payload allocation errors
8af23a142499 drm/i915/dp_mst: Verify the MST state of modesetted outputs
4fd19b257f37 drm/display/dp_mst: Add a helper to verify the MST payload state
590369e9490a drm/i915/dp_mst: Move getting the MST topology state earlier to connector check
ba6495e464c8 drm/i915: Factor out helpers for modesetting CRTCs and connectors
02ccfd9bb6c6 drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
f521b1f6ecbc drm/display/dp_mst: Fix the payload VCPI check in drm_dp_mst_dump_topology()
68a51d80a5af drm/i915/dp_mst: Fix payload removal during output disabling
657019fab279 drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state()
ec6d47d72b4c drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
453d8bee9691 drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs

== Logs ==

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

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

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

* [Intel-gfx] ✓ Fi.CI.IGT: success for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
  2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
                   ` (18 preceding siblings ...)
  2023-01-31 15:59 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2023-01-31 20:42 ` Patchwork
  19 siblings, 0 replies; 70+ messages in thread
From: Patchwork @ 2023-01-31 20:42 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

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

== Series Details ==

Series: drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling
URL   : https://patchwork.freedesktop.org/series/113527/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_12674_full -> Patchwork_113527v1_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (11 -> 11)
------------------------------

  No changes in participating hosts

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gen9_exec_parse@allowed-single:
    - shard-glk:          [PASS][1] -> [ABORT][2] ([i915#5566])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-glk6/igt@gen9_exec_parse@allowed-single.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-glk2/igt@gen9_exec_parse@allowed-single.html

  
#### Possible fixes ####

  * igt@drm_read@short-buffer-block:
    - {shard-tglu}:       [SKIP][3] ([i915#7651]) -> [PASS][4] +6 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@drm_read@short-buffer-block.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@drm_read@short-buffer-block.html

  * igt@fbdev@info:
    - {shard-rkl}:        [SKIP][5] ([i915#2582]) -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@fbdev@info.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@fbdev@info.html

  * igt@fbdev@write:
    - {shard-tglu}:       [SKIP][7] ([i915#2582]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@fbdev@write.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@fbdev@write.html

  * igt@gem_ctx_persistence@hang:
    - {shard-rkl}:        [SKIP][9] ([i915#6252]) -> [PASS][10]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-5/igt@gem_ctx_persistence@hang.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-2/igt@gem_ctx_persistence@hang.html

  * igt@gem_exec_fair@basic-none-rrul@rcs0:
    - {shard-rkl}:        [FAIL][11] ([i915#2842]) -> [PASS][12]
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@gem_exec_fair@basic-none-rrul@rcs0.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-5/igt@gem_exec_fair@basic-none-rrul@rcs0.html

  * igt@gem_exec_fair@basic-pace-share@rcs0:
    - shard-glk:          [FAIL][13] ([i915#2842]) -> [PASS][14]
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-glk7/igt@gem_exec_fair@basic-pace-share@rcs0.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-glk8/igt@gem_exec_fair@basic-pace-share@rcs0.html

  * igt@gem_exec_reloc@basic-gtt-read-noreloc:
    - {shard-rkl}:        [SKIP][15] ([i915#3281]) -> [PASS][16] +3 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-6/igt@gem_exec_reloc@basic-gtt-read-noreloc.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-5/igt@gem_exec_reloc@basic-gtt-read-noreloc.html

  * igt@gem_readwrite@read-bad-handle:
    - {shard-rkl}:        [SKIP][17] ([i915#3282]) -> [PASS][18] +3 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@gem_readwrite@read-bad-handle.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-5/igt@gem_readwrite@read-bad-handle.html

  * igt@gem_spin_batch@resubmit@rcs0:
    - {shard-rkl}:        [ABORT][19] -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@gem_spin_batch@resubmit@rcs0.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-1/igt@gem_spin_batch@resubmit@rcs0.html

  * igt@gem_spin_batch@resubmit@vecs0:
    - {shard-rkl}:        [DMESG-WARN][21] -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@gem_spin_batch@resubmit@vecs0.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-1/igt@gem_spin_batch@resubmit@vecs0.html

  * igt@gen9_exec_parse@shadow-peek:
    - {shard-rkl}:        [SKIP][23] ([i915#2527]) -> [PASS][24] +2 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@gen9_exec_parse@shadow-peek.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-5/igt@gen9_exec_parse@shadow-peek.html

  * igt@i915_hangman@gt-engine-error@bcs0:
    - {shard-rkl}:        [SKIP][25] ([i915#6258]) -> [PASS][26]
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-5/igt@i915_hangman@gt-engine-error@bcs0.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-1/igt@i915_hangman@gt-engine-error@bcs0.html

  * igt@i915_pm_dc@dc9-dpms:
    - {shard-tglu}:       [SKIP][27] ([i915#4281]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-3/igt@i915_pm_dc@dc9-dpms.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-4/igt@i915_pm_dc@dc9-dpms.html

  * igt@i915_pm_lpsp@kms-lpsp@kms-lpsp-hdmi-a:
    - {shard-tglu}:       [FAIL][29] ([i915#3825]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-4/igt@i915_pm_lpsp@kms-lpsp@kms-lpsp-hdmi-a.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-1/igt@i915_pm_lpsp@kms-lpsp@kms-lpsp-hdmi-a.html

  * igt@i915_pm_rpm@fences-dpms:
    - {shard-rkl}:        [SKIP][31] ([i915#1849]) -> [PASS][32] +1 similar issue
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@i915_pm_rpm@fences-dpms.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@i915_pm_rpm@fences-dpms.html

  * igt@i915_pm_rpm@modeset-lpsp-stress:
    - {shard-tglu}:       [SKIP][33] ([i915#1397]) -> [PASS][34]
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@i915_pm_rpm@modeset-lpsp-stress.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@i915_pm_rpm@modeset-lpsp-stress.html

  * igt@i915_pm_rpm@modeset-lpsp-stress-no-wait:
    - {shard-rkl}:        [SKIP][35] ([i915#1397]) -> [PASS][36]
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@i915_pm_rpm@modeset-lpsp-stress-no-wait.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@i915_pm_rpm@modeset-lpsp-stress-no-wait.html
    - {shard-dg1}:        [SKIP][37] ([i915#1397]) -> [PASS][38]
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-dg1-12/igt@i915_pm_rpm@modeset-lpsp-stress-no-wait.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-dg1-14/igt@i915_pm_rpm@modeset-lpsp-stress-no-wait.html

  * igt@kms_big_fb@x-tiled-32bpp-rotate-0:
    - shard-glk:          [FAIL][39] ([i915#5138]) -> [PASS][40]
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-glk7/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-glk2/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2:
    - shard-glk:          [FAIL][41] ([i915#2122]) -> [PASS][42]
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-glk9/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-glk2/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@b-hdmi-a2:
    - shard-glk:          [FAIL][43] ([i915#79]) -> [PASS][44]
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-glk7/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-hdmi-a2.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-glk2/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-hdmi-a2.html

  * igt@kms_frontbuffer_tracking@fbc-1p-rte:
    - {shard-tglu}:       [SKIP][45] ([i915#1849]) -> [PASS][46] +1 similar issue
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@kms_frontbuffer_tracking@fbc-1p-rte.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@kms_frontbuffer_tracking@fbc-1p-rte.html

  * igt@kms_frontbuffer_tracking@fbc-tiling-linear:
    - {shard-rkl}:        [SKIP][47] ([i915#1849] / [i915#4098]) -> [PASS][48] +14 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-3/igt@kms_frontbuffer_tracking@fbc-tiling-linear.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_frontbuffer_tracking@fbc-tiling-linear.html

  * igt@kms_psr@sprite_mmap_gtt:
    - {shard-rkl}:        [SKIP][49] ([i915#1072]) -> [PASS][50] +2 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@kms_psr@sprite_mmap_gtt.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_psr@sprite_mmap_gtt.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - {shard-rkl}:        [SKIP][51] ([i915#5461]) -> [PASS][52]
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_rotation_crc@primary-rotation-90:
    - {shard-rkl}:        [SKIP][53] ([i915#1845] / [i915#4098]) -> [PASS][54] +25 similar issues
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-3/igt@kms_rotation_crc@primary-rotation-90.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_rotation_crc@primary-rotation-90.html

  * igt@kms_universal_plane@disable-primary-vs-flip-pipe-b:
    - {shard-rkl}:        [SKIP][55] ([i915#1845] / [i915#4070] / [i915#4098]) -> [PASS][56]
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@kms_universal_plane@disable-primary-vs-flip-pipe-b.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_universal_plane@disable-primary-vs-flip-pipe-b.html

  * igt@kms_universal_plane@universal-plane-pageflip-windowed-pipe-a:
    - {shard-rkl}:        [SKIP][57] ([i915#4098]) -> [PASS][58]
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-3/igt@kms_universal_plane@universal-plane-pageflip-windowed-pipe-a.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-6/igt@kms_universal_plane@universal-plane-pageflip-windowed-pipe-a.html

  * igt@kms_universal_plane@universal-plane-pipe-c-sanity:
    - {shard-tglu}:       [SKIP][59] ([fdo#109274]) -> [PASS][60] +1 similar issue
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@kms_universal_plane@universal-plane-pipe-c-sanity.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@kms_universal_plane@universal-plane-pipe-c-sanity.html

  * igt@kms_vblank@pipe-d-wait-forked-busy:
    - {shard-tglu}:       [SKIP][61] ([i915#1845] / [i915#7651]) -> [PASS][62] +2 similar issues
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-tglu-6/igt@kms_vblank@pipe-d-wait-forked-busy.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-tglu-2/igt@kms_vblank@pipe-d-wait-forked-busy.html

  * igt@perf_pmu@idle@rcs0:
    - {shard-rkl}:        [FAIL][63] ([i915#4349]) -> [PASS][64]
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-1/igt@perf_pmu@idle@rcs0.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-3/igt@perf_pmu@idle@rcs0.html

  * igt@prime_vgem@coherency-gtt:
    - {shard-rkl}:        [SKIP][65] ([fdo#109295] / [fdo#111656] / [i915#3708]) -> [PASS][66]
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12674/shard-rkl-4/igt@prime_vgem@coherency-gtt.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_113527v1/shard-rkl-5/igt@prime_vgem@coherency-gtt.html

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

  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109283]: https://bugs.freedesktop.org/show_bug.cgi?id=109283
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109295]: https://bugs.freedesktop.org/show_bug.cgi?id=109295
  [fdo#109312]: https://bugs.freedesktop.org/show_bug.cgi?id=109312
  [fdo#109313]: https://bugs.freedesktop.org/show_bug.cgi?id=109313
  [fdo#109314]: https://bugs.freedesktop.org/show_bug.cgi?id=109314
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [fdo#109506]: https://bugs.freedesktop.org/show_bug.cgi?id=109506
  [fdo#109642]: https://bugs.freedesktop.org/show_bug.cgi?id=109642
  [fdo#110189]: https://bugs.freedesktop.org/show_bug.cgi?id=110189
  [fdo#110723]: https://bugs.freedesktop.org/show_bug.cgi?id=110723
  [fdo#111068]: https://bugs.freedesktop.org/show_bug.cgi?id=111068
  [fdo#111614]: https://bugs.freedesktop.org/show_bug.cgi?id=111614
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111644]: https://bugs.freedesktop.org/show_bug.cgi?id=111644
  [fdo#111656]: https://bugs.freedesktop.org/show_bug.cgi?id=111656
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [fdo#112054]: https://bugs.freedesktop.org/show_bug.cgi?id=112054
  [fdo#112283]: https://bugs.freedesktop.org/show_bug.cgi?id=112283
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1257]: https://gitlab.freedesktop.org/drm/intel/issues/1257
  [i915#132]: https://gitlab.freedesktop.org/drm/intel/issues/132
  [i915#1397]: https://gitlab.freedesktop.org/drm/intel/issues/1397
  [i915#1825]: https://gitlab.freedesktop.org/drm/intel/issues/1825
  [i915#1839]: https://gitlab.freedesktop.org/drm/intel/issues/1839
  [i915#1845]: https://gitlab.freedesktop.org/drm/intel/issues/1845
  [i915#1849]: https://gitlab.freedesktop.org/drm/intel/issues/1849
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2527]: https://gitlab.freedesktop.org/drm/intel/issues/2527
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#2587]: https://gitlab.freedesktop.org/drm/intel/issues/2587
  [i915#2658]: https://gitlab.freedesktop.org/drm/intel/issues/2658
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2681]: https://gitlab.freedesktop.org/drm/intel/issues/2681
  [i915#2705]: https://gitlab.freedesktop.org/drm/intel/issues/2705
  [i915#280]: https://gitlab.freedesktop.org/drm/intel/issues/280
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#3281]: https://gitlab.freedesktop.org/drm/intel/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3297]: https://gitlab.freedesktop.org/drm/intel/issues/3297
  [i915#3299]: https://gitlab.freedesktop.org/drm/intel/issues/3299
  [i915#3323]: https://gitlab.freedesktop.org/drm/intel/issues/3323
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3458]: https://gitlab.freedesktop.org/drm/intel/issues/3458
  [i915#3469]: https://gitlab.freedesktop.org/drm/intel/issues/3469
  [i915#3536]: https://gitlab.freedesktop.org/drm/intel/issues/3536
  [i915#3539]: https://gitlab.freedesktop.org/drm/intel/issues/3539
  [i915#3546]: https://gitlab.freedesktop.org/drm/intel/issues/3546
  [i915#3547]: https://gitlab.freedesktop.org/drm/intel/issues/3547
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3558]: https://gitlab.freedesktop.org/drm/intel/issues/3558
  [i915#3591]: https://gitlab.freedesktop.org/drm/intel/issues/3591
  [i915#3637]: https://gitlab.freedesktop.org/drm/intel/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/intel/issues/3638
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3734]: https://gitlab.freedesktop.org/drm/intel/issues/3734
  [i915#3742]: https://gitlab.freedesktop.org/drm/intel/issues/3742
  [i915#3804]: https://gitlab.freedesktop.org/drm/intel/issues/3804
  [i915#3825]: https://gitlab.freedesktop.org/drm/intel/issues/3825
  [i915#3826]: https://gitlab.freedesktop.org/drm/intel/issues/3826
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#3938]: https://gitlab.freedesktop.org/drm/intel/issues/3938
  [i915#3955]: https://gitlab.freedesktop.org/drm/intel/issues/3955
  [i915#4036]: https://gitlab.freedesktop.org/drm/intel/issues/4036
  [i915#404]: https://gitlab.freedesktop.org/drm/intel/issues/404
  [i915#4070]: https://gitlab.freedesktop.org/drm/intel/issues/4070
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4078]: https://gitlab.freedesktop.org/drm/intel/issues/4078
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4098]: https://gitlab.freedesktop.org/drm/intel/issues/4098
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4270]: https://gitlab.freedesktop.org/drm/intel/issues/4270
  [i915#4281]: https://gitlab.freedesktop.org/drm/intel/issues/4281
  [i915#4349]: https://gitlab.freedesktop.org/drm/intel/issues/4349
  [i915#4387]: https://gitlab.freedesktop.org/drm/intel/issues/4387
  [i915#4538]: https://gitlab.freedesktop.org/drm/intel/issues/4538
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4767]: https://gitlab.freedesktop.org/drm/intel/issues/4767
  [i915#4778]: https://gitlab.freedesktop.org/drm/intel/issues/4778
  [i915#4812]: https://gitlab.freedesktop.org/drm/intel/issues/4812
  [i915#4833]: https://gitlab.freedesktop.org/drm/intel/issues/4833
  [i915#4852]: https://gitlab.freedesktop.org/drm/intel/issues/4852
  [i915#4860]: https://gitlab.freedesktop.org/drm/intel/issues/4860
  [i915#4874]: https://gitlab.freedesktop.org/drm/intel/issues/4874
  [i915#4880]: https://gitlab.freedesktop.org/drm/intel/issues/4880
  [i915#4885]: https://gitlab.freedesktop.org/drm/intel/issues/4885
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5138]: https://gitlab.freedesktop.org/drm/intel/issues/5138
  [i915#5176]: https://gitlab.freedesktop.org/drm/intel/issues/5176
  [i915#5235]: https://gitlab.freedesktop.org/drm/intel/issues/5235
  [i915#5286]: https://gitlab.freedesktop.org/drm/intel/issues/5286
  [i915#5288]: https://gitlab.freedesktop.org/drm/intel/issues/5288
  [i915#5289]: https://gitlab.freedesktop.org/drm/intel/issues/5289
  [i915#5325]: https://gitlab.freedesktop.org/drm/intel/issues/5325
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#5439]: https://gitlab.freedesktop.org/drm/intel/issues/5439
  [i915#5461]: https://gitlab.freedesktop.org/drm/intel/issues/5461
  [i915#5563]: https://gitlab.freedesktop.org/drm/intel/issues/5563
  [i915#5566]: https://gitlab.freedesktop.org/drm/intel/issues/5566
  [i915#5608]: https://gitlab.freedesktop.org/drm/intel/issues/5608
  [i915#5784]: https://gitlab.freedesktop.org/drm/intel/issues/5784
  [i915#6095]: https://gitlab.freedesktop.org/drm/intel/issues/6095
  [i915#6247]: https://gitlab.freedesktop.org/drm/intel/issues/6247
  [i915#6248]: https://gitlab.freedesktop.org/drm/intel/issues/6248
  [i915#6252]: https://gitlab.freedesktop.org/drm/intel/issues/6252
  [i915#6258]: https://gitlab.freedesktop.org/drm/intel/issues/6258
  [i915#6301]: https://gitlab.freedesktop.org/drm/intel/issues/6301
  [i915#6334]: https://gitlab.freedesktop.org/drm/intel/issues/6334
  [i915#6335]: https://gitlab.freedesktop.org/drm/intel/issues/6335
  [i915#6412]: https://gitlab.freedesktop.org/drm/intel/issues/6412
  [i915#6433]: https://gitlab.freedesktop.org/drm/intel/issues/6433
  [i915#6497]: https://gitlab.freedesktop.org/drm/intel/issues/6497
  [i915#6524]: https://gitlab.freedesktop.org/drm/intel/issues/6524
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#6590]: https://gitlab.freedesktop.org/drm/intel/issues/6590
  [i915#6768]: https://gitlab.freedesktop.org/drm/intel/issues/6768
  [i915#6944]: https://gitlab.freedesktop.org/drm/intel/issues/6944
  [i915#6946]: https://gitlab.freedesktop.org/drm/intel/issues/6946
  [i915#6953]: https://gitlab.freedesktop.org/drm/intel/issues/6953
  [i915#7037]: https://gitlab.freedesktop.org/drm/intel/issues/7037
  [i915#7116]: https://gitlab.freedesktop.org/drm/intel/issues/7116
  [i915#7118]: https://gitlab.freedesktop.org/drm/intel/issues/7118
  [i915#7128]: https://gitlab.freedesktop.org/drm/intel/issues/7128
  [i915#7294]: https://gitlab.freedesktop.org/drm/intel/issues/7294
  [i915#7561]: https://gitlab.freedesktop.org/drm/intel/issues/7561
  [i915#7651]: https://gitlab.freedesktop.org/drm/intel/issues/7651
  [i915#7697]: https://gitlab.freedesktop.org/drm/intel/issues/7697
  [i915#7707]: https://gitlab.freedesktop.org/drm/intel/issues/7707
  [i915#7711]: https://gitlab.freedesktop.org/drm/intel/issues/7711
  [i915#7742]: https://gitlab.freedesktop.org/drm/intel/issues/7742
  [i915#7828]: https://gitlab.freedesktop.org/drm/intel/issues/7828
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79
  [i915#7949]: https://gitlab.freedesktop.org/drm/intel/issues/7949


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

  * Linux: CI_DRM_12674 -> Patchwork_113527v1

  CI-20190529: 20190529
  CI_DRM_12674: abcd161e6541aaf1e5c23e16019d02905c0e50fd @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_7143: c7b12dcc460fc2348e1fa7f4dcb791bb82e29e44 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_113527v1: abcd161e6541aaf1e5c23e16019d02905c0e50fd @ git://anongit.freedesktop.org/gfx-ci/linux

== Logs ==

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

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

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

* Re: [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q " Imre Deak
@ 2023-01-31 22:47   ` Lyude Paul
  2023-02-01 14:41     ` Imre Deak
  2023-01-31 23:43   ` Lyude Paul
  1 sibling, 1 reply; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 22:47 UTC (permalink / raw)
  To: Imre Deak, intel-gfx

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> The DELL P2715Q monitor's MST hub has a payload allocation problem,

LMAO hello yet again, Dell P2715Q. It's been a while.

> where the VCPI used to reserve the last two time slots (at position
> 0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
> later payload configurations.
> 
> The problem results at least in streams reusing older VCPIs to stay
> blank on the screen and the payload table containing bogus VCPIs
> (repeating the one earlier used to reserve the 0x3e, 0x3f slots) after
> the last reservered slot.

WOW. you know I've been trying for ages to figure out what is up with this
exact monitor and I think I just gave up because it's the only monitor I've
ever seen do this.

(Also yes, I do have two of this exact monitor. I think we even have this
model mentioned in our testcases. I looked up a google photo of it just to
confirm. I think ours is the P2715Qb, but it looks identical and the problem
you're describing sounds identical as well).

This patch looks fine to me, we could probably also put this in the MST
helpers as well if you can think of a way to do that and I can handle testing
it on nouveau/amdgpu, but this is basically the only monitor I've ever seen do
this - so I don't think it's a big deal either way.

either way:

Reviewed-by: Lyude Paul <lyude@redhat.com>

> 
> To work around the problem detect this monitor and the condition for the
> problem (when the last two slots get allocated in a commit), force a
> full modeset of the MST topology in the subsequent commit and reset the
> payload table during the latter commit after all payloads have been
> freed.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Lyude Paul <lyude@redhat.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_atomic.c   | 13 +++--
>  drivers/gpu/drm/i915/display/intel_atomic.h   |  3 +-
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c       |  5 +-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 48 +++++++++++++++++--
>  5 files changed, 61 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
> index 0f1c5b9c9a826..04e5f0e0fffa6 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> @@ -616,7 +616,8 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
>  }
>  
>  static int modeset_pipe(struct intel_atomic_state *state,
> -			struct intel_crtc *crtc, const char *reason)
> +			struct intel_crtc *crtc, const char *reason,
> +			bool allow_fastset)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct intel_crtc_state *crtc_state;
> @@ -629,6 +630,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
>  		return PTR_ERR(crtc_state);
>  
>  	crtc_state->uapi.mode_changed = true;
> +	if (!allow_fastset)
> +		crtc_state->uapi.connectors_changed = true;
>  	crtc_state->update_pipe = false;
>  
>  	return intel_atomic_add_affected_planes(state, crtc);
> @@ -639,6 +642,7 @@ static int modeset_pipe(struct intel_atomic_state *state,
>   * @state: atomic state
>   * @connector: connector to add the state for
>   * @reason: the reason why the connector needs to be added
> + * @allow_fastset: allow a fastset
>   *
>   * Add the @connector to the atomic state with its CRTC state and force a modeset
>   * on the CRTC if any.
> @@ -648,7 +652,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
>   * Returns 0 in case of success, a negative error code on failure.
>   */
>  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> -				   struct intel_connector *connector, const char *reason)
> +				   struct intel_connector *connector, const char *reason,
> +				   bool allow_fastset)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct drm_connector_state *conn_state;
> @@ -671,7 +676,7 @@ int intel_atomic_modeset_connector(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> -	return modeset_pipe(state, crtc, reason);
> +	return modeset_pipe(state, crtc, reason, allow_fastset);
>  }
>  
>  /**
> @@ -700,7 +705,7 @@ int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> -	return modeset_pipe(state, crtc, reason);
> +	return modeset_pipe(state, crtc, reason, true);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
> index 84295d388e3cb..7778aea8a09fe 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.h
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.h
> @@ -59,7 +59,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>  int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
>  			      struct intel_crtc *crtc, const char *reason);
>  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> -				   struct intel_connector *connector, const char *reason);
> +				   struct intel_connector *connector, const char *reason,
> +				   bool allow_fastset);
>  int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
>  				   const char *reason);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 9ccae7a460200..06d51d2b5e0d6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1656,6 +1656,7 @@ struct intel_dp {
>  	bool has_audio;
>  	bool reset_link_params;
>  	bool use_max_params;
> +	bool mst_reset_payload_table;
>  	u8 dpcd[DP_RECEIVER_CAP_SIZE];
>  	u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
>  	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index d6b0ef38f6563..c157bcd976103 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4689,6 +4689,8 @@ intel_dp_detect(struct drm_connector *connector,
>  		memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
>  		memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
>  
> +		intel_dp->mst_reset_payload_table = false;
> +
>  		if (intel_dp->is_mst) {
>  			drm_dbg_kms(&dev_priv->drm,
>  				    "MST device may have disappeared %d vs %d\n",
> @@ -4924,7 +4926,8 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
>  			continue;
>  
>  		ret = intel_atomic_modeset_connector(state, connector,
> -						     "connector tile group");
> +						     "connector tile group",
> +						     true);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 08222fc6c5ecd..a9bb339e41987 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -422,9 +422,10 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct drm_connector_list_iter connector_list_iter;
>  	struct intel_connector *connector_iter;
> +	bool reset_payload_table = connector->mst_port->mst_reset_payload_table;
>  	int ret = 0;
>  
> -	if (DISPLAY_VER(dev_priv) < 12)
> +	if (DISPLAY_VER(dev_priv) < 12 && !reset_payload_table)
>  		return  0;
>  
>  	if (!intel_connector_needs_modeset(state, &connector->base))
> @@ -437,7 +438,8 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
>  			continue;
>  
>  		ret = intel_atomic_modeset_connector(state, connector_iter,
> -						     "MST master transcoder");
> +						     "MST master transcoder",
> +						     !reset_payload_table);
>  		if (ret)
>  			break;
>  	}
> @@ -531,6 +533,41 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
>  }
>  
> +static void detect_payload_allocation_bug(const struct drm_dp_mst_topology_state *mst_state,
> +					  const struct intel_connector *connector,
> +					  struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	if (!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA))
> +		return;
> +
> +	if (drm_dp_mst_allocated_time_slots(mst_state) < DP_PAYLOAD_TABLE_SIZE - 2)
> +		return;
> +
> +	drm_dbg(&i915->drm,
> +		"[CONNECTOR:%d:%s] Payload table allocation bug detected\n",
> +		connector->base.base.id, connector->base.name);
> +
> +	intel_dp->mst_reset_payload_table = true;
> +}
> +
> +static void payload_allocation_bug_wa(const struct intel_connector *connector,
> +				      struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	if (!intel_dp->mst_reset_payload_table)
> +		return;
> +
> +	drm_dbg(&i915->drm,
> +		"[CONNECTOR:%d:%s] Resetting payload table due to allocation bug\n",
> +		connector->base.base.id, connector->base.name);
> +
> +	drm_dp_mst_reset_payload_table(&intel_dp->mst_mgr);
> +	intel_dp->mst_reset_payload_table = false;
> +}
> +
>  static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
>  				      struct intel_encoder *encoder,
>  				      const struct intel_crtc_state *old_crtc_state,
> @@ -594,10 +631,13 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
>  
>  
>  	intel_mst->connector = NULL;
> -	if (last_mst_stream)
> +	if (last_mst_stream) {
>  		dig_port->base.post_disable(state, &dig_port->base,
>  						  old_crtc_state, NULL);
>  
> +		payload_allocation_bug_wa(connector, intel_dp);
> +	}
> +
>  	drm_dbg_kms(&dev_priv->drm, "active links %d\n",
>  		    intel_dp->active_mst_links);
>  }
> @@ -662,6 +702,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
>  		drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
>  			connector->base.name, ret);
>  
> +	detect_payload_allocation_bug(mst_state, connector, intel_dp);
> +
>  	/*
>  	 * Before Gen 12 this is not done as part of
>  	 * dig_port->base.pre_enable() and should be done here. For

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
  (?)
@ 2023-01-31 23:13     ` Lyude Paul
  -1 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 23:13 UTC (permalink / raw)
  To: Imre Deak, intel-gfx
  Cc: Karol Herbst, dri-devel, stable, Ben Skeggs, Wayne Lin, Alex Deucher

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> Atm, drm_dp_remove_payload() uses the same payload state to both get the
> vc_start_slot required for the payload removal DPCD message and to
> deduct time_slots from vc_start_slot of all payloads after the one being
> removed.
> 
> The above isn't always correct, as vc_start_slot must be the up-to-date
> version contained in the new payload state, but time_slots must be the
> one used when the payload was previously added, contained in the old
> payload state. The new payload's time_slots can change vs. the old one
> if the current atomic commit changes the corresponding mode.
> 
> This patch let's drivers pass the old and new payload states to
> drm_dp_remove_payload(), but keeps these the same for now in all drivers
> not to change the behavior. A follow-up i915 patch will pass in that
> driver the correct old and new states to the function.

Oh wow, this was definitely a mistake on my part, thanks for catching this!
TBH, I think this behavior is correct so (now that I actually have a setup
capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
like to change it on other drivers as well I can test it fully. Or feel free
to leave it to me, shouldn't be too difficult I think :).

For 0-2:

Reviewed-by: Lyude Paul <lyude@redhat.com>

> 
> Cc: Lyude Paul <lyude@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Karol Herbst <kherbst@redhat.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Wayne Lin <Wayne.Lin@amd.com>
> Cc: stable@vger.kernel.org # 6.1
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
>  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
>  5 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> index a50319fc42b11..180d3893b68da 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
>  	if (enable)
>  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
>  	else
> -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
>  
>  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
>  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 847c10aa2098c..1990ff5dc7ddd 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   * drm_dp_remove_payload() - Remove an MST payload
>   * @mgr: Manager to use.
>   * @mst_state: The MST atomic state
> - * @payload: The payload to write
> + * @old_payload: The payload with its old state
> + * @new_payload: The payload to write
>   *
>   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
>   * the starting time slots of all other payloads which would have been shifted towards the start of
> @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   */
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload)
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload)
>  {
>  	struct drm_dp_mst_atomic_payload *pos;
>  	bool send_remove = false;
>  
>  	/* We failed to make the payload, so nothing to do */
> -	if (payload->vc_start_slot == -1)
> +	if (new_payload->vc_start_slot == -1)
>  		return;
>  
>  	mutex_lock(&mgr->lock);
> -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
>  	mutex_unlock(&mgr->lock);
>  
>  	if (send_remove)
> -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
>  	else
>  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> -			    payload->vcpi);
> +			    new_payload->vcpi);
>  
>  	list_for_each_entry(pos, &mst_state->payloads, next) {
> -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> -			pos->vc_start_slot -= payload->time_slots;
> +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> +			pos->vc_start_slot -= old_payload->time_slots;
>  	}
> -	payload->vc_start_slot = -1;
> +	new_payload->vc_start_slot = -1;
>  
>  	mgr->payload_count--;
> -	mgr->next_start_slot -= payload->time_slots;
> +	mgr->next_start_slot -= old_payload->time_slots;
>  
> -	if (payload->delete)
> -		drm_dp_mst_put_port_malloc(payload->port);
> +	if (new_payload->delete)
> +		drm_dp_mst_put_port_malloc(new_payload->port);
>  }
>  EXPORT_SYMBOL(drm_dp_remove_payload);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  		to_intel_connector(old_conn_state->connector);
>  	struct drm_dp_mst_topology_state *mst_state =
>  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> +	struct drm_dp_mst_atomic_payload *payload =
> +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
>  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
>  
>  	drm_dbg_kms(&i915->drm, "active links %d\n",
> @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  	intel_hdcp_disable(intel_mst->connector);
>  
>  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> +			      payload, payload);
>  
>  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
>  }
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index edcb2529b4025..ed9d374147b8d 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
>  
>  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
>  	if (msto->disabled) {
> -		drm_dp_remove_payload(mgr, mst_state, payload);
> +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
>  
>  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
>  	} else {
> diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> index 41fd8352ab656..f5eb9aa152b14 100644
> --- a/include/drm/display/drm_dp_mst_helper.h
> +++ b/include/drm/display/drm_dp_mst_helper.h
> @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
>  			     struct drm_dp_mst_atomic_payload *payload);
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload);
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload);
>  
>  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-01-31 23:13     ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 23:13 UTC (permalink / raw)
  To: Imre Deak, intel-gfx
  Cc: Karol Herbst, dri-devel, stable, Ben Skeggs, Wayne Lin,
	Alex Deucher, Harry Wentland

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> Atm, drm_dp_remove_payload() uses the same payload state to both get the
> vc_start_slot required for the payload removal DPCD message and to
> deduct time_slots from vc_start_slot of all payloads after the one being
> removed.
> 
> The above isn't always correct, as vc_start_slot must be the up-to-date
> version contained in the new payload state, but time_slots must be the
> one used when the payload was previously added, contained in the old
> payload state. The new payload's time_slots can change vs. the old one
> if the current atomic commit changes the corresponding mode.
> 
> This patch let's drivers pass the old and new payload states to
> drm_dp_remove_payload(), but keeps these the same for now in all drivers
> not to change the behavior. A follow-up i915 patch will pass in that
> driver the correct old and new states to the function.

Oh wow, this was definitely a mistake on my part, thanks for catching this!
TBH, I think this behavior is correct so (now that I actually have a setup
capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
like to change it on other drivers as well I can test it fully. Or feel free
to leave it to me, shouldn't be too difficult I think :).

For 0-2:

Reviewed-by: Lyude Paul <lyude@redhat.com>

> 
> Cc: Lyude Paul <lyude@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Karol Herbst <kherbst@redhat.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Wayne Lin <Wayne.Lin@amd.com>
> Cc: stable@vger.kernel.org # 6.1
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
>  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
>  5 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> index a50319fc42b11..180d3893b68da 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
>  	if (enable)
>  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
>  	else
> -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
>  
>  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
>  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 847c10aa2098c..1990ff5dc7ddd 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   * drm_dp_remove_payload() - Remove an MST payload
>   * @mgr: Manager to use.
>   * @mst_state: The MST atomic state
> - * @payload: The payload to write
> + * @old_payload: The payload with its old state
> + * @new_payload: The payload to write
>   *
>   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
>   * the starting time slots of all other payloads which would have been shifted towards the start of
> @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   */
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload)
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload)
>  {
>  	struct drm_dp_mst_atomic_payload *pos;
>  	bool send_remove = false;
>  
>  	/* We failed to make the payload, so nothing to do */
> -	if (payload->vc_start_slot == -1)
> +	if (new_payload->vc_start_slot == -1)
>  		return;
>  
>  	mutex_lock(&mgr->lock);
> -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
>  	mutex_unlock(&mgr->lock);
>  
>  	if (send_remove)
> -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
>  	else
>  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> -			    payload->vcpi);
> +			    new_payload->vcpi);
>  
>  	list_for_each_entry(pos, &mst_state->payloads, next) {
> -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> -			pos->vc_start_slot -= payload->time_slots;
> +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> +			pos->vc_start_slot -= old_payload->time_slots;
>  	}
> -	payload->vc_start_slot = -1;
> +	new_payload->vc_start_slot = -1;
>  
>  	mgr->payload_count--;
> -	mgr->next_start_slot -= payload->time_slots;
> +	mgr->next_start_slot -= old_payload->time_slots;
>  
> -	if (payload->delete)
> -		drm_dp_mst_put_port_malloc(payload->port);
> +	if (new_payload->delete)
> +		drm_dp_mst_put_port_malloc(new_payload->port);
>  }
>  EXPORT_SYMBOL(drm_dp_remove_payload);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  		to_intel_connector(old_conn_state->connector);
>  	struct drm_dp_mst_topology_state *mst_state =
>  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> +	struct drm_dp_mst_atomic_payload *payload =
> +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
>  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
>  
>  	drm_dbg_kms(&i915->drm, "active links %d\n",
> @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  	intel_hdcp_disable(intel_mst->connector);
>  
>  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> +			      payload, payload);
>  
>  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
>  }
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index edcb2529b4025..ed9d374147b8d 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
>  
>  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
>  	if (msto->disabled) {
> -		drm_dp_remove_payload(mgr, mst_state, payload);
> +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
>  
>  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
>  	} else {
> diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> index 41fd8352ab656..f5eb9aa152b14 100644
> --- a/include/drm/display/drm_dp_mst_helper.h
> +++ b/include/drm/display/drm_dp_mst_helper.h
> @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
>  			     struct drm_dp_mst_atomic_payload *payload);
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload);
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload);
>  
>  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-01-31 23:13     ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 23:13 UTC (permalink / raw)
  To: Imre Deak, intel-gfx
  Cc: Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> Atm, drm_dp_remove_payload() uses the same payload state to both get the
> vc_start_slot required for the payload removal DPCD message and to
> deduct time_slots from vc_start_slot of all payloads after the one being
> removed.
> 
> The above isn't always correct, as vc_start_slot must be the up-to-date
> version contained in the new payload state, but time_slots must be the
> one used when the payload was previously added, contained in the old
> payload state. The new payload's time_slots can change vs. the old one
> if the current atomic commit changes the corresponding mode.
> 
> This patch let's drivers pass the old and new payload states to
> drm_dp_remove_payload(), but keeps these the same for now in all drivers
> not to change the behavior. A follow-up i915 patch will pass in that
> driver the correct old and new states to the function.

Oh wow, this was definitely a mistake on my part, thanks for catching this!
TBH, I think this behavior is correct so (now that I actually have a setup
capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
like to change it on other drivers as well I can test it fully. Or feel free
to leave it to me, shouldn't be too difficult I think :).

For 0-2:

Reviewed-by: Lyude Paul <lyude@redhat.com>

> 
> Cc: Lyude Paul <lyude@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Karol Herbst <kherbst@redhat.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Wayne Lin <Wayne.Lin@amd.com>
> Cc: stable@vger.kernel.org # 6.1
> Cc: dri-devel@lists.freedesktop.org
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
>  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
>  5 files changed, 21 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> index a50319fc42b11..180d3893b68da 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
>  	if (enable)
>  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
>  	else
> -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
>  
>  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
>  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 847c10aa2098c..1990ff5dc7ddd 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   * drm_dp_remove_payload() - Remove an MST payload
>   * @mgr: Manager to use.
>   * @mst_state: The MST atomic state
> - * @payload: The payload to write
> + * @old_payload: The payload with its old state
> + * @new_payload: The payload to write
>   *
>   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
>   * the starting time slots of all other payloads which would have been shifted towards the start of
> @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
>   */
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload)
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload)
>  {
>  	struct drm_dp_mst_atomic_payload *pos;
>  	bool send_remove = false;
>  
>  	/* We failed to make the payload, so nothing to do */
> -	if (payload->vc_start_slot == -1)
> +	if (new_payload->vc_start_slot == -1)
>  		return;
>  
>  	mutex_lock(&mgr->lock);
> -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
>  	mutex_unlock(&mgr->lock);
>  
>  	if (send_remove)
> -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
>  	else
>  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> -			    payload->vcpi);
> +			    new_payload->vcpi);
>  
>  	list_for_each_entry(pos, &mst_state->payloads, next) {
> -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> -			pos->vc_start_slot -= payload->time_slots;
> +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> +			pos->vc_start_slot -= old_payload->time_slots;
>  	}
> -	payload->vc_start_slot = -1;
> +	new_payload->vc_start_slot = -1;
>  
>  	mgr->payload_count--;
> -	mgr->next_start_slot -= payload->time_slots;
> +	mgr->next_start_slot -= old_payload->time_slots;
>  
> -	if (payload->delete)
> -		drm_dp_mst_put_port_malloc(payload->port);
> +	if (new_payload->delete)
> +		drm_dp_mst_put_port_malloc(new_payload->port);
>  }
>  EXPORT_SYMBOL(drm_dp_remove_payload);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  		to_intel_connector(old_conn_state->connector);
>  	struct drm_dp_mst_topology_state *mst_state =
>  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> +	struct drm_dp_mst_atomic_payload *payload =
> +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
>  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
>  
>  	drm_dbg_kms(&i915->drm, "active links %d\n",
> @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  	intel_hdcp_disable(intel_mst->connector);
>  
>  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> +			      payload, payload);
>  
>  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
>  }
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index edcb2529b4025..ed9d374147b8d 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
>  
>  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
>  	if (msto->disabled) {
> -		drm_dp_remove_payload(mgr, mst_state, payload);
> +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
>  
>  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
>  	} else {
> diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> index 41fd8352ab656..f5eb9aa152b14 100644
> --- a/include/drm/display/drm_dp_mst_helper.h
> +++ b/include/drm/display/drm_dp_mst_helper.h
> @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
>  			     struct drm_dp_mst_atomic_payload *payload);
>  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
>  			   struct drm_dp_mst_topology_state *mst_state,
> -			   struct drm_dp_mst_atomic_payload *payload);
> +			   const struct drm_dp_mst_atomic_payload *old_payload,
> +			   struct drm_dp_mst_atomic_payload *new_payload);
>  
>  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration " Imre Deak
@ 2023-01-31 23:14   ` Lyude Paul
  2023-02-03 12:22   ` Ville Syrjälä
  1 sibling, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 23:14 UTC (permalink / raw)
  To: Imre Deak, intel-gfx

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> Simplify the loop iterating the payloads by using a helper to get a
> payload by its VCPI (keeping the list VCPI sorted). This also removes
> the assumption that the biggest VCPI matches the number of payloads
> (even though this holds now).
> 
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Lyude Paul <lyude@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 45 ++++++++++++-------
>  1 file changed, 28 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 8787df19f428b..0c04b96ae614c 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -4737,6 +4737,18 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
>  	kfree(mst_edid);
>  }
>  
> +static struct drm_dp_mst_atomic_payload *
> +get_payload_by_vcpi(struct drm_dp_mst_topology_state *mst_state, int vcpi)
> +{
> +	struct drm_dp_mst_atomic_payload *payload;
> +
> +	list_for_each_entry(payload, &mst_state->payloads, next)
> +		if (payload->vcpi == vcpi)
> +			return payload;
> +
> +	return NULL;
> +}
> +
>  /**
>   * drm_dp_mst_dump_topology(): dump topology to seq file.
>   * @m: seq_file to dump output to
> @@ -4748,7 +4760,6 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
>  			      struct drm_dp_mst_topology_mgr *mgr)
>  {
>  	struct drm_dp_mst_topology_state *state;
> -	struct drm_dp_mst_atomic_payload *payload;
>  	int i, ret;
>  
>  	mutex_lock(&mgr->lock);
> @@ -4768,24 +4779,24 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
>  		   state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
>  
>  	seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc |     sink name     |\n");
> -	for (i = 0; i < mgr->max_payloads; i++) {
> -		list_for_each_entry(payload, &state->payloads, next) {
> -			char name[14];
> +	for_each_set_bit(i, (unsigned long *)&state->payload_mask,
> +			 BITS_PER_TYPE(state->payload_mask)) {

Huh, TIL we have a for_each_set_bit() macro. neat.

> +		const struct drm_dp_mst_atomic_payload *payload = get_payload_by_vcpi(state, i + 1);
> +		char name[14];
>  
> -			if (payload->vcpi != i + 1 || payload->delete)
> -				continue;
> +		if (payload->delete)
> +			continue;
>  
> -			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> -			seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> -				   i,
> -				   payload->port->port_num,
> -				   payload->vcpi,
> -				   payload->vc_start_slot,
> -				   payload->vc_start_slot + payload->time_slots - 1,
> -				   payload->pbn,
> -				   payload->dsc_enabled ? "Y" : "N",
> -				   (*name != 0) ? name : "Unknown");
> -		}
> +		fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> +		seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> +			   i,
> +			   payload->port->port_num,
> +			   payload->vcpi,
> +			   payload->vc_start_slot,
> +			   payload->vc_start_slot + payload->time_slots - 1,
> +			   payload->pbn,
> +			   payload->dsc_enabled ? "Y" : "N",
> +			   (*name != 0) ? name : "Unknown");
>  	}
>  
>  	seq_printf(m, "\n*** DPCD Info ***\n");

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q " Imre Deak
  2023-01-31 22:47   ` Lyude Paul
@ 2023-01-31 23:43   ` Lyude Paul
  1 sibling, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-01-31 23:43 UTC (permalink / raw)
  To: Imre Deak, intel-gfx

I mentioned this once already but: really, I am genuinely impressed at this! I
never expected to see this monitor ever work. Also, thank you a ton for adding
the payload table verification stuff here. For the whole series:

Reviewed-by: Lyude Paul <lyude@redhat.com>

On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> The DELL P2715Q monitor's MST hub has a payload allocation problem,
> where the VCPI used to reserve the last two time slots (at position
> 0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
> later payload configurations.
> 
> The problem results at least in streams reusing older VCPIs to stay
> blank on the screen and the payload table containing bogus VCPIs
> (repeating the one earlier used to reserve the 0x3e, 0x3f slots) after
> the last reservered slot.
> 
> To work around the problem detect this monitor and the condition for the
> problem (when the last two slots get allocated in a commit), force a
> full modeset of the MST topology in the subsequent commit and reset the
> payload table during the latter commit after all payloads have been
> freed.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Lyude Paul <lyude@redhat.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_atomic.c   | 13 +++--
>  drivers/gpu/drm/i915/display/intel_atomic.h   |  3 +-
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c       |  5 +-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 48 +++++++++++++++++--
>  5 files changed, 61 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
> index 0f1c5b9c9a826..04e5f0e0fffa6 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> @@ -616,7 +616,8 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
>  }
>  
>  static int modeset_pipe(struct intel_atomic_state *state,
> -			struct intel_crtc *crtc, const char *reason)
> +			struct intel_crtc *crtc, const char *reason,
> +			bool allow_fastset)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct intel_crtc_state *crtc_state;
> @@ -629,6 +630,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
>  		return PTR_ERR(crtc_state);
>  
>  	crtc_state->uapi.mode_changed = true;
> +	if (!allow_fastset)
> +		crtc_state->uapi.connectors_changed = true;
>  	crtc_state->update_pipe = false;
>  
>  	return intel_atomic_add_affected_planes(state, crtc);
> @@ -639,6 +642,7 @@ static int modeset_pipe(struct intel_atomic_state *state,
>   * @state: atomic state
>   * @connector: connector to add the state for
>   * @reason: the reason why the connector needs to be added
> + * @allow_fastset: allow a fastset
>   *
>   * Add the @connector to the atomic state with its CRTC state and force a modeset
>   * on the CRTC if any.
> @@ -648,7 +652,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
>   * Returns 0 in case of success, a negative error code on failure.
>   */
>  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> -				   struct intel_connector *connector, const char *reason)
> +				   struct intel_connector *connector, const char *reason,
> +				   bool allow_fastset)
>  {
>  	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct drm_connector_state *conn_state;
> @@ -671,7 +676,7 @@ int intel_atomic_modeset_connector(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> -	return modeset_pipe(state, crtc, reason);
> +	return modeset_pipe(state, crtc, reason, allow_fastset);
>  }
>  
>  /**
> @@ -700,7 +705,7 @@ int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
>  	if (ret)
>  		return ret;
>  
> -	return modeset_pipe(state, crtc, reason);
> +	return modeset_pipe(state, crtc, reason, true);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
> index 84295d388e3cb..7778aea8a09fe 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.h
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.h
> @@ -59,7 +59,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>  int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
>  			      struct intel_crtc *crtc, const char *reason);
>  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> -				   struct intel_connector *connector, const char *reason);
> +				   struct intel_connector *connector, const char *reason,
> +				   bool allow_fastset);
>  int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
>  				   const char *reason);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 9ccae7a460200..06d51d2b5e0d6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1656,6 +1656,7 @@ struct intel_dp {
>  	bool has_audio;
>  	bool reset_link_params;
>  	bool use_max_params;
> +	bool mst_reset_payload_table;
>  	u8 dpcd[DP_RECEIVER_CAP_SIZE];
>  	u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
>  	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index d6b0ef38f6563..c157bcd976103 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4689,6 +4689,8 @@ intel_dp_detect(struct drm_connector *connector,
>  		memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
>  		memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
>  
> +		intel_dp->mst_reset_payload_table = false;
> +
>  		if (intel_dp->is_mst) {
>  			drm_dbg_kms(&dev_priv->drm,
>  				    "MST device may have disappeared %d vs %d\n",
> @@ -4924,7 +4926,8 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
>  			continue;
>  
>  		ret = intel_atomic_modeset_connector(state, connector,
> -						     "connector tile group");
> +						     "connector tile group",
> +						     true);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 08222fc6c5ecd..a9bb339e41987 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -422,9 +422,10 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
>  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
>  	struct drm_connector_list_iter connector_list_iter;
>  	struct intel_connector *connector_iter;
> +	bool reset_payload_table = connector->mst_port->mst_reset_payload_table;
>  	int ret = 0;
>  
> -	if (DISPLAY_VER(dev_priv) < 12)
> +	if (DISPLAY_VER(dev_priv) < 12 && !reset_payload_table)
>  		return  0;
>  
>  	if (!intel_connector_needs_modeset(state, &connector->base))
> @@ -437,7 +438,8 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
>  			continue;
>  
>  		ret = intel_atomic_modeset_connector(state, connector_iter,
> -						     "MST master transcoder");
> +						     "MST master transcoder",
> +						     !reset_payload_table);
>  		if (ret)
>  			break;
>  	}
> @@ -531,6 +533,41 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
>  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
>  }
>  
> +static void detect_payload_allocation_bug(const struct drm_dp_mst_topology_state *mst_state,
> +					  const struct intel_connector *connector,
> +					  struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	if (!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA))
> +		return;
> +
> +	if (drm_dp_mst_allocated_time_slots(mst_state) < DP_PAYLOAD_TABLE_SIZE - 2)
> +		return;
> +
> +	drm_dbg(&i915->drm,
> +		"[CONNECTOR:%d:%s] Payload table allocation bug detected\n",
> +		connector->base.base.id, connector->base.name);
> +
> +	intel_dp->mst_reset_payload_table = true;
> +}
> +
> +static void payload_allocation_bug_wa(const struct intel_connector *connector,
> +				      struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	if (!intel_dp->mst_reset_payload_table)
> +		return;
> +
> +	drm_dbg(&i915->drm,
> +		"[CONNECTOR:%d:%s] Resetting payload table due to allocation bug\n",
> +		connector->base.base.id, connector->base.name);
> +
> +	drm_dp_mst_reset_payload_table(&intel_dp->mst_mgr);
> +	intel_dp->mst_reset_payload_table = false;
> +}
> +
>  static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
>  				      struct intel_encoder *encoder,
>  				      const struct intel_crtc_state *old_crtc_state,
> @@ -594,10 +631,13 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
>  
>  
>  	intel_mst->connector = NULL;
> -	if (last_mst_stream)
> +	if (last_mst_stream) {
>  		dig_port->base.post_disable(state, &dig_port->base,
>  						  old_crtc_state, NULL);
>  
> +		payload_allocation_bug_wa(connector, intel_dp);
> +	}
> +
>  	drm_dbg_kms(&dev_priv->drm, "active links %d\n",
>  		    intel_dp->active_mst_links);
>  }
> @@ -662,6 +702,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
>  		drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
>  			connector->base.name, ret);
>  
> +	detect_payload_allocation_bug(mst_state, connector, intel_dp);
> +
>  	/*
>  	 * Before Gen 12 this is not done as part of
>  	 * dig_port->base.pre_enable() and should be done here. For

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders Imre Deak
@ 2023-02-01  9:41   ` Jani Nikula
  2023-02-01 14:03     ` Imre Deak
  0 siblings, 1 reply; 70+ messages in thread
From: Jani Nikula @ 2023-02-01  9:41 UTC (permalink / raw)
  To: Imre Deak, intel-gfx

On Tue, 31 Jan 2023, Imre Deak <imre.deak@intel.com> wrote:
> Read out and verify an MST encoder's HW state after any of the
> MST connectors driven by the encoder is modeset.
>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c      | 91 +++++++++++++++++--
>  drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
>  .../drm/i915/display/intel_display_types.h    | 18 ++++
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 68 +++++++++++++-
>  drivers/gpu/drm/i915/display/intel_dp_mst.h   |  2 +-
>  .../drm/i915/display/intel_modeset_verify.c   |  2 +-
>  drivers/gpu/drm/i915/i915_reg.h               |  6 +-
>  7 files changed, 173 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 254559abedfba..6acda4d357af3 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -661,13 +661,23 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
>  	return ret;
>  }
>  
> +static enum transcoder get_transcoder_for_pipe(const struct intel_encoder *encoder,
> +					       enum pipe pipe)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	if (HAS_TRANSCODER(i915, TRANSCODER_EDP) && encoder->port == PORT_A)
> +		return TRANSCODER_EDP;
> +	else
> +		return (enum transcoder) pipe;
> +}
> +
>  bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
>  {
>  	struct drm_device *dev = intel_connector->base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
>  	int type = intel_connector->base.connector_type;
> -	enum port port = encoder->port;
>  	enum transcoder cpu_transcoder;
>  	intel_wakeref_t wakeref;
>  	enum pipe pipe = 0;
> @@ -684,10 +694,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
>  		goto out;
>  	}
>  
> -	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
> -		cpu_transcoder = TRANSCODER_EDP;
> -	else
> -		cpu_transcoder = (enum transcoder) pipe;
> +	cpu_transcoder = get_transcoder_for_pipe(encoder, pipe);
>  
>  	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
>  
> @@ -2155,17 +2162,29 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
>  		return DP_TP_CTL(encoder->port);
>  }
>  
> -i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
> -			    const struct intel_crtc_state *crtc_state)
> +static i915_reg_t __dp_tp_status_reg(struct intel_encoder *encoder,
> +				     enum transcoder transcoder)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  
>  	if (DISPLAY_VER(dev_priv) >= 12)
> -		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
> +		return TGL_DP_TP_STATUS(transcoder);
>  	else
>  		return DP_TP_STATUS(encoder->port);
>  }
>  
> +i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
> +			    const struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum transcoder transcoder = INVALID_TRANSCODER;
> +
> +	if (DISPLAY_VER(dev_priv) >= 12)
> +		transcoder = tgl_dp_tp_transcoder(crtc_state);
> +
> +	return __dp_tp_status_reg(encoder, transcoder);
> +}
> +
>  static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
>  							  const struct intel_crtc_state *crtc_state,
>  							  bool enable)
> @@ -3500,6 +3519,61 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
>  	intel_audio_codec_get_config(encoder, pipe_config);
>  }
>  
> +static bool intel_ddi_get_hw_mst_state(struct intel_encoder *encoder,
> +				       struct intel_encoder_mst_state *state)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	enum transcoder transcoder;
> +	u8 vc_pipe_mask = 0;
> +	u8 pipe_mask;
> +	bool is_mst;
> +	u32 dp_status;
> +	bool in_mst_mode;
> +	int vc;
> +
> +	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
> +	if (!is_mst || !pipe_mask)
> +		return false;
> +
> +	transcoder = get_transcoder_for_pipe(encoder, ffs(pipe_mask) - 1);
> +	dp_status = intel_de_read(i915, __dp_tp_status_reg(encoder, transcoder));
> +
> +	in_mst_mode = REG_FIELD_GET(DP_TP_STATUS_MODE_STATUS_MST, dp_status);
> +	if (drm_WARN_ON(&i915->drm, !in_mst_mode))
> +		return false;
> +
> +	state->num_mst_streams = REG_FIELD_GET(DP_TP_STATUS_NUM_STREAMS_ENABLED, dp_status);
> +	drm_WARN_ON(&i915->drm, state->num_mst_streams == 0 ||
> +				state->num_mst_streams > ARRAY_SIZE(state->mst_stream));
> +
> +	for (vc = 0; vc < ARRAY_SIZE(state->mst_stream); vc++) {
> +		struct intel_crtc *crtc;
> +		struct intel_link_m_n m_n;
> +
> +		if (vc >= state->num_mst_streams) {
> +			state->mst_stream[vc].pipe = INVALID_PIPE;
> +			state->mst_stream[vc].tu = 0;
> +			continue;
> +		}
> +
> +		state->mst_stream[vc].pipe = (dp_status & DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)) >>
> +					     DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc);
> +
> +		drm_WARN_ON(&i915->drm, vc_pipe_mask & BIT(state->mst_stream[vc].pipe));
> +		vc_pipe_mask |= BIT(state->mst_stream[vc].pipe);
> +
> +		transcoder = get_transcoder_for_pipe(encoder, state->mst_stream[vc].pipe);
> +		crtc = intel_crtc_for_pipe(i915, state->mst_stream[vc].pipe);
> +
> +		intel_cpu_transcoder_get_m1_n1(crtc, transcoder, &m_n);
> +		state->mst_stream[vc].tu = m_n.tu;
> +	}
> +
> +	drm_WARN_ON(&i915->drm, vc_pipe_mask != pipe_mask);
> +
> +	return true;
> +}
> +
>  void intel_ddi_get_clock(struct intel_encoder *encoder,
>  			 struct intel_crtc_state *crtc_state,
>  			 struct intel_shared_dpll *pll)
> @@ -4384,6 +4458,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
>  	encoder->post_disable = intel_ddi_post_disable;
>  	encoder->update_pipe = intel_ddi_update_pipe;
>  	encoder->get_hw_state = intel_ddi_get_hw_state;
> +	encoder->get_hw_mst_state = intel_ddi_get_hw_mst_state;
>  	encoder->sync_state = intel_ddi_sync_state;
>  	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
>  	encoder->suspend = intel_ddi_encoder_suspend;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 7976658771ab3..8b2b7a30b1b01 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -7541,7 +7541,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
>  
>  	if (state->modeset) {
>  		intel_verify_planes(state);
> -		intel_dp_mst_verify_state(state);
> +		intel_dp_mst_verify_state(state, true);
>  	}
>  
>  	intel_sagv_post_plane_update(state);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 06d51d2b5e0d6..066a1b956b0ba 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -151,6 +151,18 @@ enum intel_hotplug_state {
>  	INTEL_HOTPLUG_RETRY,
>  };
>  
> +struct intel_encoder_mst_state {
> +	/**
> +	 *  TODO: move the encoder state from intel_crtc_state to here, and
> +	 *  make this a generic encoder state.
> +	 */
> +	u8 num_mst_streams;
> +	struct {
> +		u8 pipe;
> +		u8 tu;
> +	} mst_stream[I915_MAX_PIPES];
> +};
> +
>  struct intel_encoder {
>  	struct drm_encoder base;
>  
> @@ -213,6 +225,12 @@ struct intel_encoder {
>  	 * be set correctly before calling this function. */
>  	void (*get_config)(struct intel_encoder *,
>  			   struct intel_crtc_state *pipe_config);
> +	/**
> +	 * Determine if the encoder is active in MST mode and if so
> +	 * read out the corresponding HW state.
> +	 */
> +	bool (*get_hw_mst_state)(struct intel_encoder *encoder,
> +				 struct intel_encoder_mst_state *mst_state);
>  
>  	/*
>  	 * Optional hook called during init/resume to sync any state
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index a9bb339e41987..5bc18450b09c6 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -1322,23 +1322,55 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
>  /**
>   * intel_dp_mst_verify_state - Verify the MST state for all connectors in the atomic state
>   * @state: atomic state
> + * @connectors_enabled: %true if called after the modeset's enabling
> + *                      %false if called after the disabling sequence
>   *
>   * Verify the MST SW and sink state for all modesetted MST connectors in @state.
>   */
> -void intel_dp_mst_verify_state(struct intel_atomic_state *state)
> +void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled)
>  {
> +	struct drm_i915_private *i915 = to_i915(state->base.dev);
>  	struct drm_dp_mst_topology_state *mst_state;
>  	struct drm_dp_mst_topology_mgr *mgr;
>  	int i;
>  
>  	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
>  		struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
> +		struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +		struct intel_encoder_mst_state hw_state;
>  		struct drm_connector *_connector;
>  		struct drm_connector_state *_conn_state;
>  		bool mst_needs_modeset = false;
> +		bool has_alloc_errors = drm_dp_mst_has_payload_alloc_errors(mst_state);
> +		int i;

I'm sure it works, but it's probably not a hot idea to shadow the
variable for the inner loop.

BR,
Jani.

> +
> +		if (!encoder->get_hw_mst_state(encoder, &hw_state)) {
> +			drm_WARN_ON(&i915->drm, drm_dp_mst_payload_count(mst_state));
> +			continue;
> +		}
> +
> +		/*
> +		 * The streams for which the payload allocation has failed got
> +		 * still enabled in the HW. In that case check only for an
> +		 * upper bound of mgr->payload_count here and skip the MST payload
> +		 * vs. HW state check later, since those will not match.
> +		 */
> +		if (!has_alloc_errors)
> +			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams !=
> +						drm_dp_mst_payload_count(mst_state));
> +		else
> +			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams <
> +						drm_dp_mst_payload_count(mst_state));
>  
>  		for_each_new_connector_in_state(&state->base, _connector, _conn_state, i) {
>  			struct intel_connector *connector = to_intel_connector(_connector);
> +			struct intel_digital_connector_state *conn_state;
> +			struct intel_crtc *crtc;
> +			struct intel_crtc_state *crtc_state = NULL;
> +			struct drm_dp_mst_atomic_payload *payload;
> +			enum pipe pipe;
> +			int sw_vc;
> +			int tu;
>  
>  			if (!connector->mst_port ||
>  			    !intel_connector_needs_modeset(state, &connector->base))
> @@ -1346,7 +1378,39 @@ void intel_dp_mst_verify_state(struct intel_atomic_state *state)
>  
>  			mst_needs_modeset = true;
>  
> -			break;
> +			if (has_alloc_errors)
> +				break;
> +
> +			payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
> +			if (drm_WARN_ON(&i915->drm, !payload))
> +				continue;
> +
> +			conn_state = to_intel_digital_connector_state(_conn_state);
> +			crtc = conn_state->base.crtc ? to_intel_crtc(conn_state->base.crtc) : NULL;
> +			if (crtc)
> +				crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> +
> +			if (connectors_enabled && crtc_state && crtc_state->hw.active) {
> +				pipe = crtc->pipe;
> +				tu = drm_dp_mst_payload_time_slots(payload);
> +				drm_WARN_ON(&i915->drm, crtc_state->dp_m_n.tu != tu);
> +			} else {
> +				pipe = INVALID_PIPE;
> +				tu = 0;
> +			}
> +
> +			sw_vc = drm_dp_mst_payload_vchannel(mst_state, payload);
> +			if (sw_vc < 0) {
> +				drm_WARN_ON(&i915->drm, pipe != INVALID_PIPE);
> +				drm_WARN_ON(&i915->drm, tu != 0);
> +			} else {
> +				if (drm_WARN_ON(&i915->drm,
> +						sw_vc >= ARRAY_SIZE(hw_state.mst_stream)))
> +					continue;
> +
> +				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].pipe != pipe);
> +				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].tu != tu);
> +			}
>  		}
>  
>  		if (!mst_needs_modeset)
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> index 74633390c280c..53367b6a1ba39 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> @@ -26,6 +26,6 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
>  int intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
>  						  struct intel_connector *connector,
>  						  struct intel_crtc *crtc);
> -void intel_dp_mst_verify_state(struct intel_atomic_state *state);
> +void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled);
>  
>  #endif /* __INTEL_DP_MST_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> index 45f0d9789ef8e..caf541b562e54 100644
> --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> @@ -245,5 +245,5 @@ void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
>  	verify_encoder_state(dev_priv, state);
>  	verify_connector_state(state, NULL);
>  	intel_shared_dpll_verify_disabled(dev_priv);
> -	intel_dp_mst_verify_state(state);
> +	intel_dp_mst_verify_state(state, false);
>  }
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 596efc940ee70..6a406c9daa042 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6818,10 +6818,10 @@ enum skl_power_gate {
>  #define  DP_TP_STATUS_IDLE_DONE			(1 << 25)
>  #define  DP_TP_STATUS_ACT_SENT			(1 << 24)
>  #define  DP_TP_STATUS_MODE_STATUS_MST		(1 << 23)
> +#define  DP_TP_STATUS_NUM_STREAMS_ENABLED	(7 << 16)
>  #define  DP_TP_STATUS_AUTOTRAIN_DONE		(1 << 12)
> -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC2	(3 << 8)
> -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC1	(3 << 4)
> -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC0	(3 << 0)
> +#define  DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc)	((vc) * 4)
> +#define  DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)	(3 << DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc))
>  
>  /* DDI Buffer Control */
>  #define _DDI_BUF_CTL_A				0x64000

-- 
Jani Nikula, Intel Open Source Graphics Center

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

* Re: [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders
  2023-02-01  9:41   ` Jani Nikula
@ 2023-02-01 14:03     ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-01 14:03 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Wed, Feb 01, 2023 at 11:41:47AM +0200, Jani Nikula wrote:
> On Tue, 31 Jan 2023, Imre Deak <imre.deak@intel.com> wrote:
> > Read out and verify an MST encoder's HW state after any of the
> > MST connectors driven by the encoder is modeset.
> >
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_ddi.c      | 91 +++++++++++++++++--
> >  drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
> >  .../drm/i915/display/intel_display_types.h    | 18 ++++
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 68 +++++++++++++-
> >  drivers/gpu/drm/i915/display/intel_dp_mst.h   |  2 +-
> >  .../drm/i915/display/intel_modeset_verify.c   |  2 +-
> >  drivers/gpu/drm/i915/i915_reg.h               |  6 +-
> >  7 files changed, 173 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > index 254559abedfba..6acda4d357af3 100644
> > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > @@ -661,13 +661,23 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
> >  	return ret;
> >  }
> >  
> > +static enum transcoder get_transcoder_for_pipe(const struct intel_encoder *encoder,
> > +					       enum pipe pipe)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +
> > +	if (HAS_TRANSCODER(i915, TRANSCODER_EDP) && encoder->port == PORT_A)
> > +		return TRANSCODER_EDP;
> > +	else
> > +		return (enum transcoder) pipe;
> > +}
> > +
> >  bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
> >  {
> >  	struct drm_device *dev = intel_connector->base.dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
> >  	int type = intel_connector->base.connector_type;
> > -	enum port port = encoder->port;
> >  	enum transcoder cpu_transcoder;
> >  	intel_wakeref_t wakeref;
> >  	enum pipe pipe = 0;
> > @@ -684,10 +694,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
> >  		goto out;
> >  	}
> >  
> > -	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
> > -		cpu_transcoder = TRANSCODER_EDP;
> > -	else
> > -		cpu_transcoder = (enum transcoder) pipe;
> > +	cpu_transcoder = get_transcoder_for_pipe(encoder, pipe);
> >  
> >  	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
> >  
> > @@ -2155,17 +2162,29 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
> >  		return DP_TP_CTL(encoder->port);
> >  }
> >  
> > -i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
> > -			    const struct intel_crtc_state *crtc_state)
> > +static i915_reg_t __dp_tp_status_reg(struct intel_encoder *encoder,
> > +				     enum transcoder transcoder)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> >  
> >  	if (DISPLAY_VER(dev_priv) >= 12)
> > -		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
> > +		return TGL_DP_TP_STATUS(transcoder);
> >  	else
> >  		return DP_TP_STATUS(encoder->port);
> >  }
> >  
> > +i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
> > +			    const struct intel_crtc_state *crtc_state)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > +	enum transcoder transcoder = INVALID_TRANSCODER;
> > +
> > +	if (DISPLAY_VER(dev_priv) >= 12)
> > +		transcoder = tgl_dp_tp_transcoder(crtc_state);
> > +
> > +	return __dp_tp_status_reg(encoder, transcoder);
> > +}
> > +
> >  static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
> >  							  const struct intel_crtc_state *crtc_state,
> >  							  bool enable)
> > @@ -3500,6 +3519,61 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
> >  	intel_audio_codec_get_config(encoder, pipe_config);
> >  }
> >  
> > +static bool intel_ddi_get_hw_mst_state(struct intel_encoder *encoder,
> > +				       struct intel_encoder_mst_state *state)
> > +{
> > +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> > +	enum transcoder transcoder;
> > +	u8 vc_pipe_mask = 0;
> > +	u8 pipe_mask;
> > +	bool is_mst;
> > +	u32 dp_status;
> > +	bool in_mst_mode;
> > +	int vc;
> > +
> > +	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
> > +	if (!is_mst || !pipe_mask)
> > +		return false;
> > +
> > +	transcoder = get_transcoder_for_pipe(encoder, ffs(pipe_mask) - 1);
> > +	dp_status = intel_de_read(i915, __dp_tp_status_reg(encoder, transcoder));
> > +
> > +	in_mst_mode = REG_FIELD_GET(DP_TP_STATUS_MODE_STATUS_MST, dp_status);
> > +	if (drm_WARN_ON(&i915->drm, !in_mst_mode))
> > +		return false;
> > +
> > +	state->num_mst_streams = REG_FIELD_GET(DP_TP_STATUS_NUM_STREAMS_ENABLED, dp_status);
> > +	drm_WARN_ON(&i915->drm, state->num_mst_streams == 0 ||
> > +				state->num_mst_streams > ARRAY_SIZE(state->mst_stream));
> > +
> > +	for (vc = 0; vc < ARRAY_SIZE(state->mst_stream); vc++) {
> > +		struct intel_crtc *crtc;
> > +		struct intel_link_m_n m_n;
> > +
> > +		if (vc >= state->num_mst_streams) {
> > +			state->mst_stream[vc].pipe = INVALID_PIPE;
> > +			state->mst_stream[vc].tu = 0;
> > +			continue;
> > +		}
> > +
> > +		state->mst_stream[vc].pipe = (dp_status & DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)) >>
> > +					     DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc);
> > +
> > +		drm_WARN_ON(&i915->drm, vc_pipe_mask & BIT(state->mst_stream[vc].pipe));
> > +		vc_pipe_mask |= BIT(state->mst_stream[vc].pipe);
> > +
> > +		transcoder = get_transcoder_for_pipe(encoder, state->mst_stream[vc].pipe);
> > +		crtc = intel_crtc_for_pipe(i915, state->mst_stream[vc].pipe);
> > +
> > +		intel_cpu_transcoder_get_m1_n1(crtc, transcoder, &m_n);
> > +		state->mst_stream[vc].tu = m_n.tu;
> > +	}
> > +
> > +	drm_WARN_ON(&i915->drm, vc_pipe_mask != pipe_mask);
> > +
> > +	return true;
> > +}
> > +
> >  void intel_ddi_get_clock(struct intel_encoder *encoder,
> >  			 struct intel_crtc_state *crtc_state,
> >  			 struct intel_shared_dpll *pll)
> > @@ -4384,6 +4458,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
> >  	encoder->post_disable = intel_ddi_post_disable;
> >  	encoder->update_pipe = intel_ddi_update_pipe;
> >  	encoder->get_hw_state = intel_ddi_get_hw_state;
> > +	encoder->get_hw_mst_state = intel_ddi_get_hw_mst_state;
> >  	encoder->sync_state = intel_ddi_sync_state;
> >  	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
> >  	encoder->suspend = intel_ddi_encoder_suspend;
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index 7976658771ab3..8b2b7a30b1b01 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -7541,7 +7541,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> >  
> >  	if (state->modeset) {
> >  		intel_verify_planes(state);
> > -		intel_dp_mst_verify_state(state);
> > +		intel_dp_mst_verify_state(state, true);
> >  	}
> >  
> >  	intel_sagv_post_plane_update(state);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 06d51d2b5e0d6..066a1b956b0ba 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -151,6 +151,18 @@ enum intel_hotplug_state {
> >  	INTEL_HOTPLUG_RETRY,
> >  };
> >  
> > +struct intel_encoder_mst_state {
> > +	/**
> > +	 *  TODO: move the encoder state from intel_crtc_state to here, and
> > +	 *  make this a generic encoder state.
> > +	 */
> > +	u8 num_mst_streams;
> > +	struct {
> > +		u8 pipe;
> > +		u8 tu;
> > +	} mst_stream[I915_MAX_PIPES];
> > +};
> > +
> >  struct intel_encoder {
> >  	struct drm_encoder base;
> >  
> > @@ -213,6 +225,12 @@ struct intel_encoder {
> >  	 * be set correctly before calling this function. */
> >  	void (*get_config)(struct intel_encoder *,
> >  			   struct intel_crtc_state *pipe_config);
> > +	/**
> > +	 * Determine if the encoder is active in MST mode and if so
> > +	 * read out the corresponding HW state.
> > +	 */
> > +	bool (*get_hw_mst_state)(struct intel_encoder *encoder,
> > +				 struct intel_encoder_mst_state *mst_state);
> >  
> >  	/*
> >  	 * Optional hook called during init/resume to sync any state
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index a9bb339e41987..5bc18450b09c6 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -1322,23 +1322,55 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
> >  /**
> >   * intel_dp_mst_verify_state - Verify the MST state for all connectors in the atomic state
> >   * @state: atomic state
> > + * @connectors_enabled: %true if called after the modeset's enabling
> > + *                      %false if called after the disabling sequence
> >   *
> >   * Verify the MST SW and sink state for all modesetted MST connectors in @state.
> >   */
> > -void intel_dp_mst_verify_state(struct intel_atomic_state *state)
> > +void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled)
> >  {
> > +	struct drm_i915_private *i915 = to_i915(state->base.dev);
> >  	struct drm_dp_mst_topology_state *mst_state;
> >  	struct drm_dp_mst_topology_mgr *mgr;
> >  	int i;
> >  
> >  	for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
> >  		struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
> > +		struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> > +		struct intel_encoder_mst_state hw_state;
> >  		struct drm_connector *_connector;
> >  		struct drm_connector_state *_conn_state;
> >  		bool mst_needs_modeset = false;
> > +		bool has_alloc_errors = drm_dp_mst_has_payload_alloc_errors(mst_state);
> > +		int i;
> 
> I'm sure it works, but it's probably not a hot idea to shadow the
> variable for the inner loop.

Thanks for catching it, will fix it. Looks like we can't enable -Wshadow
in i915 at least due to the same issue elsewhere.

> BR,
> Jani.
> 
> > +
> > +		if (!encoder->get_hw_mst_state(encoder, &hw_state)) {
> > +			drm_WARN_ON(&i915->drm, drm_dp_mst_payload_count(mst_state));
> > +			continue;
> > +		}
> > +
> > +		/*
> > +		 * The streams for which the payload allocation has failed got
> > +		 * still enabled in the HW. In that case check only for an
> > +		 * upper bound of mgr->payload_count here and skip the MST payload
> > +		 * vs. HW state check later, since those will not match.
> > +		 */
> > +		if (!has_alloc_errors)
> > +			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams !=
> > +						drm_dp_mst_payload_count(mst_state));
> > +		else
> > +			drm_WARN_ON(&i915->drm, hw_state.num_mst_streams <
> > +						drm_dp_mst_payload_count(mst_state));
> >  
> >  		for_each_new_connector_in_state(&state->base, _connector, _conn_state, i) {
> >  			struct intel_connector *connector = to_intel_connector(_connector);
> > +			struct intel_digital_connector_state *conn_state;
> > +			struct intel_crtc *crtc;
> > +			struct intel_crtc_state *crtc_state = NULL;
> > +			struct drm_dp_mst_atomic_payload *payload;
> > +			enum pipe pipe;
> > +			int sw_vc;
> > +			int tu;
> >  
> >  			if (!connector->mst_port ||
> >  			    !intel_connector_needs_modeset(state, &connector->base))
> > @@ -1346,7 +1378,39 @@ void intel_dp_mst_verify_state(struct intel_atomic_state *state)
> >  
> >  			mst_needs_modeset = true;
> >  
> > -			break;
> > +			if (has_alloc_errors)
> > +				break;
> > +
> > +			payload = drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > +			if (drm_WARN_ON(&i915->drm, !payload))
> > +				continue;
> > +
> > +			conn_state = to_intel_digital_connector_state(_conn_state);
> > +			crtc = conn_state->base.crtc ? to_intel_crtc(conn_state->base.crtc) : NULL;
> > +			if (crtc)
> > +				crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
> > +
> > +			if (connectors_enabled && crtc_state && crtc_state->hw.active) {
> > +				pipe = crtc->pipe;
> > +				tu = drm_dp_mst_payload_time_slots(payload);
> > +				drm_WARN_ON(&i915->drm, crtc_state->dp_m_n.tu != tu);
> > +			} else {
> > +				pipe = INVALID_PIPE;
> > +				tu = 0;
> > +			}
> > +
> > +			sw_vc = drm_dp_mst_payload_vchannel(mst_state, payload);
> > +			if (sw_vc < 0) {
> > +				drm_WARN_ON(&i915->drm, pipe != INVALID_PIPE);
> > +				drm_WARN_ON(&i915->drm, tu != 0);
> > +			} else {
> > +				if (drm_WARN_ON(&i915->drm,
> > +						sw_vc >= ARRAY_SIZE(hw_state.mst_stream)))
> > +					continue;
> > +
> > +				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].pipe != pipe);
> > +				drm_WARN_ON(&i915->drm, hw_state.mst_stream[sw_vc].tu != tu);
> > +			}
> >  		}
> >  
> >  		if (!mst_needs_modeset)
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> > index 74633390c280c..53367b6a1ba39 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
> > @@ -26,6 +26,6 @@ int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
> >  int intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
> >  						  struct intel_connector *connector,
> >  						  struct intel_crtc *crtc);
> > -void intel_dp_mst_verify_state(struct intel_atomic_state *state);
> > +void intel_dp_mst_verify_state(struct intel_atomic_state *state, bool connectors_enabled);
> >  
> >  #endif /* __INTEL_DP_MST_H__ */
> > diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> > index 45f0d9789ef8e..caf541b562e54 100644
> > --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> > +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
> > @@ -245,5 +245,5 @@ void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
> >  	verify_encoder_state(dev_priv, state);
> >  	verify_connector_state(state, NULL);
> >  	intel_shared_dpll_verify_disabled(dev_priv);
> > -	intel_dp_mst_verify_state(state);
> > +	intel_dp_mst_verify_state(state, false);
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 596efc940ee70..6a406c9daa042 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -6818,10 +6818,10 @@ enum skl_power_gate {
> >  #define  DP_TP_STATUS_IDLE_DONE			(1 << 25)
> >  #define  DP_TP_STATUS_ACT_SENT			(1 << 24)
> >  #define  DP_TP_STATUS_MODE_STATUS_MST		(1 << 23)
> > +#define  DP_TP_STATUS_NUM_STREAMS_ENABLED	(7 << 16)
> >  #define  DP_TP_STATUS_AUTOTRAIN_DONE		(1 << 12)
> > -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC2	(3 << 8)
> > -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC1	(3 << 4)
> > -#define  DP_TP_STATUS_PAYLOAD_MAPPING_VC0	(3 << 0)
> > +#define  DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc)	((vc) * 4)
> > +#define  DP_TP_STATUS_PAYLOAD_MAPPING_MASK(vc)	(3 << DP_TP_STATUS_PAYLOAD_MAPPING_SHIFT(vc))
> >  
> >  /* DDI Buffer Control */
> >  #define _DDI_BUF_CTL_A				0x64000
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

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

* Re: [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q payload allocation problem
  2023-01-31 22:47   ` Lyude Paul
@ 2023-02-01 14:41     ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-01 14:41 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx

On Tue, Jan 31, 2023 at 05:47:11PM -0500, Lyude Paul wrote:
> On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> > The DELL P2715Q monitor's MST hub has a payload allocation problem,
> 
> LMAO hello yet again, Dell P2715Q. It's been a while.
> 
> > where the VCPI used to reserve the last two time slots (at position
> > 0x3e, 0x3f) in the hub's payload table, this VCPI can't be reused for
> > later payload configurations.
> > 
> > The problem results at least in streams reusing older VCPIs to stay
> > blank on the screen and the payload table containing bogus VCPIs
> > (repeating the one earlier used to reserve the 0x3e, 0x3f slots) after
> > the last reservered slot.
> 
> WOW. you know I've been trying for ages to figure out what is up with this
> exact monitor and I think I just gave up because it's the only monitor I've
> ever seen do this.
> 
> (Also yes, I do have two of this exact monitor. I think we even have this
> model mentioned in our testcases. I looked up a google photo of it just to
> confirm. I think ours is the P2715Qb, but it looks identical and the problem
> you're describing sounds identical as well).
> 
> This patch looks fine to me, we could probably also put this in the MST
> helpers as well if you can think of a way to do that and I can handle testing
> it on nouveau/amdgpu, but this is basically the only monitor I've ever seen do
> this - so I don't think it's a big deal either way.

Ok, it would be good if you could repro the same issue on your side.

I think the driver specific part is to detect the issue and force a full
modeset in the next commit. The MST core could then clear the payload
table internally, maybe based on some flag the driver passed.

Also the detection and forcing a full modeset as in this patch is probably
better done during the connector check phase of the next commit, which
could check the previous payload allocations, I'll check if that works.

> either way:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks.

> > To work around the problem detect this monitor and the condition for the
> > problem (when the last two slots get allocated in a commit), force a
> > full modeset of the MST topology in the subsequent commit and reset the
> > payload table during the latter commit after all payloads have been
> > freed.
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Lyude Paul <lyude@redhat.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_atomic.c   | 13 +++--
> >  drivers/gpu/drm/i915/display/intel_atomic.h   |  3 +-
> >  .../drm/i915/display/intel_display_types.h    |  1 +
> >  drivers/gpu/drm/i915/display/intel_dp.c       |  5 +-
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   | 48 +++++++++++++++++--
> >  5 files changed, 61 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
> > index 0f1c5b9c9a826..04e5f0e0fffa6 100644
> > --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> > @@ -616,7 +616,8 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
> >  }
> >  
> >  static int modeset_pipe(struct intel_atomic_state *state,
> > -			struct intel_crtc *crtc, const char *reason)
> > +			struct intel_crtc *crtc, const char *reason,
> > +			bool allow_fastset)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(state->base.dev);
> >  	struct intel_crtc_state *crtc_state;
> > @@ -629,6 +630,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
> >  		return PTR_ERR(crtc_state);
> >  
> >  	crtc_state->uapi.mode_changed = true;
> > +	if (!allow_fastset)
> > +		crtc_state->uapi.connectors_changed = true;
> >  	crtc_state->update_pipe = false;
> >  
> >  	return intel_atomic_add_affected_planes(state, crtc);
> > @@ -639,6 +642,7 @@ static int modeset_pipe(struct intel_atomic_state *state,
> >   * @state: atomic state
> >   * @connector: connector to add the state for
> >   * @reason: the reason why the connector needs to be added
> > + * @allow_fastset: allow a fastset
> >   *
> >   * Add the @connector to the atomic state with its CRTC state and force a modeset
> >   * on the CRTC if any.
> > @@ -648,7 +652,8 @@ static int modeset_pipe(struct intel_atomic_state *state,
> >   * Returns 0 in case of success, a negative error code on failure.
> >   */
> >  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> > -				   struct intel_connector *connector, const char *reason)
> > +				   struct intel_connector *connector, const char *reason,
> > +				   bool allow_fastset)
> >  {
> >  	struct drm_i915_private *i915 = to_i915(state->base.dev);
> >  	struct drm_connector_state *conn_state;
> > @@ -671,7 +676,7 @@ int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> >  	if (ret)
> >  		return ret;
> >  
> > -	return modeset_pipe(state, crtc, reason);
> > +	return modeset_pipe(state, crtc, reason, allow_fastset);
> >  }
> >  
> >  /**
> > @@ -700,7 +705,7 @@ int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
> >  	if (ret)
> >  		return ret;
> >  
> > -	return modeset_pipe(state, crtc, reason);
> > +	return modeset_pipe(state, crtc, reason, true);
> >  }
> >  
> >  /**
> > diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h
> > index 84295d388e3cb..7778aea8a09fe 100644
> > --- a/drivers/gpu/drm/i915/display/intel_atomic.h
> > +++ b/drivers/gpu/drm/i915/display/intel_atomic.h
> > @@ -59,7 +59,8 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
> >  int intel_atomic_modeset_pipe(struct intel_atomic_state *state,
> >  			      struct intel_crtc *crtc, const char *reason);
> >  int intel_atomic_modeset_connector(struct intel_atomic_state *state,
> > -				   struct intel_connector *connector, const char *reason);
> > +				   struct intel_connector *connector, const char *reason,
> > +				   bool allow_fastset);
> >  int intel_atomic_modeset_all_pipes(struct intel_atomic_state *state,
> >  				   const char *reason);
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 9ccae7a460200..06d51d2b5e0d6 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1656,6 +1656,7 @@ struct intel_dp {
> >  	bool has_audio;
> >  	bool reset_link_params;
> >  	bool use_max_params;
> > +	bool mst_reset_payload_table;
> >  	u8 dpcd[DP_RECEIVER_CAP_SIZE];
> >  	u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
> >  	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index d6b0ef38f6563..c157bcd976103 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -4689,6 +4689,8 @@ intel_dp_detect(struct drm_connector *connector,
> >  		memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
> >  		memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
> >  
> > +		intel_dp->mst_reset_payload_table = false;
> > +
> >  		if (intel_dp->is_mst) {
> >  			drm_dbg_kms(&dev_priv->drm,
> >  				    "MST device may have disappeared %d vs %d\n",
> > @@ -4924,7 +4926,8 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
> >  			continue;
> >  
> >  		ret = intel_atomic_modeset_connector(state, connector,
> > -						     "connector tile group");
> > +						     "connector tile group",
> > +						     true);
> >  		if (ret)
> >  			break;
> >  	}
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 08222fc6c5ecd..a9bb339e41987 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -422,9 +422,10 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> >  	struct drm_connector_list_iter connector_list_iter;
> >  	struct intel_connector *connector_iter;
> > +	bool reset_payload_table = connector->mst_port->mst_reset_payload_table;
> >  	int ret = 0;
> >  
> > -	if (DISPLAY_VER(dev_priv) < 12)
> > +	if (DISPLAY_VER(dev_priv) < 12 && !reset_payload_table)
> >  		return  0;
> >  
> >  	if (!intel_connector_needs_modeset(state, &connector->base))
> > @@ -437,7 +438,8 @@ intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector,
> >  			continue;
> >  
> >  		ret = intel_atomic_modeset_connector(state, connector_iter,
> > -						     "MST master transcoder");
> > +						     "MST master transcoder",
> > +						     !reset_payload_table);
> >  		if (ret)
> >  			break;
> >  	}
> > @@ -531,6 +533,41 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> >  }
> >  
> > +static void detect_payload_allocation_bug(const struct drm_dp_mst_topology_state *mst_state,
> > +					  const struct intel_connector *connector,
> > +					  struct intel_dp *intel_dp)
> > +{
> > +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > +
> > +	if (!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_MST_PAYLOAD_TABLE_RESET_WA))
> > +		return;
> > +
> > +	if (drm_dp_mst_allocated_time_slots(mst_state) < DP_PAYLOAD_TABLE_SIZE - 2)
> > +		return;
> > +
> > +	drm_dbg(&i915->drm,
> > +		"[CONNECTOR:%d:%s] Payload table allocation bug detected\n",
> > +		connector->base.base.id, connector->base.name);
> > +
> > +	intel_dp->mst_reset_payload_table = true;
> > +}
> > +
> > +static void payload_allocation_bug_wa(const struct intel_connector *connector,
> > +				      struct intel_dp *intel_dp)
> > +{
> > +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> > +
> > +	if (!intel_dp->mst_reset_payload_table)
> > +		return;
> > +
> > +	drm_dbg(&i915->drm,
> > +		"[CONNECTOR:%d:%s] Resetting payload table due to allocation bug\n",
> > +		connector->base.base.id, connector->base.name);
> > +
> > +	drm_dp_mst_reset_payload_table(&intel_dp->mst_mgr);
> > +	intel_dp->mst_reset_payload_table = false;
> > +}
> > +
> >  static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
> >  				      struct intel_encoder *encoder,
> >  				      const struct intel_crtc_state *old_crtc_state,
> > @@ -594,10 +631,13 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
> >  
> >  
> >  	intel_mst->connector = NULL;
> > -	if (last_mst_stream)
> > +	if (last_mst_stream) {
> >  		dig_port->base.post_disable(state, &dig_port->base,
> >  						  old_crtc_state, NULL);
> >  
> > +		payload_allocation_bug_wa(connector, intel_dp);
> > +	}
> > +
> >  	drm_dbg_kms(&dev_priv->drm, "active links %d\n",
> >  		    intel_dp->active_mst_links);
> >  }
> > @@ -662,6 +702,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
> >  		drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
> >  			connector->base.name, ret);
> >  
> > +	detect_payload_allocation_bug(mst_state, connector, intel_dp);
> > +
> >  	/*
> >  	 * Before Gen 12 this is not done as part of
> >  	 * dig_port->base.pre_enable() and should be done here. For
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-01-31 23:13     ` [Intel-gfx] " Lyude Paul
  (?)
@ 2023-02-01 15:04       ` Imre Deak
  -1 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-01 15:04 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Tue, Jan 31, 2023 at 06:13:10PM -0500, Lyude Paul wrote:
> On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> > Atm, drm_dp_remove_payload() uses the same payload state to both get the
> > vc_start_slot required for the payload removal DPCD message and to
> > deduct time_slots from vc_start_slot of all payloads after the one being
> > removed.
> > 
> > The above isn't always correct, as vc_start_slot must be the up-to-date
> > version contained in the new payload state, but time_slots must be the
> > one used when the payload was previously added, contained in the old
> > payload state. The new payload's time_slots can change vs. the old one
> > if the current atomic commit changes the corresponding mode.
> > 
> > This patch let's drivers pass the old and new payload states to
> > drm_dp_remove_payload(), but keeps these the same for now in all drivers
> > not to change the behavior. A follow-up i915 patch will pass in that
> > driver the correct old and new states to the function.
> 
> Oh wow, this was definitely a mistake on my part, thanks for catching this!
> TBH, I think this behavior is correct so (now that I actually have a setup
> capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
> like to change it on other drivers as well I can test it fully.

I only checked that the other drivers pass the new payload state to
drm_dp_remove_payload(), so not sure how that works atm if the same
commit has to both remove the payload (with the old time_slots value)
and add it back (with a new time_slots value). Maybe that can't happen
in those drivers, or time_slots get updated between remove and readd.

> Or feel free to leave it to me, shouldn't be too difficult I think :).

Yes, this patch should have no functional change, so please check what
would apply to other drivers as well.

Could you also check Ville's comment about storing start_slot elsewhere
than the atomic state (leaving only time_slots there). I wonder if that
would work, at least it would simplify things I think.

> For 0-2:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks.

> 
> > 
> > Cc: Lyude Paul <lyude@redhat.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Ben Skeggs <bskeggs@redhat.com>
> > Cc: Karol Herbst <kherbst@redhat.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: Alex Deucher <alexander.deucher@amd.com>
> > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: stable@vger.kernel.org # 6.1
> > Cc: dri-devel@lists.freedesktop.org
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> >  5 files changed, 21 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > index a50319fc42b11..180d3893b68da 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> >  	if (enable)
> >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> >  	else
> > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> >  
> >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 847c10aa2098c..1990ff5dc7ddd 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   * drm_dp_remove_payload() - Remove an MST payload
> >   * @mgr: Manager to use.
> >   * @mst_state: The MST atomic state
> > - * @payload: The payload to write
> > + * @old_payload: The payload with its old state
> > + * @new_payload: The payload to write
> >   *
> >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   */
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload)
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload)
> >  {
> >  	struct drm_dp_mst_atomic_payload *pos;
> >  	bool send_remove = false;
> >  
> >  	/* We failed to make the payload, so nothing to do */
> > -	if (payload->vc_start_slot == -1)
> > +	if (new_payload->vc_start_slot == -1)
> >  		return;
> >  
> >  	mutex_lock(&mgr->lock);
> > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> >  	mutex_unlock(&mgr->lock);
> >  
> >  	if (send_remove)
> > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> >  	else
> >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > -			    payload->vcpi);
> > +			    new_payload->vcpi);
> >  
> >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > -			pos->vc_start_slot -= payload->time_slots;
> > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > +			pos->vc_start_slot -= old_payload->time_slots;
> >  	}
> > -	payload->vc_start_slot = -1;
> > +	new_payload->vc_start_slot = -1;
> >  
> >  	mgr->payload_count--;
> > -	mgr->next_start_slot -= payload->time_slots;
> > +	mgr->next_start_slot -= old_payload->time_slots;
> >  
> > -	if (payload->delete)
> > -		drm_dp_mst_put_port_malloc(payload->port);
> > +	if (new_payload->delete)
> > +		drm_dp_mst_put_port_malloc(new_payload->port);
> >  }
> >  EXPORT_SYMBOL(drm_dp_remove_payload);
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  		to_intel_connector(old_conn_state->connector);
> >  	struct drm_dp_mst_topology_state *mst_state =
> >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > +	struct drm_dp_mst_atomic_payload *payload =
> > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> >  
> >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  	intel_hdcp_disable(intel_mst->connector);
> >  
> >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > +			      payload, payload);
> >  
> >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> >  }
> > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > index edcb2529b4025..ed9d374147b8d 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> >  
> >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> >  	if (msto->disabled) {
> > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> >  
> >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> >  	} else {
> > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > index 41fd8352ab656..f5eb9aa152b14 100644
> > --- a/include/drm/display/drm_dp_mst_helper.h
> > +++ b/include/drm/display/drm_dp_mst_helper.h
> > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> >  			     struct drm_dp_mst_atomic_payload *payload);
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload);
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload);
> >  
> >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> >  
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-01 15:04       ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-01 15:04 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Tue, Jan 31, 2023 at 06:13:10PM -0500, Lyude Paul wrote:
> On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> > Atm, drm_dp_remove_payload() uses the same payload state to both get the
> > vc_start_slot required for the payload removal DPCD message and to
> > deduct time_slots from vc_start_slot of all payloads after the one being
> > removed.
> > 
> > The above isn't always correct, as vc_start_slot must be the up-to-date
> > version contained in the new payload state, but time_slots must be the
> > one used when the payload was previously added, contained in the old
> > payload state. The new payload's time_slots can change vs. the old one
> > if the current atomic commit changes the corresponding mode.
> > 
> > This patch let's drivers pass the old and new payload states to
> > drm_dp_remove_payload(), but keeps these the same for now in all drivers
> > not to change the behavior. A follow-up i915 patch will pass in that
> > driver the correct old and new states to the function.
> 
> Oh wow, this was definitely a mistake on my part, thanks for catching this!
> TBH, I think this behavior is correct so (now that I actually have a setup
> capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
> like to change it on other drivers as well I can test it fully.

I only checked that the other drivers pass the new payload state to
drm_dp_remove_payload(), so not sure how that works atm if the same
commit has to both remove the payload (with the old time_slots value)
and add it back (with a new time_slots value). Maybe that can't happen
in those drivers, or time_slots get updated between remove and readd.

> Or feel free to leave it to me, shouldn't be too difficult I think :).

Yes, this patch should have no functional change, so please check what
would apply to other drivers as well.

Could you also check Ville's comment about storing start_slot elsewhere
than the atomic state (leaving only time_slots there). I wonder if that
would work, at least it would simplify things I think.

> For 0-2:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks.

> 
> > 
> > Cc: Lyude Paul <lyude@redhat.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Ben Skeggs <bskeggs@redhat.com>
> > Cc: Karol Herbst <kherbst@redhat.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: Alex Deucher <alexander.deucher@amd.com>
> > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: stable@vger.kernel.org # 6.1
> > Cc: dri-devel@lists.freedesktop.org
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> >  5 files changed, 21 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > index a50319fc42b11..180d3893b68da 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> >  	if (enable)
> >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> >  	else
> > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> >  
> >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 847c10aa2098c..1990ff5dc7ddd 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   * drm_dp_remove_payload() - Remove an MST payload
> >   * @mgr: Manager to use.
> >   * @mst_state: The MST atomic state
> > - * @payload: The payload to write
> > + * @old_payload: The payload with its old state
> > + * @new_payload: The payload to write
> >   *
> >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   */
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload)
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload)
> >  {
> >  	struct drm_dp_mst_atomic_payload *pos;
> >  	bool send_remove = false;
> >  
> >  	/* We failed to make the payload, so nothing to do */
> > -	if (payload->vc_start_slot == -1)
> > +	if (new_payload->vc_start_slot == -1)
> >  		return;
> >  
> >  	mutex_lock(&mgr->lock);
> > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> >  	mutex_unlock(&mgr->lock);
> >  
> >  	if (send_remove)
> > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> >  	else
> >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > -			    payload->vcpi);
> > +			    new_payload->vcpi);
> >  
> >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > -			pos->vc_start_slot -= payload->time_slots;
> > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > +			pos->vc_start_slot -= old_payload->time_slots;
> >  	}
> > -	payload->vc_start_slot = -1;
> > +	new_payload->vc_start_slot = -1;
> >  
> >  	mgr->payload_count--;
> > -	mgr->next_start_slot -= payload->time_slots;
> > +	mgr->next_start_slot -= old_payload->time_slots;
> >  
> > -	if (payload->delete)
> > -		drm_dp_mst_put_port_malloc(payload->port);
> > +	if (new_payload->delete)
> > +		drm_dp_mst_put_port_malloc(new_payload->port);
> >  }
> >  EXPORT_SYMBOL(drm_dp_remove_payload);
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  		to_intel_connector(old_conn_state->connector);
> >  	struct drm_dp_mst_topology_state *mst_state =
> >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > +	struct drm_dp_mst_atomic_payload *payload =
> > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> >  
> >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  	intel_hdcp_disable(intel_mst->connector);
> >  
> >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > +			      payload, payload);
> >  
> >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> >  }
> > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > index edcb2529b4025..ed9d374147b8d 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> >  
> >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> >  	if (msto->disabled) {
> > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> >  
> >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> >  	} else {
> > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > index 41fd8352ab656..f5eb9aa152b14 100644
> > --- a/include/drm/display/drm_dp_mst_helper.h
> > +++ b/include/drm/display/drm_dp_mst_helper.h
> > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> >  			     struct drm_dp_mst_atomic_payload *payload);
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload);
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload);
> >  
> >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> >  
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-01 15:04       ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-01 15:04 UTC (permalink / raw)
  To: Lyude Paul
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Tue, Jan 31, 2023 at 06:13:10PM -0500, Lyude Paul wrote:
> On Tue, 2023-01-31 at 17:05 +0200, Imre Deak wrote:
> > Atm, drm_dp_remove_payload() uses the same payload state to both get the
> > vc_start_slot required for the payload removal DPCD message and to
> > deduct time_slots from vc_start_slot of all payloads after the one being
> > removed.
> > 
> > The above isn't always correct, as vc_start_slot must be the up-to-date
> > version contained in the new payload state, but time_slots must be the
> > one used when the payload was previously added, contained in the old
> > payload state. The new payload's time_slots can change vs. the old one
> > if the current atomic commit changes the corresponding mode.
> > 
> > This patch let's drivers pass the old and new payload states to
> > drm_dp_remove_payload(), but keeps these the same for now in all drivers
> > not to change the behavior. A follow-up i915 patch will pass in that
> > driver the correct old and new states to the function.
> 
> Oh wow, this was definitely a mistake on my part, thanks for catching this!
> TBH, I think this behavior is correct so (now that I actually have a setup
> capable of testing amdgpu's MST fully thanks to gitlab issue 2171…) if you'd
> like to change it on other drivers as well I can test it fully.

I only checked that the other drivers pass the new payload state to
drm_dp_remove_payload(), so not sure how that works atm if the same
commit has to both remove the payload (with the old time_slots value)
and add it back (with a new time_slots value). Maybe that can't happen
in those drivers, or time_slots get updated between remove and readd.

> Or feel free to leave it to me, shouldn't be too difficult I think :).

Yes, this patch should have no functional change, so please check what
would apply to other drivers as well.

Could you also check Ville's comment about storing start_slot elsewhere
than the atomic state (leaving only time_slots there). I wonder if that
would work, at least it would simplify things I think.

> For 0-2:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks.

> 
> > 
> > Cc: Lyude Paul <lyude@redhat.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Ben Skeggs <bskeggs@redhat.com>
> > Cc: Karol Herbst <kherbst@redhat.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: Alex Deucher <alexander.deucher@amd.com>
> > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: stable@vger.kernel.org # 6.1
> > Cc: dri-devel@lists.freedesktop.org
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> >  5 files changed, 21 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > index a50319fc42b11..180d3893b68da 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> >  	if (enable)
> >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> >  	else
> > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> >  
> >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 847c10aa2098c..1990ff5dc7ddd 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   * drm_dp_remove_payload() - Remove an MST payload
> >   * @mgr: Manager to use.
> >   * @mst_state: The MST atomic state
> > - * @payload: The payload to write
> > + * @old_payload: The payload with its old state
> > + * @new_payload: The payload to write
> >   *
> >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> >   */
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload)
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload)
> >  {
> >  	struct drm_dp_mst_atomic_payload *pos;
> >  	bool send_remove = false;
> >  
> >  	/* We failed to make the payload, so nothing to do */
> > -	if (payload->vc_start_slot == -1)
> > +	if (new_payload->vc_start_slot == -1)
> >  		return;
> >  
> >  	mutex_lock(&mgr->lock);
> > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> >  	mutex_unlock(&mgr->lock);
> >  
> >  	if (send_remove)
> > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> >  	else
> >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > -			    payload->vcpi);
> > +			    new_payload->vcpi);
> >  
> >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > -			pos->vc_start_slot -= payload->time_slots;
> > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > +			pos->vc_start_slot -= old_payload->time_slots;
> >  	}
> > -	payload->vc_start_slot = -1;
> > +	new_payload->vc_start_slot = -1;
> >  
> >  	mgr->payload_count--;
> > -	mgr->next_start_slot -= payload->time_slots;
> > +	mgr->next_start_slot -= old_payload->time_slots;
> >  
> > -	if (payload->delete)
> > -		drm_dp_mst_put_port_malloc(payload->port);
> > +	if (new_payload->delete)
> > +		drm_dp_mst_put_port_malloc(new_payload->port);
> >  }
> >  EXPORT_SYMBOL(drm_dp_remove_payload);
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  		to_intel_connector(old_conn_state->connector);
> >  	struct drm_dp_mst_topology_state *mst_state =
> >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > +	struct drm_dp_mst_atomic_payload *payload =
> > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> >  
> >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> >  	intel_hdcp_disable(intel_mst->connector);
> >  
> >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > +			      payload, payload);
> >  
> >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> >  }
> > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > index edcb2529b4025..ed9d374147b8d 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> >  
> >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> >  	if (msto->disabled) {
> > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> >  
> >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> >  	} else {
> > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > index 41fd8352ab656..f5eb9aa152b14 100644
> > --- a/include/drm/display/drm_dp_mst_helper.h
> > +++ b/include/drm/display/drm_dp_mst_helper.h
> > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> >  			     struct drm_dp_mst_atomic_payload *payload);
> >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> >  			   struct drm_dp_mst_topology_state *mst_state,
> > -			   struct drm_dp_mst_atomic_payload *payload);
> > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > +			   struct drm_dp_mst_atomic_payload *new_payload);
> >  
> >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> >  
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:15     ` Dan Carpenter
  0 siblings, 0 replies; 70+ messages in thread
From: kernel test robot @ 2023-02-02 10:13 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Dan Carpenter

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20230131150548.1614458-12-imre.deak@intel.com>
References: <20230131150548.1614458-12-imre.deak@intel.com>
TO: Imre Deak <imre.deak@intel.com>
TO: intel-gfx@lists.freedesktop.org
CC: dri-devel@lists.freedesktop.org

Hi Imre,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-tip/drm-tip]

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
:::::: branch date: 2 days ago
:::::: commit date: 2 days ago
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>

smatch warnings:
drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'

vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c

ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3291  
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3292  /**
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3293   * drm_dp_add_payload_part1() - Execute payload update part 1
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3294   * @mgr: Manager to use.
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3295   * @mst_state: The MST atomic state
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3296   * @payload: The payload to write
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3297   *
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3298   * Determines the starting time slot for the given payload, and programs the VCPI for this payload
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3299   * into hardware. After calling this, the driver should generate ACT and payload packets.
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3300   *
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3301   * Returns: 0 on success, error code on failure. In the event that this fails,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3302   * @payload.vc_start_slot will also be set to -1.
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3303   */
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3345  EXPORT_SYMBOL(drm_dp_add_payload_part1);
263efde31f97c4 drivers/gpu/drm/drm_dp_mst_topology.c         cpaul@redhat.com 2016-04-22  3346  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

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

* Re: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:15     ` Dan Carpenter
  0 siblings, 0 replies; 70+ messages in thread
From: Dan Carpenter @ 2023-02-02 12:15 UTC (permalink / raw)
  To: oe-kbuild, Imre Deak, intel-gfx; +Cc: lkp, oe-kbuild-all, dri-devel

Hi Imre,

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>

smatch warnings:
drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'

vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c

4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;

Hard to tell if this is an error path or a success path.

33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests


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

* Re: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:15     ` Dan Carpenter
  0 siblings, 0 replies; 70+ messages in thread
From: Dan Carpenter @ 2023-02-02 12:15 UTC (permalink / raw)
  To: oe-kbuild, Imre Deak, intel-gfx; +Cc: lkp, dri-devel, oe-kbuild-all

Hi Imre,

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>

smatch warnings:
drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'

vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c

4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;

Hard to tell if this is an error path or a success path.

33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests


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

* Re: [Intel-gfx] [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:15     ` Dan Carpenter
  0 siblings, 0 replies; 70+ messages in thread
From: Dan Carpenter @ 2023-02-02 12:15 UTC (permalink / raw)
  To: oe-kbuild, Imre Deak, intel-gfx; +Cc: dri-devel, oe-kbuild-all

Hi Imre,

url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>

smatch warnings:
drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'

vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c

4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;

Hard to tell if this is an error path or a success path.

33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests


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

* Re: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
  2023-02-02 12:15     ` Dan Carpenter
  (?)
@ 2023-02-02 12:35       ` Imre Deak
  -1 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-02 12:35 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: oe-kbuild, intel-gfx, lkp, oe-kbuild-all, dri-devel

Hi,

On Thu, Feb 02, 2023 at 03:15:46PM +0300, Dan Carpenter wrote:
> Hi Imre,
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
> base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
> patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
> patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
> config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
> compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
> 
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Reported-by: Dan Carpenter <error27@gmail.com>
> 
> smatch warnings:
> drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'
> 
> vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c
> 
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
> 706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;
> 
> Hard to tell if this is an error path or a success path.

thanks for the report. The function before the change in this patchset
returned 0 in this case, so I didn't want to change that. Looking at the
callers none of them uses the return value (except for printing an error
message). I think returning an error code in this case as well would be
more consistent, but that change should be a follow-up.

> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
> 3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
> dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }
> 
> -- 
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests
> 

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

* Re: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:35       ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-02 12:35 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: intel-gfx, oe-kbuild-all, oe-kbuild, dri-devel, lkp

Hi,

On Thu, Feb 02, 2023 at 03:15:46PM +0300, Dan Carpenter wrote:
> Hi Imre,
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
> base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
> patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
> patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
> config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
> compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
> 
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Reported-by: Dan Carpenter <error27@gmail.com>
> 
> smatch warnings:
> drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'
> 
> vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c
> 
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
> 706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;
> 
> Hard to tell if this is an error path or a success path.

thanks for the report. The function before the change in this patchset
returned 0 in this case, so I didn't want to change that. Looking at the
callers none of them uses the return value (except for printing an error
message). I think returning an error code in this case as well would be
more consistent, but that change should be a follow-up.

> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
> 3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
> dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }
> 
> -- 
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests
> 

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

* Re: [Intel-gfx] [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
@ 2023-02-02 12:35       ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-02 12:35 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: intel-gfx, oe-kbuild-all, oe-kbuild, dri-devel

Hi,

On Thu, Feb 02, 2023 at 03:15:46PM +0300, Dan Carpenter wrote:
> Hi Imre,
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Imre-Deak/drm-i915-dp_mst-Add-the-MST-topology-state-for-modesetted-CRTCs/20230131-230853
> base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
> patch link:    https://lore.kernel.org/r/20230131150548.1614458-12-imre.deak%40intel.com
> patch subject: [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors
> config: x86_64-randconfig-m001 (https://download.01.org/0day-ci/archive/20230202/202302021855.yyqIeQ2o-lkp@intel.com/config)
> compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
> 
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Reported-by: Dan Carpenter <error27@gmail.com>
> 
> smatch warnings:
> drivers/gpu/drm/display/drm_dp_mst_topology.c:3316 drm_dp_add_payload_part1() warn: missing error code 'ret'
> 
> vim +/ret +3316 drivers/gpu/drm/display/drm_dp_mst_topology.c
> 
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3304  int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3305  			     struct drm_dp_mst_topology_state *mst_state,
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3306  			     struct drm_dp_mst_atomic_payload *payload)
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3307  {
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3308  	struct drm_dp_mst_port *port;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3309  	int ret = 0;
> 706246c761ddd3 drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2018-12-13  3310  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3311  	port = drm_dp_mst_topology_get_port_validated(mgr, payload->port);
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3312  	if (!port) {
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3313  		drm_dbg_kms(mgr->dev,
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3314  			    "VCPI %d for port %p not in topology, not creating a payload\n",
> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3315  			    payload->vcpi, payload->port);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31 @3316  		goto alloc_fail;
> 
> Hard to tell if this is an error path or a success path.

thanks for the report. The function before the change in this patchset
returned 0 in this case, so I didn't want to change that. Looking at the
callers none of them uses the return value (except for printing an error
message). I think returning an error code in this case as well would be
more consistent, but that change should be a follow-up.

> 33f960e23c29d1 drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2022-12-14  3317  	}
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3318  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3319  	if (mgr->payload_count == 0)
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3320  		mgr->next_start_slot = mst_state->start_slot;
> 3769e4c0af5b82 drivers/gpu/drm/drm_dp_mst_topology.c         Wayne Lin        2021-06-16  3321  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3322  	payload->vc_start_slot = mgr->next_start_slot;
> cfe9f90358d97a drivers/gpu/drm/drm_dp_mst_topology.c         Lyude Paul       2019-01-10  3323  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3324  	ret = drm_dp_create_payload_step1(mgr, payload);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3325  	drm_dp_mst_topology_put_port(port);
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3326  	if (ret < 0) {
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3327  		drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n",
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3328  			 payload->port, ret);
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3329  		goto alloc_fail;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3330  	}
> dfda0df3426483 drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-08-06  3331  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3332  	payload->alloc_failed = false;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3333  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3334  	mgr->payload_count++;
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3335  	mgr->next_start_slot += payload->time_slots;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3336  
> 4d07b0bc403403 drivers/gpu/drm/display/drm_dp_mst_topology.c Lyude Paul       2022-08-17  3337  	return 0;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3338  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3339  alloc_fail:
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3340  	payload->vc_start_slot = -1;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3341  	payload->alloc_failed = true;
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3342  
> 5c4df7ffba973b drivers/gpu/drm/display/drm_dp_mst_topology.c Imre Deak        2023-01-31  3343  	return ret;
> ad7f8a1f9ced7f drivers/gpu/drm/drm_dp_mst_topology.c         Dave Airlie      2014-06-05  3344  }
> 
> -- 
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests
> 

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

* Re: [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
  2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration " Imre Deak
  2023-01-31 23:14   ` Lyude Paul
@ 2023-02-03 12:22   ` Ville Syrjälä
  2023-02-03 13:12     ` Imre Deak
  1 sibling, 1 reply; 70+ messages in thread
From: Ville Syrjälä @ 2023-02-03 12:22 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Jan 31, 2023 at 05:05:37PM +0200, Imre Deak wrote:
> Simplify the loop iterating the payloads by using a helper to get a
> payload by its VCPI (keeping the list VCPI sorted). This also removes
> the assumption that the biggest VCPI matches the number of payloads
> (even though this holds now).
> 
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Lyude Paul <lyude@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 45 ++++++++++++-------
>  1 file changed, 28 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> index 8787df19f428b..0c04b96ae614c 100644
> --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> @@ -4737,6 +4737,18 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
>  	kfree(mst_edid);
>  }
>  
> +static struct drm_dp_mst_atomic_payload *
> +get_payload_by_vcpi(struct drm_dp_mst_topology_state *mst_state, int vcpi)
> +{
> +	struct drm_dp_mst_atomic_payload *payload;
> +
> +	list_for_each_entry(payload, &mst_state->payloads, next)
> +		if (payload->vcpi == vcpi)
> +			return payload;
> +
> +	return NULL;
> +}
> +
>  /**
>   * drm_dp_mst_dump_topology(): dump topology to seq file.
>   * @m: seq_file to dump output to
> @@ -4748,7 +4760,6 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
>  			      struct drm_dp_mst_topology_mgr *mgr)
>  {
>  	struct drm_dp_mst_topology_state *state;
> -	struct drm_dp_mst_atomic_payload *payload;
>  	int i, ret;
>  
>  	mutex_lock(&mgr->lock);
> @@ -4768,24 +4779,24 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
>  		   state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
>  
>  	seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc |     sink name     |\n");
> -	for (i = 0; i < mgr->max_payloads; i++) {
> -		list_for_each_entry(payload, &state->payloads, next) {
> -			char name[14];
> +	for_each_set_bit(i, (unsigned long *)&state->payload_mask,
> +			 BITS_PER_TYPE(state->payload_mask)) {

payload_mask is u32, unsigned long can be 64 bits. Does this
actually work for both little and big endian?

> +		const struct drm_dp_mst_atomic_payload *payload = get_payload_by_vcpi(state, i + 1);
> +		char name[14];
>  
> -			if (payload->vcpi != i + 1 || payload->delete)
> -				continue;
> +		if (payload->delete)
> +			continue;
>  
> -			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> -			seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> -				   i,
> -				   payload->port->port_num,
> -				   payload->vcpi,
> -				   payload->vc_start_slot,
> -				   payload->vc_start_slot + payload->time_slots - 1,
> -				   payload->pbn,
> -				   payload->dsc_enabled ? "Y" : "N",
> -				   (*name != 0) ? name : "Unknown");
> -		}
> +		fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> +		seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> +			   i,
> +			   payload->port->port_num,
> +			   payload->vcpi,
> +			   payload->vc_start_slot,
> +			   payload->vc_start_slot + payload->time_slots - 1,
> +			   payload->pbn,
> +			   payload->dsc_enabled ? "Y" : "N",
> +			   (*name != 0) ? name : "Unknown");
>  	}
>  
>  	seq_printf(m, "\n*** DPCD Info ***\n");
> -- 
> 2.37.1

-- 
Ville Syrjälä
Intel

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

* Re: [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration in drm_dp_mst_dump_topology()
  2023-02-03 12:22   ` Ville Syrjälä
@ 2023-02-03 13:12     ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-03 13:12 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Feb 03, 2023 at 02:22:44PM +0200, Ville Syrjälä wrote:
> On Tue, Jan 31, 2023 at 05:05:37PM +0200, Imre Deak wrote:
> > Simplify the loop iterating the payloads by using a helper to get a
> > payload by its VCPI (keeping the list VCPI sorted). This also removes
> > the assumption that the biggest VCPI matches the number of payloads
> > (even though this holds now).
> > 
> > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Lyude Paul <lyude@redhat.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 45 ++++++++++++-------
> >  1 file changed, 28 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > index 8787df19f428b..0c04b96ae614c 100644
> > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > @@ -4737,6 +4737,18 @@ static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
> >  	kfree(mst_edid);
> >  }
> >  
> > +static struct drm_dp_mst_atomic_payload *
> > +get_payload_by_vcpi(struct drm_dp_mst_topology_state *mst_state, int vcpi)
> > +{
> > +	struct drm_dp_mst_atomic_payload *payload;
> > +
> > +	list_for_each_entry(payload, &mst_state->payloads, next)
> > +		if (payload->vcpi == vcpi)
> > +			return payload;
> > +
> > +	return NULL;
> > +}
> > +
> >  /**
> >   * drm_dp_mst_dump_topology(): dump topology to seq file.
> >   * @m: seq_file to dump output to
> > @@ -4748,7 +4760,6 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
> >  			      struct drm_dp_mst_topology_mgr *mgr)
> >  {
> >  	struct drm_dp_mst_topology_state *state;
> > -	struct drm_dp_mst_atomic_payload *payload;
> >  	int i, ret;
> >  
> >  	mutex_lock(&mgr->lock);
> > @@ -4768,24 +4779,24 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
> >  		   state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
> >  
> >  	seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc |     sink name     |\n");
> > -	for (i = 0; i < mgr->max_payloads; i++) {
> > -		list_for_each_entry(payload, &state->payloads, next) {
> > -			char name[14];
> > +	for_each_set_bit(i, (unsigned long *)&state->payload_mask,
> > +			 BITS_PER_TYPE(state->payload_mask)) {
> 
> payload_mask is u32, unsigned long can be 64 bits. Does this
> actually work for both little and big endian?

That's a good catch, on big-endian it's bogus AFAICS. There doesn't
seem to be a 32 bit version of for_each_set_bit, so would

	unsigned long mask = state->payload_mask;
	for_each_set_bit(i, &mask, BITS_PER_TYPE(mask))

be ok?

> 
> > +		const struct drm_dp_mst_atomic_payload *payload = get_payload_by_vcpi(state, i + 1);
> > +		char name[14];
> >  
> > -			if (payload->vcpi != i + 1 || payload->delete)
> > -				continue;
> > +		if (payload->delete)
> > +			continue;
> >  
> > -			fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> > -			seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> > -				   i,
> > -				   payload->port->port_num,
> > -				   payload->vcpi,
> > -				   payload->vc_start_slot,
> > -				   payload->vc_start_slot + payload->time_slots - 1,
> > -				   payload->pbn,
> > -				   payload->dsc_enabled ? "Y" : "N",
> > -				   (*name != 0) ? name : "Unknown");
> > -		}
> > +		fetch_monitor_name(mgr, payload->port, name, sizeof(name));
> > +		seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n",
> > +			   i,
> > +			   payload->port->port_num,
> > +			   payload->vcpi,
> > +			   payload->vc_start_slot,
> > +			   payload->vc_start_slot + payload->time_slots - 1,
> > +			   payload->pbn,
> > +			   payload->dsc_enabled ? "Y" : "N",
> > +			   (*name != 0) ? name : "Unknown");
> >  	}
> >  
> >  	seq_printf(m, "\n*** DPCD Info ***\n");
> > -- 
> > 2.37.1
> 
> -- 
> Ville Syrjälä
> Intel

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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-02-01 15:04       ` [Intel-gfx] " Imre Deak
  (?)
@ 2023-02-07  0:42         ` Lyude Paul
  -1 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-07  0:42 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> 
> Yes, this patch should have no functional change, so please check what
> would apply to other drivers as well.
> 
> Could you also check Ville's comment about storing start_slot elsewhere
> than the atomic state (leaving only time_slots there). I wonder if that
> would work, at least it would simplify things I think.

Ideally it'd be nice if we could have all this info in the atomic commit, but
yeah - you're not the first person to find this a bit confusing. FWIW though,
the way we store start_slot right now is intended to follow the same kind of
behavior we have with atomic CRTC commit dependencies, I think I also made it
that way so all of the state would be in a single place but there's no hard
requirement for it.

So if you guys think it'd be better design-wise to store this something else,
I've got no strong feelings either way
> 
> > For 0-2:
> > 
> > Reviewed-by: Lyude Paul <lyude@redhat.com>
> 
> Thanks.
> 
> > 
> > > 
> > > Cc: Lyude Paul <lyude@redhat.com>
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > Cc: Karol Herbst <kherbst@redhat.com>
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > Cc: stable@vger.kernel.org # 6.1
> > > Cc: dri-devel@lists.freedesktop.org
> > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > index a50319fc42b11..180d3893b68da 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > >  	if (enable)
> > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > >  	else
> > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > >  
> > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   * drm_dp_remove_payload() - Remove an MST payload
> > >   * @mgr: Manager to use.
> > >   * @mst_state: The MST atomic state
> > > - * @payload: The payload to write
> > > + * @old_payload: The payload with its old state
> > > + * @new_payload: The payload to write
> > >   *
> > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   */
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > >  {
> > >  	struct drm_dp_mst_atomic_payload *pos;
> > >  	bool send_remove = false;
> > >  
> > >  	/* We failed to make the payload, so nothing to do */
> > > -	if (payload->vc_start_slot == -1)
> > > +	if (new_payload->vc_start_slot == -1)
> > >  		return;
> > >  
> > >  	mutex_lock(&mgr->lock);
> > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > >  	mutex_unlock(&mgr->lock);
> > >  
> > >  	if (send_remove)
> > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > >  	else
> > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > -			    payload->vcpi);
> > > +			    new_payload->vcpi);
> > >  
> > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > -			pos->vc_start_slot -= payload->time_slots;
> > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > +			pos->vc_start_slot -= old_payload->time_slots;
> > >  	}
> > > -	payload->vc_start_slot = -1;
> > > +	new_payload->vc_start_slot = -1;
> > >  
> > >  	mgr->payload_count--;
> > > -	mgr->next_start_slot -= payload->time_slots;
> > > +	mgr->next_start_slot -= old_payload->time_slots;
> > >  
> > > -	if (payload->delete)
> > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > +	if (new_payload->delete)
> > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  		to_intel_connector(old_conn_state->connector);
> > >  	struct drm_dp_mst_topology_state *mst_state =
> > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > +	struct drm_dp_mst_atomic_payload *payload =
> > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > >  
> > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  	intel_hdcp_disable(intel_mst->connector);
> > >  
> > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > +			      payload, payload);
> > >  
> > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > >  }
> > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > index edcb2529b4025..ed9d374147b8d 100644
> > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > >  
> > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > >  	if (msto->disabled) {
> > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > >  
> > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > >  	} else {
> > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > >  			     struct drm_dp_mst_atomic_payload *payload);
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > >  
> > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > >  
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-07  0:42         ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-07  0:42 UTC (permalink / raw)
  To: imre.deak
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> 
> Yes, this patch should have no functional change, so please check what
> would apply to other drivers as well.
> 
> Could you also check Ville's comment about storing start_slot elsewhere
> than the atomic state (leaving only time_slots there). I wonder if that
> would work, at least it would simplify things I think.

Ideally it'd be nice if we could have all this info in the atomic commit, but
yeah - you're not the first person to find this a bit confusing. FWIW though,
the way we store start_slot right now is intended to follow the same kind of
behavior we have with atomic CRTC commit dependencies, I think I also made it
that way so all of the state would be in a single place but there's no hard
requirement for it.

So if you guys think it'd be better design-wise to store this something else,
I've got no strong feelings either way
> 
> > For 0-2:
> > 
> > Reviewed-by: Lyude Paul <lyude@redhat.com>
> 
> Thanks.
> 
> > 
> > > 
> > > Cc: Lyude Paul <lyude@redhat.com>
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > Cc: Karol Herbst <kherbst@redhat.com>
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > Cc: stable@vger.kernel.org # 6.1
> > > Cc: dri-devel@lists.freedesktop.org
> > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > index a50319fc42b11..180d3893b68da 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > >  	if (enable)
> > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > >  	else
> > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > >  
> > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   * drm_dp_remove_payload() - Remove an MST payload
> > >   * @mgr: Manager to use.
> > >   * @mst_state: The MST atomic state
> > > - * @payload: The payload to write
> > > + * @old_payload: The payload with its old state
> > > + * @new_payload: The payload to write
> > >   *
> > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   */
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > >  {
> > >  	struct drm_dp_mst_atomic_payload *pos;
> > >  	bool send_remove = false;
> > >  
> > >  	/* We failed to make the payload, so nothing to do */
> > > -	if (payload->vc_start_slot == -1)
> > > +	if (new_payload->vc_start_slot == -1)
> > >  		return;
> > >  
> > >  	mutex_lock(&mgr->lock);
> > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > >  	mutex_unlock(&mgr->lock);
> > >  
> > >  	if (send_remove)
> > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > >  	else
> > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > -			    payload->vcpi);
> > > +			    new_payload->vcpi);
> > >  
> > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > -			pos->vc_start_slot -= payload->time_slots;
> > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > +			pos->vc_start_slot -= old_payload->time_slots;
> > >  	}
> > > -	payload->vc_start_slot = -1;
> > > +	new_payload->vc_start_slot = -1;
> > >  
> > >  	mgr->payload_count--;
> > > -	mgr->next_start_slot -= payload->time_slots;
> > > +	mgr->next_start_slot -= old_payload->time_slots;
> > >  
> > > -	if (payload->delete)
> > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > +	if (new_payload->delete)
> > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  		to_intel_connector(old_conn_state->connector);
> > >  	struct drm_dp_mst_topology_state *mst_state =
> > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > +	struct drm_dp_mst_atomic_payload *payload =
> > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > >  
> > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  	intel_hdcp_disable(intel_mst->connector);
> > >  
> > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > +			      payload, payload);
> > >  
> > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > >  }
> > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > index edcb2529b4025..ed9d374147b8d 100644
> > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > >  
> > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > >  	if (msto->disabled) {
> > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > >  
> > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > >  	} else {
> > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > >  			     struct drm_dp_mst_atomic_payload *payload);
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > >  
> > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > >  
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-07  0:42         ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-07  0:42 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> 
> Yes, this patch should have no functional change, so please check what
> would apply to other drivers as well.
> 
> Could you also check Ville's comment about storing start_slot elsewhere
> than the atomic state (leaving only time_slots there). I wonder if that
> would work, at least it would simplify things I think.

Ideally it'd be nice if we could have all this info in the atomic commit, but
yeah - you're not the first person to find this a bit confusing. FWIW though,
the way we store start_slot right now is intended to follow the same kind of
behavior we have with atomic CRTC commit dependencies, I think I also made it
that way so all of the state would be in a single place but there's no hard
requirement for it.

So if you guys think it'd be better design-wise to store this something else,
I've got no strong feelings either way
> 
> > For 0-2:
> > 
> > Reviewed-by: Lyude Paul <lyude@redhat.com>
> 
> Thanks.
> 
> > 
> > > 
> > > Cc: Lyude Paul <lyude@redhat.com>
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > Cc: Karol Herbst <kherbst@redhat.com>
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > Cc: stable@vger.kernel.org # 6.1
> > > Cc: dri-devel@lists.freedesktop.org
> > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > index a50319fc42b11..180d3893b68da 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > >  	if (enable)
> > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > >  	else
> > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > >  
> > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   * drm_dp_remove_payload() - Remove an MST payload
> > >   * @mgr: Manager to use.
> > >   * @mst_state: The MST atomic state
> > > - * @payload: The payload to write
> > > + * @old_payload: The payload with its old state
> > > + * @new_payload: The payload to write
> > >   *
> > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > >   */
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > >  {
> > >  	struct drm_dp_mst_atomic_payload *pos;
> > >  	bool send_remove = false;
> > >  
> > >  	/* We failed to make the payload, so nothing to do */
> > > -	if (payload->vc_start_slot == -1)
> > > +	if (new_payload->vc_start_slot == -1)
> > >  		return;
> > >  
> > >  	mutex_lock(&mgr->lock);
> > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > >  	mutex_unlock(&mgr->lock);
> > >  
> > >  	if (send_remove)
> > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > >  	else
> > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > -			    payload->vcpi);
> > > +			    new_payload->vcpi);
> > >  
> > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > -			pos->vc_start_slot -= payload->time_slots;
> > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > +			pos->vc_start_slot -= old_payload->time_slots;
> > >  	}
> > > -	payload->vc_start_slot = -1;
> > > +	new_payload->vc_start_slot = -1;
> > >  
> > >  	mgr->payload_count--;
> > > -	mgr->next_start_slot -= payload->time_slots;
> > > +	mgr->next_start_slot -= old_payload->time_slots;
> > >  
> > > -	if (payload->delete)
> > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > +	if (new_payload->delete)
> > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  		to_intel_connector(old_conn_state->connector);
> > >  	struct drm_dp_mst_topology_state *mst_state =
> > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > +	struct drm_dp_mst_atomic_payload *payload =
> > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > >  
> > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > >  	intel_hdcp_disable(intel_mst->connector);
> > >  
> > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > +			      payload, payload);
> > >  
> > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > >  }
> > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > index edcb2529b4025..ed9d374147b8d 100644
> > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > >  
> > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > >  	if (msto->disabled) {
> > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > >  
> > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > >  	} else {
> > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > >  			     struct drm_dp_mst_atomic_payload *payload);
> > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > >  
> > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > >  
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-02-07  0:42         ` Lyude Paul
  (?)
@ 2023-02-07 12:11           ` Imre Deak
  -1 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-07 12:11 UTC (permalink / raw)
  To: Lyude Paul
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > 
> > Yes, this patch should have no functional change, so please check what
> > would apply to other drivers as well.
> > 
> > Could you also check Ville's comment about storing start_slot elsewhere
> > than the atomic state (leaving only time_slots there). I wonder if that
> > would work, at least it would simplify things I think.
> 
> Ideally it'd be nice if we could have all this info in the atomic commit, but
> yeah - you're not the first person to find this a bit confusing. FWIW though,
> the way we store start_slot right now is intended to follow the same kind of
> behavior we have with atomic CRTC commit dependencies, I think I also made it
> that way so all of the state would be in a single place but there's no hard
> requirement for it.

As I understood the atomic state should be precomputed during atomic
check and not changed later during the commit phase. In case of
start_slot this would mean knowing in advance the actual (driver
specific) disabling / enabling sequence of the payloads, not sure how
feasible it is to figure that out. start_slot also changes dynamically
as each payload is disabled, so these intermediate versions of the field
would need to be tracked somehow separately from the final (precomputed)
versions.

> So if you guys think it'd be better design-wise to store this something else,
> I've got no strong feelings either way
> > 
> > > For 0-2:
> > > 
> > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > 
> > Thanks.
> > 
> > > 
> > > > 
> > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > Cc: stable@vger.kernel.org # 6.1
> > > > Cc: dri-devel@lists.freedesktop.org
> > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > index a50319fc42b11..180d3893b68da 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > >  	if (enable)
> > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > >  	else
> > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > >  
> > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > >   * @mgr: Manager to use.
> > > >   * @mst_state: The MST atomic state
> > > > - * @payload: The payload to write
> > > > + * @old_payload: The payload with its old state
> > > > + * @new_payload: The payload to write
> > > >   *
> > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   */
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > >  {
> > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > >  	bool send_remove = false;
> > > >  
> > > >  	/* We failed to make the payload, so nothing to do */
> > > > -	if (payload->vc_start_slot == -1)
> > > > +	if (new_payload->vc_start_slot == -1)
> > > >  		return;
> > > >  
> > > >  	mutex_lock(&mgr->lock);
> > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > >  	mutex_unlock(&mgr->lock);
> > > >  
> > > >  	if (send_remove)
> > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > >  	else
> > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > -			    payload->vcpi);
> > > > +			    new_payload->vcpi);
> > > >  
> > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > >  	}
> > > > -	payload->vc_start_slot = -1;
> > > > +	new_payload->vc_start_slot = -1;
> > > >  
> > > >  	mgr->payload_count--;
> > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > >  
> > > > -	if (payload->delete)
> > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > +	if (new_payload->delete)
> > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > >  }
> > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  		to_intel_connector(old_conn_state->connector);
> > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > >  
> > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  	intel_hdcp_disable(intel_mst->connector);
> > > >  
> > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > +			      payload, payload);
> > > >  
> > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > >  }
> > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > >  
> > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > >  	if (msto->disabled) {
> > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > >  
> > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > >  	} else {
> > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > >  
> > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > >  
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-07 12:11           ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-07 12:11 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > 
> > Yes, this patch should have no functional change, so please check what
> > would apply to other drivers as well.
> > 
> > Could you also check Ville's comment about storing start_slot elsewhere
> > than the atomic state (leaving only time_slots there). I wonder if that
> > would work, at least it would simplify things I think.
> 
> Ideally it'd be nice if we could have all this info in the atomic commit, but
> yeah - you're not the first person to find this a bit confusing. FWIW though,
> the way we store start_slot right now is intended to follow the same kind of
> behavior we have with atomic CRTC commit dependencies, I think I also made it
> that way so all of the state would be in a single place but there's no hard
> requirement for it.

As I understood the atomic state should be precomputed during atomic
check and not changed later during the commit phase. In case of
start_slot this would mean knowing in advance the actual (driver
specific) disabling / enabling sequence of the payloads, not sure how
feasible it is to figure that out. start_slot also changes dynamically
as each payload is disabled, so these intermediate versions of the field
would need to be tracked somehow separately from the final (precomputed)
versions.

> So if you guys think it'd be better design-wise to store this something else,
> I've got no strong feelings either way
> > 
> > > For 0-2:
> > > 
> > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > 
> > Thanks.
> > 
> > > 
> > > > 
> > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > Cc: stable@vger.kernel.org # 6.1
> > > > Cc: dri-devel@lists.freedesktop.org
> > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > index a50319fc42b11..180d3893b68da 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > >  	if (enable)
> > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > >  	else
> > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > >  
> > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > >   * @mgr: Manager to use.
> > > >   * @mst_state: The MST atomic state
> > > > - * @payload: The payload to write
> > > > + * @old_payload: The payload with its old state
> > > > + * @new_payload: The payload to write
> > > >   *
> > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   */
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > >  {
> > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > >  	bool send_remove = false;
> > > >  
> > > >  	/* We failed to make the payload, so nothing to do */
> > > > -	if (payload->vc_start_slot == -1)
> > > > +	if (new_payload->vc_start_slot == -1)
> > > >  		return;
> > > >  
> > > >  	mutex_lock(&mgr->lock);
> > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > >  	mutex_unlock(&mgr->lock);
> > > >  
> > > >  	if (send_remove)
> > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > >  	else
> > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > -			    payload->vcpi);
> > > > +			    new_payload->vcpi);
> > > >  
> > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > >  	}
> > > > -	payload->vc_start_slot = -1;
> > > > +	new_payload->vc_start_slot = -1;
> > > >  
> > > >  	mgr->payload_count--;
> > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > >  
> > > > -	if (payload->delete)
> > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > +	if (new_payload->delete)
> > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > >  }
> > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  		to_intel_connector(old_conn_state->connector);
> > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > >  
> > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  	intel_hdcp_disable(intel_mst->connector);
> > > >  
> > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > +			      payload, payload);
> > > >  
> > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > >  }
> > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > >  
> > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > >  	if (msto->disabled) {
> > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > >  
> > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > >  	} else {
> > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > >  
> > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > >  
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-07 12:11           ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-07 12:11 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > 
> > Yes, this patch should have no functional change, so please check what
> > would apply to other drivers as well.
> > 
> > Could you also check Ville's comment about storing start_slot elsewhere
> > than the atomic state (leaving only time_slots there). I wonder if that
> > would work, at least it would simplify things I think.
> 
> Ideally it'd be nice if we could have all this info in the atomic commit, but
> yeah - you're not the first person to find this a bit confusing. FWIW though,
> the way we store start_slot right now is intended to follow the same kind of
> behavior we have with atomic CRTC commit dependencies, I think I also made it
> that way so all of the state would be in a single place but there's no hard
> requirement for it.

As I understood the atomic state should be precomputed during atomic
check and not changed later during the commit phase. In case of
start_slot this would mean knowing in advance the actual (driver
specific) disabling / enabling sequence of the payloads, not sure how
feasible it is to figure that out. start_slot also changes dynamically
as each payload is disabled, so these intermediate versions of the field
would need to be tracked somehow separately from the final (precomputed)
versions.

> So if you guys think it'd be better design-wise to store this something else,
> I've got no strong feelings either way
> > 
> > > For 0-2:
> > > 
> > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > 
> > Thanks.
> > 
> > > 
> > > > 
> > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > Cc: stable@vger.kernel.org # 6.1
> > > > Cc: dri-devel@lists.freedesktop.org
> > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > index a50319fc42b11..180d3893b68da 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > >  	if (enable)
> > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > >  	else
> > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > >  
> > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > >   * @mgr: Manager to use.
> > > >   * @mst_state: The MST atomic state
> > > > - * @payload: The payload to write
> > > > + * @old_payload: The payload with its old state
> > > > + * @new_payload: The payload to write
> > > >   *
> > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > >   */
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > >  {
> > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > >  	bool send_remove = false;
> > > >  
> > > >  	/* We failed to make the payload, so nothing to do */
> > > > -	if (payload->vc_start_slot == -1)
> > > > +	if (new_payload->vc_start_slot == -1)
> > > >  		return;
> > > >  
> > > >  	mutex_lock(&mgr->lock);
> > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > >  	mutex_unlock(&mgr->lock);
> > > >  
> > > >  	if (send_remove)
> > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > >  	else
> > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > -			    payload->vcpi);
> > > > +			    new_payload->vcpi);
> > > >  
> > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > >  	}
> > > > -	payload->vc_start_slot = -1;
> > > > +	new_payload->vc_start_slot = -1;
> > > >  
> > > >  	mgr->payload_count--;
> > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > >  
> > > > -	if (payload->delete)
> > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > +	if (new_payload->delete)
> > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > >  }
> > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  		to_intel_connector(old_conn_state->connector);
> > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > >  
> > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > >  	intel_hdcp_disable(intel_mst->connector);
> > > >  
> > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > +			      payload, payload);
> > > >  
> > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > >  }
> > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > >  
> > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > >  	if (msto->disabled) {
> > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > >  
> > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > >  	} else {
> > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > >  
> > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > >  
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-02-07 12:11           ` Imre Deak
  (?)
@ 2023-02-08  0:21             ` Lyude Paul
  -1 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-08  0:21 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > 
> > > Yes, this patch should have no functional change, so please check what
> > > would apply to other drivers as well.
> > > 
> > > Could you also check Ville's comment about storing start_slot elsewhere
> > > than the atomic state (leaving only time_slots there). I wonder if that
> > > would work, at least it would simplify things I think.
> > 
> > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > the way we store start_slot right now is intended to follow the same kind of
> > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > that way so all of the state would be in a single place but there's no hard
> > requirement for it.
> 
> As I understood the atomic state should be precomputed during atomic
> check and not changed later during the commit phase. In case of
> start_slot this would mean knowing in advance the actual (driver
> specific) disabling / enabling sequence of the payloads, not sure how
> feasible it is to figure that out. start_slot also changes dynamically

It isn't feasible afaict, which was the main motivation for having the strange
update procedure - this is pretty much something that needs to be determined
at commit time.

> as each payload is disabled, so these intermediate versions of the field
> would need to be tracked somehow separately from the final (precomputed)
> versions.

FWIW, the current way this works is that we call
drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
currently writing to the start_slot field (remember, at this point we may not
have atomic locks held anymore). Then at that point, start_slot in the new
atomic state should hold the current in-hw start_slot value. start_slot isn't
actually set to the new starting slot until drm_dp_add_payload_part1(). That
of course as you pointed out, doesn't help us unless we read all of the
start_slot values before we start changing payloads - since disabling payloads
inevitably changes the start slot of payloads that come afterwards.

I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
reason I assumed this was OK when writing this code was that since we're
updating one payload at a time, ACT, repeat, that the start slots of each
payload in hardware _would_ actually change in the same way we modify them in
helpers. e.g., my expectation was if we had a bunch of payloads like this:

Payload #1: 15 slots, start_slot=0
Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

And then disabled say, payload #1, that immediately after we get the ACT that
the payload table in hardware would look like this:

Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

But it sounds like it actually would look like this in the real world?

Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

So I'm curious, is there something I missed here? At what point does the MST
hub at the other end decide that it's time to move the start slots back? (keep
in mind, the MST specification does explicitly mention that there should never
be holes in the payload table - so something has to be shifting the payloads
back).

> 
> > So if you guys think it'd be better design-wise to store this something else,
> > I've got no strong feelings either way
> > > 
> > > > For 0-2:
> > > > 
> > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > 
> > > Thanks.
> > > 
> > > > 
> > > > > 
> > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > >  	if (enable)
> > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > >  	else
> > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > >  
> > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > >   * @mgr: Manager to use.
> > > > >   * @mst_state: The MST atomic state
> > > > > - * @payload: The payload to write
> > > > > + * @old_payload: The payload with its old state
> > > > > + * @new_payload: The payload to write
> > > > >   *
> > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   */
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > >  {
> > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > >  	bool send_remove = false;
> > > > >  
> > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > -	if (payload->vc_start_slot == -1)
> > > > > +	if (new_payload->vc_start_slot == -1)
> > > > >  		return;
> > > > >  
> > > > >  	mutex_lock(&mgr->lock);
> > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > >  	mutex_unlock(&mgr->lock);
> > > > >  
> > > > >  	if (send_remove)
> > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > >  	else
> > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > -			    payload->vcpi);
> > > > > +			    new_payload->vcpi);
> > > > >  
> > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > >  	}
> > > > > -	payload->vc_start_slot = -1;
> > > > > +	new_payload->vc_start_slot = -1;
> > > > >  
> > > > >  	mgr->payload_count--;
> > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > >  
> > > > > -	if (payload->delete)
> > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > +	if (new_payload->delete)
> > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > >  }
> > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  		to_intel_connector(old_conn_state->connector);
> > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > >  
> > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > >  
> > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > +			      payload, payload);
> > > > >  
> > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > >  }
> > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > >  
> > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > >  	if (msto->disabled) {
> > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > >  
> > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > >  	} else {
> > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > >  
> > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > >  
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-08  0:21             ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-08  0:21 UTC (permalink / raw)
  To: imre.deak
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > 
> > > Yes, this patch should have no functional change, so please check what
> > > would apply to other drivers as well.
> > > 
> > > Could you also check Ville's comment about storing start_slot elsewhere
> > > than the atomic state (leaving only time_slots there). I wonder if that
> > > would work, at least it would simplify things I think.
> > 
> > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > the way we store start_slot right now is intended to follow the same kind of
> > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > that way so all of the state would be in a single place but there's no hard
> > requirement for it.
> 
> As I understood the atomic state should be precomputed during atomic
> check and not changed later during the commit phase. In case of
> start_slot this would mean knowing in advance the actual (driver
> specific) disabling / enabling sequence of the payloads, not sure how
> feasible it is to figure that out. start_slot also changes dynamically

It isn't feasible afaict, which was the main motivation for having the strange
update procedure - this is pretty much something that needs to be determined
at commit time.

> as each payload is disabled, so these intermediate versions of the field
> would need to be tracked somehow separately from the final (precomputed)
> versions.

FWIW, the current way this works is that we call
drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
currently writing to the start_slot field (remember, at this point we may not
have atomic locks held anymore). Then at that point, start_slot in the new
atomic state should hold the current in-hw start_slot value. start_slot isn't
actually set to the new starting slot until drm_dp_add_payload_part1(). That
of course as you pointed out, doesn't help us unless we read all of the
start_slot values before we start changing payloads - since disabling payloads
inevitably changes the start slot of payloads that come afterwards.

I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
reason I assumed this was OK when writing this code was that since we're
updating one payload at a time, ACT, repeat, that the start slots of each
payload in hardware _would_ actually change in the same way we modify them in
helpers. e.g., my expectation was if we had a bunch of payloads like this:

Payload #1: 15 slots, start_slot=0
Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

And then disabled say, payload #1, that immediately after we get the ACT that
the payload table in hardware would look like this:

Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

But it sounds like it actually would look like this in the real world?

Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

So I'm curious, is there something I missed here? At what point does the MST
hub at the other end decide that it's time to move the start slots back? (keep
in mind, the MST specification does explicitly mention that there should never
be holes in the payload table - so something has to be shifting the payloads
back).

> 
> > So if you guys think it'd be better design-wise to store this something else,
> > I've got no strong feelings either way
> > > 
> > > > For 0-2:
> > > > 
> > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > 
> > > Thanks.
> > > 
> > > > 
> > > > > 
> > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > >  	if (enable)
> > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > >  	else
> > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > >  
> > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > >   * @mgr: Manager to use.
> > > > >   * @mst_state: The MST atomic state
> > > > > - * @payload: The payload to write
> > > > > + * @old_payload: The payload with its old state
> > > > > + * @new_payload: The payload to write
> > > > >   *
> > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   */
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > >  {
> > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > >  	bool send_remove = false;
> > > > >  
> > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > -	if (payload->vc_start_slot == -1)
> > > > > +	if (new_payload->vc_start_slot == -1)
> > > > >  		return;
> > > > >  
> > > > >  	mutex_lock(&mgr->lock);
> > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > >  	mutex_unlock(&mgr->lock);
> > > > >  
> > > > >  	if (send_remove)
> > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > >  	else
> > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > -			    payload->vcpi);
> > > > > +			    new_payload->vcpi);
> > > > >  
> > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > >  	}
> > > > > -	payload->vc_start_slot = -1;
> > > > > +	new_payload->vc_start_slot = -1;
> > > > >  
> > > > >  	mgr->payload_count--;
> > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > >  
> > > > > -	if (payload->delete)
> > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > +	if (new_payload->delete)
> > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > >  }
> > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  		to_intel_connector(old_conn_state->connector);
> > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > >  
> > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > >  
> > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > +			      payload, payload);
> > > > >  
> > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > >  }
> > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > >  
> > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > >  	if (msto->disabled) {
> > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > >  
> > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > >  	} else {
> > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > >  
> > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > >  
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-08  0:21             ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-08  0:21 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > 
> > > Yes, this patch should have no functional change, so please check what
> > > would apply to other drivers as well.
> > > 
> > > Could you also check Ville's comment about storing start_slot elsewhere
> > > than the atomic state (leaving only time_slots there). I wonder if that
> > > would work, at least it would simplify things I think.
> > 
> > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > the way we store start_slot right now is intended to follow the same kind of
> > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > that way so all of the state would be in a single place but there's no hard
> > requirement for it.
> 
> As I understood the atomic state should be precomputed during atomic
> check and not changed later during the commit phase. In case of
> start_slot this would mean knowing in advance the actual (driver
> specific) disabling / enabling sequence of the payloads, not sure how
> feasible it is to figure that out. start_slot also changes dynamically

It isn't feasible afaict, which was the main motivation for having the strange
update procedure - this is pretty much something that needs to be determined
at commit time.

> as each payload is disabled, so these intermediate versions of the field
> would need to be tracked somehow separately from the final (precomputed)
> versions.

FWIW, the current way this works is that we call
drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
currently writing to the start_slot field (remember, at this point we may not
have atomic locks held anymore). Then at that point, start_slot in the new
atomic state should hold the current in-hw start_slot value. start_slot isn't
actually set to the new starting slot until drm_dp_add_payload_part1(). That
of course as you pointed out, doesn't help us unless we read all of the
start_slot values before we start changing payloads - since disabling payloads
inevitably changes the start slot of payloads that come afterwards.

I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
reason I assumed this was OK when writing this code was that since we're
updating one payload at a time, ACT, repeat, that the start slots of each
payload in hardware _would_ actually change in the same way we modify them in
helpers. e.g., my expectation was if we had a bunch of payloads like this:

Payload #1: 15 slots, start_slot=0
Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

And then disabled say, payload #1, that immediately after we get the ACT that
the payload table in hardware would look like this:

Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

But it sounds like it actually would look like this in the real world?

Payload #2: 15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30

So I'm curious, is there something I missed here? At what point does the MST
hub at the other end decide that it's time to move the start slots back? (keep
in mind, the MST specification does explicitly mention that there should never
be holes in the payload table - so something has to be shifting the payloads
back).

> 
> > So if you guys think it'd be better design-wise to store this something else,
> > I've got no strong feelings either way
> > > 
> > > > For 0-2:
> > > > 
> > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > 
> > > Thanks.
> > > 
> > > > 
> > > > > 
> > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > >  	if (enable)
> > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > >  	else
> > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > >  
> > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > >   * @mgr: Manager to use.
> > > > >   * @mst_state: The MST atomic state
> > > > > - * @payload: The payload to write
> > > > > + * @old_payload: The payload with its old state
> > > > > + * @new_payload: The payload to write
> > > > >   *
> > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > >   */
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > >  {
> > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > >  	bool send_remove = false;
> > > > >  
> > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > -	if (payload->vc_start_slot == -1)
> > > > > +	if (new_payload->vc_start_slot == -1)
> > > > >  		return;
> > > > >  
> > > > >  	mutex_lock(&mgr->lock);
> > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > >  	mutex_unlock(&mgr->lock);
> > > > >  
> > > > >  	if (send_remove)
> > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > >  	else
> > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > -			    payload->vcpi);
> > > > > +			    new_payload->vcpi);
> > > > >  
> > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > >  	}
> > > > > -	payload->vc_start_slot = -1;
> > > > > +	new_payload->vc_start_slot = -1;
> > > > >  
> > > > >  	mgr->payload_count--;
> > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > >  
> > > > > -	if (payload->delete)
> > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > +	if (new_payload->delete)
> > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > >  }
> > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  		to_intel_connector(old_conn_state->connector);
> > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > >  
> > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > >  
> > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > +			      payload, payload);
> > > > >  
> > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > >  }
> > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > >  
> > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > >  	if (msto->disabled) {
> > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > >  
> > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > >  	} else {
> > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > >  
> > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > >  
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-02-08  0:21             ` Lyude Paul
  (?)
@ 2023-02-08  7:41               ` Imre Deak
  -1 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-08  7:41 UTC (permalink / raw)
  To: Lyude Paul
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > > 
> > > > Yes, this patch should have no functional change, so please check what
> > > > would apply to other drivers as well.
> > > > 
> > > > Could you also check Ville's comment about storing start_slot elsewhere
> > > > than the atomic state (leaving only time_slots there). I wonder if that
> > > > would work, at least it would simplify things I think.
> > > 
> > > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > > the way we store start_slot right now is intended to follow the same kind of
> > > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > > that way so all of the state would be in a single place but there's no hard
> > > requirement for it.
> > 
> > As I understood the atomic state should be precomputed during atomic
> > check and not changed later during the commit phase. In case of
> > start_slot this would mean knowing in advance the actual (driver
> > specific) disabling / enabling sequence of the payloads, not sure how
> > feasible it is to figure that out. start_slot also changes dynamically
> 
> It isn't feasible afaict, which was the main motivation for having the strange
> update procedure - this is pretty much something that needs to be determined
> at commit time.
>
> > as each payload is disabled, so these intermediate versions of the field
> > would need to be tracked somehow separately from the final (precomputed)
> > versions.
> 
> FWIW, the current way this works is that we call
> drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
> currently writing to the start_slot field (remember, at this point we may not
> have atomic locks held anymore). Then at that point, start_slot in the new
> atomic state should hold the current in-hw start_slot value. start_slot isn't
> actually set to the new starting slot until drm_dp_add_payload_part1(). That
> of course as you pointed out, doesn't help us unless we read all of the
> start_slot values before we start changing payloads - since disabling payloads
> inevitably changes the start slot of payloads that come afterwards.
> 
> I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
> reason I assumed this was OK when writing this code was that since we're
> updating one payload at a time, ACT, repeat, that the start slots of each
> payload in hardware _would_ actually change in the same way we modify them in
> helpers. e.g., my expectation was if we had a bunch of payloads like this:
> 
> Payload #1: 15 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30
> 
> And then disabled say, payload #1, that immediately after we get the ACT that
> the payload table in hardware would look like this:
> 
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15

The above is the actual and expected HW state state yes.

> But it sounds like it actually would look like this in the real world?
> 
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30

No, the problem currently is not that start_slot of the subsequent
payloads are not shifted towards the beginning. Rather the atomic state
doesn't get updated properly, becoming out of sync with the HW. For
instance in a commit resizing payload #1, in the commit phase
(intel_atomic_commit_tail()) will begin by removing payload #1. The
initial state is

            old payload state         new payload state
Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30

mgr->next_start_slot = 45

intel_mst_disable_dp() will pass the old MST and payload state to
drm_dp_remove_payload(): The MST state was added during atomic check,
since payload #1 changed, then intel_atomic_commit() ->
drm_atomic_helper_swap_state() sets the MST current state (returned by
drm_atomic_get_mst_topology_state()) to point to the old state. So at
the point drm_dp_remove_payload() returns we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 30

then after re-enabling payload #1, after drm_dp_add_payload_part1()
returns (passing to it the new MST and payload state) we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 50

So in the new SW state payload #1 and #3 incorrectly overlap, with the
actual HW state being:

Payload #1: 20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

A subsequent commit will see the wrong start_slot in the SW state for
payload #2 (15) and #3 (30).

> So I'm curious, is there something I missed here? At what point does the MST
> hub at the other end decide that it's time to move the start slots back?

The hub shifts back payloads after the DPCD write command to 0x1c0 -
0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
the point of disabling the stream, in intel_mst_post_disable_dp() ->
intel_disable_transcoder() for i915).

> (keep in mind, the MST specification does explicitly mention that
> there should never be holes in the payload table - so something has to
> be shifting the payloads back).

Right, the hubs I checked conform to this.

> > > So if you guys think it'd be better design-wise to store this something else,
> > > I've got no strong feelings either way
> > > > 
> > > > > For 0-2:
> > > > > 
> > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > 
> > > > Thanks.
> > > > 
> > > > > 
> > > > > > 
> > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > ---
> > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > >  	if (enable)
> > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > >  	else
> > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > >   * @mgr: Manager to use.
> > > > > >   * @mst_state: The MST atomic state
> > > > > > - * @payload: The payload to write
> > > > > > + * @old_payload: The payload with its old state
> > > > > > + * @new_payload: The payload to write
> > > > > >   *
> > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   */
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > >  {
> > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > >  	bool send_remove = false;
> > > > > >  
> > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > >  		return;
> > > > > >  
> > > > > >  	mutex_lock(&mgr->lock);
> > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > >  	mutex_unlock(&mgr->lock);
> > > > > >  
> > > > > >  	if (send_remove)
> > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > >  	else
> > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > -			    payload->vcpi);
> > > > > > +			    new_payload->vcpi);
> > > > > >  
> > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > >  	}
> > > > > > -	payload->vc_start_slot = -1;
> > > > > > +	new_payload->vc_start_slot = -1;
> > > > > >  
> > > > > >  	mgr->payload_count--;
> > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > >  
> > > > > > -	if (payload->delete)
> > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > +	if (new_payload->delete)
> > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > >  
> > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > >  
> > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > +			      payload, payload);
> > > > > >  
> > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > >  }
> > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > >  
> > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > >  	if (msto->disabled) {
> > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > >  	} else {
> > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > >  
> > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > >  
> > > > > 
> > > > > -- 
> > > > > Cheers,
> > > > >  Lyude Paul (she/her)
> > > > >  Software Engineer at Red Hat
> > > > > 
> > > > 
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-08  7:41               ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-08  7:41 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > > 
> > > > Yes, this patch should have no functional change, so please check what
> > > > would apply to other drivers as well.
> > > > 
> > > > Could you also check Ville's comment about storing start_slot elsewhere
> > > > than the atomic state (leaving only time_slots there). I wonder if that
> > > > would work, at least it would simplify things I think.
> > > 
> > > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > > the way we store start_slot right now is intended to follow the same kind of
> > > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > > that way so all of the state would be in a single place but there's no hard
> > > requirement for it.
> > 
> > As I understood the atomic state should be precomputed during atomic
> > check and not changed later during the commit phase. In case of
> > start_slot this would mean knowing in advance the actual (driver
> > specific) disabling / enabling sequence of the payloads, not sure how
> > feasible it is to figure that out. start_slot also changes dynamically
> 
> It isn't feasible afaict, which was the main motivation for having the strange
> update procedure - this is pretty much something that needs to be determined
> at commit time.
>
> > as each payload is disabled, so these intermediate versions of the field
> > would need to be tracked somehow separately from the final (precomputed)
> > versions.
> 
> FWIW, the current way this works is that we call
> drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
> currently writing to the start_slot field (remember, at this point we may not
> have atomic locks held anymore). Then at that point, start_slot in the new
> atomic state should hold the current in-hw start_slot value. start_slot isn't
> actually set to the new starting slot until drm_dp_add_payload_part1(). That
> of course as you pointed out, doesn't help us unless we read all of the
> start_slot values before we start changing payloads - since disabling payloads
> inevitably changes the start slot of payloads that come afterwards.
> 
> I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
> reason I assumed this was OK when writing this code was that since we're
> updating one payload at a time, ACT, repeat, that the start slots of each
> payload in hardware _would_ actually change in the same way we modify them in
> helpers. e.g., my expectation was if we had a bunch of payloads like this:
> 
> Payload #1: 15 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30
> 
> And then disabled say, payload #1, that immediately after we get the ACT that
> the payload table in hardware would look like this:
> 
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15

The above is the actual and expected HW state state yes.

> But it sounds like it actually would look like this in the real world?
> 
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30

No, the problem currently is not that start_slot of the subsequent
payloads are not shifted towards the beginning. Rather the atomic state
doesn't get updated properly, becoming out of sync with the HW. For
instance in a commit resizing payload #1, in the commit phase
(intel_atomic_commit_tail()) will begin by removing payload #1. The
initial state is

            old payload state         new payload state
Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30

mgr->next_start_slot = 45

intel_mst_disable_dp() will pass the old MST and payload state to
drm_dp_remove_payload(): The MST state was added during atomic check,
since payload #1 changed, then intel_atomic_commit() ->
drm_atomic_helper_swap_state() sets the MST current state (returned by
drm_atomic_get_mst_topology_state()) to point to the old state. So at
the point drm_dp_remove_payload() returns we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 30

then after re-enabling payload #1, after drm_dp_add_payload_part1()
returns (passing to it the new MST and payload state) we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 50

So in the new SW state payload #1 and #3 incorrectly overlap, with the
actual HW state being:

Payload #1: 20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

A subsequent commit will see the wrong start_slot in the SW state for
payload #2 (15) and #3 (30).

> So I'm curious, is there something I missed here? At what point does the MST
> hub at the other end decide that it's time to move the start slots back?

The hub shifts back payloads after the DPCD write command to 0x1c0 -
0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
the point of disabling the stream, in intel_mst_post_disable_dp() ->
intel_disable_transcoder() for i915).

> (keep in mind, the MST specification does explicitly mention that
> there should never be holes in the payload table - so something has to
> be shifting the payloads back).

Right, the hubs I checked conform to this.

> > > So if you guys think it'd be better design-wise to store this something else,
> > > I've got no strong feelings either way
> > > > 
> > > > > For 0-2:
> > > > > 
> > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > 
> > > > Thanks.
> > > > 
> > > > > 
> > > > > > 
> > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > ---
> > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > >  	if (enable)
> > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > >  	else
> > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > >   * @mgr: Manager to use.
> > > > > >   * @mst_state: The MST atomic state
> > > > > > - * @payload: The payload to write
> > > > > > + * @old_payload: The payload with its old state
> > > > > > + * @new_payload: The payload to write
> > > > > >   *
> > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   */
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > >  {
> > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > >  	bool send_remove = false;
> > > > > >  
> > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > >  		return;
> > > > > >  
> > > > > >  	mutex_lock(&mgr->lock);
> > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > >  	mutex_unlock(&mgr->lock);
> > > > > >  
> > > > > >  	if (send_remove)
> > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > >  	else
> > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > -			    payload->vcpi);
> > > > > > +			    new_payload->vcpi);
> > > > > >  
> > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > >  	}
> > > > > > -	payload->vc_start_slot = -1;
> > > > > > +	new_payload->vc_start_slot = -1;
> > > > > >  
> > > > > >  	mgr->payload_count--;
> > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > >  
> > > > > > -	if (payload->delete)
> > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > +	if (new_payload->delete)
> > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > >  
> > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > >  
> > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > +			      payload, payload);
> > > > > >  
> > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > >  }
> > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > >  
> > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > >  	if (msto->disabled) {
> > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > >  	} else {
> > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > >  
> > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > >  
> > > > > 
> > > > > -- 
> > > > > Cheers,
> > > > >  Lyude Paul (she/her)
> > > > >  Software Engineer at Red Hat
> > > > > 
> > > > 
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-08  7:41               ` Imre Deak
  0 siblings, 0 replies; 70+ messages in thread
From: Imre Deak @ 2023-02-08  7:41 UTC (permalink / raw)
  To: Lyude Paul
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > On Mon, Feb 06, 2023 at 07:42:32PM -0500, Lyude Paul wrote:
> > > On Wed, 2023-02-01 at 17:04 +0200, Imre Deak wrote:
> > > > 
> > > > Yes, this patch should have no functional change, so please check what
> > > > would apply to other drivers as well.
> > > > 
> > > > Could you also check Ville's comment about storing start_slot elsewhere
> > > > than the atomic state (leaving only time_slots there). I wonder if that
> > > > would work, at least it would simplify things I think.
> > > 
> > > Ideally it'd be nice if we could have all this info in the atomic commit, but
> > > yeah - you're not the first person to find this a bit confusing. FWIW though,
> > > the way we store start_slot right now is intended to follow the same kind of
> > > behavior we have with atomic CRTC commit dependencies, I think I also made it
> > > that way so all of the state would be in a single place but there's no hard
> > > requirement for it.
> > 
> > As I understood the atomic state should be precomputed during atomic
> > check and not changed later during the commit phase. In case of
> > start_slot this would mean knowing in advance the actual (driver
> > specific) disabling / enabling sequence of the payloads, not sure how
> > feasible it is to figure that out. start_slot also changes dynamically
> 
> It isn't feasible afaict, which was the main motivation for having the strange
> update procedure - this is pretty much something that needs to be determined
> at commit time.
>
> > as each payload is disabled, so these intermediate versions of the field
> > would need to be tracked somehow separately from the final (precomputed)
> > versions.
> 
> FWIW, the current way this works is that we call
> drm_dp_mst_atomic_wait_for_dependencies() in order to ensure that no one's
> currently writing to the start_slot field (remember, at this point we may not
> have atomic locks held anymore). Then at that point, start_slot in the new
> atomic state should hold the current in-hw start_slot value. start_slot isn't
> actually set to the new starting slot until drm_dp_add_payload_part1(). That
> of course as you pointed out, doesn't help us unless we read all of the
> start_slot values before we start changing payloads - since disabling payloads
> inevitably changes the start slot of payloads that come afterwards.
> 
> I'll admit I'm a bit surprised this logic was wrong - if I recall the whole
> reason I assumed this was OK when writing this code was that since we're
> updating one payload at a time, ACT, repeat, that the start slots of each
> payload in hardware _would_ actually change in the same way we modify them in
> helpers. e.g., my expectation was if we had a bunch of payloads like this:
> 
> Payload #1: 15 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30
> 
> And then disabled say, payload #1, that immediately after we get the ACT that
> the payload table in hardware would look like this:
> 
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15

The above is the actual and expected HW state state yes.

> But it sounds like it actually would look like this in the real world?
> 
> Payload #2: 15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30

No, the problem currently is not that start_slot of the subsequent
payloads are not shifted towards the beginning. Rather the atomic state
doesn't get updated properly, becoming out of sync with the HW. For
instance in a commit resizing payload #1, in the commit phase
(intel_atomic_commit_tail()) will begin by removing payload #1. The
initial state is

            old payload state         new payload state
Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30

mgr->next_start_slot = 45

intel_mst_disable_dp() will pass the old MST and payload state to
drm_dp_remove_payload(): The MST state was added during atomic check,
since payload #1 changed, then intel_atomic_commit() ->
drm_atomic_helper_swap_state() sets the MST current state (returned by
drm_atomic_get_mst_topology_state()) to point to the old state. So at
the point drm_dp_remove_payload() returns we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 30

then after re-enabling payload #1, after drm_dp_add_payload_part1()
returns (passing to it the new MST and payload state) we have:

            old payload state         new payload state
Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30

mgr->next_start_slot = 50

So in the new SW state payload #1 and #3 incorrectly overlap, with the
actual HW state being:

Payload #1: 20 slots, start_slot=30
Payload #2: 15 slots, start_slot=0
Payload #3: 15 slots, start_slot=15

A subsequent commit will see the wrong start_slot in the SW state for
payload #2 (15) and #3 (30).

> So I'm curious, is there something I missed here? At what point does the MST
> hub at the other end decide that it's time to move the start slots back?

The hub shifts back payloads after the DPCD write command to 0x1c0 -
0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
the point of disabling the stream, in intel_mst_post_disable_dp() ->
intel_disable_transcoder() for i915).

> (keep in mind, the MST specification does explicitly mention that
> there should never be holes in the payload table - so something has to
> be shifting the payloads back).

Right, the hubs I checked conform to this.

> > > So if you guys think it'd be better design-wise to store this something else,
> > > I've got no strong feelings either way
> > > > 
> > > > > For 0-2:
> > > > > 
> > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > 
> > > > Thanks.
> > > > 
> > > > > 
> > > > > > 
> > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > ---
> > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > >  	if (enable)
> > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > >  	else
> > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > >   * @mgr: Manager to use.
> > > > > >   * @mst_state: The MST atomic state
> > > > > > - * @payload: The payload to write
> > > > > > + * @old_payload: The payload with its old state
> > > > > > + * @new_payload: The payload to write
> > > > > >   *
> > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > >   */
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > >  {
> > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > >  	bool send_remove = false;
> > > > > >  
> > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > >  		return;
> > > > > >  
> > > > > >  	mutex_lock(&mgr->lock);
> > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > >  	mutex_unlock(&mgr->lock);
> > > > > >  
> > > > > >  	if (send_remove)
> > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > >  	else
> > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > -			    payload->vcpi);
> > > > > > +			    new_payload->vcpi);
> > > > > >  
> > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > >  	}
> > > > > > -	payload->vc_start_slot = -1;
> > > > > > +	new_payload->vc_start_slot = -1;
> > > > > >  
> > > > > >  	mgr->payload_count--;
> > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > >  
> > > > > > -	if (payload->delete)
> > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > +	if (new_payload->delete)
> > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > >  
> > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > >  
> > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > >  
> > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > +			      payload, payload);
> > > > > >  
> > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > >  }
> > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > >  
> > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > >  	if (msto->disabled) {
> > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > >  
> > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > >  	} else {
> > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > >  
> > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > >  
> > > > > 
> > > > > -- 
> > > > > Cheers,
> > > > >  Lyude Paul (she/her)
> > > > >  Software Engineer at Red Hat
> > > > > 
> > > > 
> > > 
> > > -- 
> > > Cheers,
> > >  Lyude Paul (she/her)
> > >  Software Engineer at Red Hat
> > > 
> > 
> 
> -- 
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
> 

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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
  2023-02-08  7:41               ` Imre Deak
  (?)
@ 2023-02-09 21:43                 ` Lyude Paul
  -1 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-09 21:43 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher

On Wed, 2023-02-08 at 09:41 +0200, Imre Deak wrote:
> On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> > On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > 
> > And then disabled say, payload #1, that immediately after we get the ACT that
> > the payload table in hardware would look like this:
> > 
> > Payload #2: 15 slots, start_slot=0
> > Payload #3: 15 slots, start_slot=15
> 
> The above is the actual and expected HW state state yes.
> 
> > But it sounds like it actually would look like this in the real world?
> > 
> > Payload #2: 15 slots, start_slot=15
> > Payload #3: 15 slots, start_slot=30
> 
> No, the problem currently is not that start_slot of the subsequent
> payloads are not shifted towards the beginning. Rather the atomic state
> doesn't get updated properly, becoming out of sync with the HW. For
> instance in a commit resizing payload #1, in the commit phase
> (intel_atomic_commit_tail()) will begin by removing payload #1. The
> initial state is
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30
> 
> mgr->next_start_slot = 45
> 
> intel_mst_disable_dp() will pass the old MST and payload state to
> drm_dp_remove_payload(): The MST state was added during atomic check,
> since payload #1 changed, then intel_atomic_commit() ->
> drm_atomic_helper_swap_state() sets the MST current state (returned by
> drm_atomic_get_mst_topology_state()) to point to the old state. So at

OK - this took me a while to wrap my head around but you're completely right.
It appears I totally misunderstood where the state swapping actually happens
during the check -> commit sequence. I think if that's how things work too
then yeah, it definitely might not be a bad idea to move the start slot out of
the atomic state :P. I guess we could just keep this in the mst manager struct
instead of the commit state and make the rules for access be the same: protect
them through commit ordering, and document that the proper way of accessing
start values outside of the context of an atomic commit (if this was needed
for some reason) is:

* grab mst lock
* call drm_dp_mst_atomic_wait_for_dependencies()
* read values under lock

Thank y'all again so much for helping out with this! It is super appreciated,
and once you guys push these patches upstream I will look into adopting this
for nouveau. I already poked some folks from AMD as well to make sure they're
keeping an eye on this (although looking at the Cc I realize they were already
added a while ago, whoops lol). 

> the point drm_dp_remove_payload() returns we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 30
> 
> then after re-enabling payload #1, after drm_dp_add_payload_part1()
> returns (passing to it the new MST and payload state) we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 50
> 
> So in the new SW state payload #1 and #3 incorrectly overlap, with the
> actual HW state being:
> 
> Payload #1: 20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15
> 
> A subsequent commit will see the wrong start_slot in the SW state for
> payload #2 (15) and #3 (30).
> 
> > So I'm curious, is there something I missed here? At what point does the MST
> > hub at the other end decide that it's time to move the start slots back?
> 
> The hub shifts back payloads after the DPCD write command to 0x1c0 -
> 0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
> the point of disabling the stream, in intel_mst_post_disable_dp() ->
> intel_disable_transcoder() for i915).
> 
> > (keep in mind, the MST specification does explicitly mention that
> > there should never be holes in the payload table - so something has to
> > be shifting the payloads back).
> 
> Right, the hubs I checked conform to this.

> 
> > > > So if you guys think it'd be better design-wise to store this something else,
> > > > I've got no strong feelings either way
> > > > > 
> > > > > > For 0-2:
> > > > > > 
> > > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > > 
> > > > > Thanks.
> > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > > ---
> > > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > > >  	if (enable)
> > > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > > >  	else
> > > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > > >   * @mgr: Manager to use.
> > > > > > >   * @mst_state: The MST atomic state
> > > > > > > - * @payload: The payload to write
> > > > > > > + * @old_payload: The payload with its old state
> > > > > > > + * @new_payload: The payload to write
> > > > > > >   *
> > > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   */
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > > >  {
> > > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > > >  	bool send_remove = false;
> > > > > > >  
> > > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > > >  		return;
> > > > > > >  
> > > > > > >  	mutex_lock(&mgr->lock);
> > > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > > >  	mutex_unlock(&mgr->lock);
> > > > > > >  
> > > > > > >  	if (send_remove)
> > > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > > >  	else
> > > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > > -			    payload->vcpi);
> > > > > > > +			    new_payload->vcpi);
> > > > > > >  
> > > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > > >  	}
> > > > > > > -	payload->vc_start_slot = -1;
> > > > > > > +	new_payload->vc_start_slot = -1;
> > > > > > >  
> > > > > > >  	mgr->payload_count--;
> > > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > > >  
> > > > > > > -	if (payload->delete)
> > > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > > +	if (new_payload->delete)
> > > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > > >  }
> > > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > > >  
> > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > > >  
> > > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > > >  
> > > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > > +			      payload, payload);
> > > > > > >  
> > > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > > >  }
> > > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > > >  
> > > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > > >  	if (msto->disabled) {
> > > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > > >  	} else {
> > > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > > >  
> > > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > > >  
> > > > > > 
> > > > > > -- 
> > > > > > Cheers,
> > > > > >  Lyude Paul (she/her)
> > > > > >  Software Engineer at Red Hat
> > > > > > 
> > > > > 
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-09 21:43                 ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-09 21:43 UTC (permalink / raw)
  To: imre.deak
  Cc: intel-gfx, Ville Syrjälä,
	Ben Skeggs, Karol Herbst, Harry Wentland, Alex Deucher,
	Wayne Lin, stable, dri-devel

On Wed, 2023-02-08 at 09:41 +0200, Imre Deak wrote:
> On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> > On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > 
> > And then disabled say, payload #1, that immediately after we get the ACT that
> > the payload table in hardware would look like this:
> > 
> > Payload #2: 15 slots, start_slot=0
> > Payload #3: 15 slots, start_slot=15
> 
> The above is the actual and expected HW state state yes.
> 
> > But it sounds like it actually would look like this in the real world?
> > 
> > Payload #2: 15 slots, start_slot=15
> > Payload #3: 15 slots, start_slot=30
> 
> No, the problem currently is not that start_slot of the subsequent
> payloads are not shifted towards the beginning. Rather the atomic state
> doesn't get updated properly, becoming out of sync with the HW. For
> instance in a commit resizing payload #1, in the commit phase
> (intel_atomic_commit_tail()) will begin by removing payload #1. The
> initial state is
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30
> 
> mgr->next_start_slot = 45
> 
> intel_mst_disable_dp() will pass the old MST and payload state to
> drm_dp_remove_payload(): The MST state was added during atomic check,
> since payload #1 changed, then intel_atomic_commit() ->
> drm_atomic_helper_swap_state() sets the MST current state (returned by
> drm_atomic_get_mst_topology_state()) to point to the old state. So at

OK - this took me a while to wrap my head around but you're completely right.
It appears I totally misunderstood where the state swapping actually happens
during the check -> commit sequence. I think if that's how things work too
then yeah, it definitely might not be a bad idea to move the start slot out of
the atomic state :P. I guess we could just keep this in the mst manager struct
instead of the commit state and make the rules for access be the same: protect
them through commit ordering, and document that the proper way of accessing
start values outside of the context of an atomic commit (if this was needed
for some reason) is:

* grab mst lock
* call drm_dp_mst_atomic_wait_for_dependencies()
* read values under lock

Thank y'all again so much for helping out with this! It is super appreciated,
and once you guys push these patches upstream I will look into adopting this
for nouveau. I already poked some folks from AMD as well to make sure they're
keeping an eye on this (although looking at the Cc I realize they were already
added a while ago, whoops lol). 

> the point drm_dp_remove_payload() returns we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 30
> 
> then after re-enabling payload #1, after drm_dp_add_payload_part1()
> returns (passing to it the new MST and payload state) we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 50
> 
> So in the new SW state payload #1 and #3 incorrectly overlap, with the
> actual HW state being:
> 
> Payload #1: 20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15
> 
> A subsequent commit will see the wrong start_slot in the SW state for
> payload #2 (15) and #3 (30).
> 
> > So I'm curious, is there something I missed here? At what point does the MST
> > hub at the other end decide that it's time to move the start slots back?
> 
> The hub shifts back payloads after the DPCD write command to 0x1c0 -
> 0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
> the point of disabling the stream, in intel_mst_post_disable_dp() ->
> intel_disable_transcoder() for i915).
> 
> > (keep in mind, the MST specification does explicitly mention that
> > there should never be holes in the payload table - so something has to
> > be shifting the payloads back).
> 
> Right, the hubs I checked conform to this.

> 
> > > > So if you guys think it'd be better design-wise to store this something else,
> > > > I've got no strong feelings either way
> > > > > 
> > > > > > For 0-2:
> > > > > > 
> > > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > > 
> > > > > Thanks.
> > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > > ---
> > > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > > >  	if (enable)
> > > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > > >  	else
> > > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > > >   * @mgr: Manager to use.
> > > > > > >   * @mst_state: The MST atomic state
> > > > > > > - * @payload: The payload to write
> > > > > > > + * @old_payload: The payload with its old state
> > > > > > > + * @new_payload: The payload to write
> > > > > > >   *
> > > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   */
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > > >  {
> > > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > > >  	bool send_remove = false;
> > > > > > >  
> > > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > > >  		return;
> > > > > > >  
> > > > > > >  	mutex_lock(&mgr->lock);
> > > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > > >  	mutex_unlock(&mgr->lock);
> > > > > > >  
> > > > > > >  	if (send_remove)
> > > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > > >  	else
> > > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > > -			    payload->vcpi);
> > > > > > > +			    new_payload->vcpi);
> > > > > > >  
> > > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > > >  	}
> > > > > > > -	payload->vc_start_slot = -1;
> > > > > > > +	new_payload->vc_start_slot = -1;
> > > > > > >  
> > > > > > >  	mgr->payload_count--;
> > > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > > >  
> > > > > > > -	if (payload->delete)
> > > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > > +	if (new_payload->delete)
> > > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > > >  }
> > > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > > >  
> > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > > >  
> > > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > > >  
> > > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > > +			      payload, payload);
> > > > > > >  
> > > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > > >  }
> > > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > > >  
> > > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > > >  	if (msto->disabled) {
> > > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > > >  	} else {
> > > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > > >  
> > > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > > >  
> > > > > > 
> > > > > > -- 
> > > > > > Cheers,
> > > > > >  Lyude Paul (she/her)
> > > > > >  Software Engineer at Red Hat
> > > > > > 
> > > > > 
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Intel-gfx] [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload()
@ 2023-02-09 21:43                 ` Lyude Paul
  0 siblings, 0 replies; 70+ messages in thread
From: Lyude Paul @ 2023-02-09 21:43 UTC (permalink / raw)
  To: imre.deak
  Cc: dri-devel, Karol Herbst, intel-gfx, stable, Ben Skeggs,
	Wayne Lin, Alex Deucher, Harry Wentland

On Wed, 2023-02-08 at 09:41 +0200, Imre Deak wrote:
> On Tue, Feb 07, 2023 at 07:21:48PM -0500, Lyude Paul wrote:
> > On Tue, 2023-02-07 at 14:11 +0200, Imre Deak wrote:
> > 
> > And then disabled say, payload #1, that immediately after we get the ACT that
> > the payload table in hardware would look like this:
> > 
> > Payload #2: 15 slots, start_slot=0
> > Payload #3: 15 slots, start_slot=15
> 
> The above is the actual and expected HW state state yes.
> 
> > But it sounds like it actually would look like this in the real world?
> > 
> > Payload #2: 15 slots, start_slot=15
> > Payload #3: 15 slots, start_slot=30
> 
> No, the problem currently is not that start_slot of the subsequent
> payloads are not shifted towards the beginning. Rather the atomic state
> doesn't get updated properly, becoming out of sync with the HW. For
> instance in a commit resizing payload #1, in the commit phase
> (intel_atomic_commit_tail()) will begin by removing payload #1. The
> initial state is
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=0    20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=15   15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=30   15 slots, start_slot=30
> 
> mgr->next_start_slot = 45
> 
> intel_mst_disable_dp() will pass the old MST and payload state to
> drm_dp_remove_payload(): The MST state was added during atomic check,
> since payload #1 changed, then intel_atomic_commit() ->
> drm_atomic_helper_swap_state() sets the MST current state (returned by
> drm_atomic_get_mst_topology_state()) to point to the old state. So at

OK - this took me a while to wrap my head around but you're completely right.
It appears I totally misunderstood where the state swapping actually happens
during the check -> commit sequence. I think if that's how things work too
then yeah, it definitely might not be a bad idea to move the start slot out of
the atomic state :P. I guess we could just keep this in the mst manager struct
instead of the commit state and make the rules for access be the same: protect
them through commit ordering, and document that the proper way of accessing
start values outside of the context of an atomic commit (if this was needed
for some reason) is:

* grab mst lock
* call drm_dp_mst_atomic_wait_for_dependencies()
* read values under lock

Thank y'all again so much for helping out with this! It is super appreciated,
and once you guys push these patches upstream I will look into adopting this
for nouveau. I already poked some folks from AMD as well to make sure they're
keeping an eye on this (although looking at the Cc I realize they were already
added a while ago, whoops lol). 

> the point drm_dp_remove_payload() returns we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=0
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 30
> 
> then after re-enabling payload #1, after drm_dp_add_payload_part1()
> returns (passing to it the new MST and payload state) we have:
> 
>             old payload state         new payload state
> Payload #1: 15 slots, start_slot=-1   20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0    15 slots, start_slot=15
> Payload #3: 15 slots, start_slot=15   15 slots, start_slot=30
> 
> mgr->next_start_slot = 50
> 
> So in the new SW state payload #1 and #3 incorrectly overlap, with the
> actual HW state being:
> 
> Payload #1: 20 slots, start_slot=30
> Payload #2: 15 slots, start_slot=0
> Payload #3: 15 slots, start_slot=15
> 
> A subsequent commit will see the wrong start_slot in the SW state for
> payload #2 (15) and #3 (30).
> 
> > So I'm curious, is there something I missed here? At what point does the MST
> > hub at the other end decide that it's time to move the start slots back?
> 
> The hub shifts back payloads after the DPCD write command to 0x1c0 -
> 0x1c2 to remove a payload. (The HW OTOH does the corresponding shift at
> the point of disabling the stream, in intel_mst_post_disable_dp() ->
> intel_disable_transcoder() for i915).
> 
> > (keep in mind, the MST specification does explicitly mention that
> > there should never be holes in the payload table - so something has to
> > be shifting the payloads back).
> 
> Right, the hubs I checked conform to this.

> 
> > > > So if you guys think it'd be better design-wise to store this something else,
> > > > I've got no strong feelings either way
> > > > > 
> > > > > > For 0-2:
> > > > > > 
> > > > > > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > > > > 
> > > > > Thanks.
> > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > Cc: Lyude Paul <lyude@redhat.com>
> > > > > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Cc: Ben Skeggs <bskeggs@redhat.com>
> > > > > > > Cc: Karol Herbst <kherbst@redhat.com>
> > > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > > Cc: Alex Deucher <alexander.deucher@amd.com>
> > > > > > > Cc: Wayne Lin <Wayne.Lin@amd.com>
> > > > > > > Cc: stable@vger.kernel.org # 6.1
> > > > > > > Cc: dri-devel@lists.freedesktop.org
> > > > > > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > > > ---
> > > > > > >  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  2 +-
> > > > > > >  drivers/gpu/drm/display/drm_dp_mst_topology.c | 26 ++++++++++---------
> > > > > > >  drivers/gpu/drm/i915/display/intel_dp_mst.c   |  4 ++-
> > > > > > >  drivers/gpu/drm/nouveau/dispnv50/disp.c       |  2 +-
> > > > > > >  include/drm/display/drm_dp_mst_helper.h       |  3 ++-
> > > > > > >  5 files changed, 21 insertions(+), 16 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > index a50319fc42b11..180d3893b68da 100644
> > > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> > > > > > > @@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
> > > > > > >  	if (enable)
> > > > > > >  		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
> > > > > > >  	else
> > > > > > > -		drm_dp_remove_payload(mst_mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
> > > > > > >  	 * AUX message. The sequence is slot 1-63 allocated sequence for each
> > > > > > > diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > index 847c10aa2098c..1990ff5dc7ddd 100644
> > > > > > > --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
> > > > > > > @@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   * drm_dp_remove_payload() - Remove an MST payload
> > > > > > >   * @mgr: Manager to use.
> > > > > > >   * @mst_state: The MST atomic state
> > > > > > > - * @payload: The payload to write
> > > > > > > + * @old_payload: The payload with its old state
> > > > > > > + * @new_payload: The payload to write
> > > > > > >   *
> > > > > > >   * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
> > > > > > >   * the starting time slots of all other payloads which would have been shifted towards the start of
> > > > > > > @@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
> > > > > > >   */
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload)
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload)
> > > > > > >  {
> > > > > > >  	struct drm_dp_mst_atomic_payload *pos;
> > > > > > >  	bool send_remove = false;
> > > > > > >  
> > > > > > >  	/* We failed to make the payload, so nothing to do */
> > > > > > > -	if (payload->vc_start_slot == -1)
> > > > > > > +	if (new_payload->vc_start_slot == -1)
> > > > > > >  		return;
> > > > > > >  
> > > > > > >  	mutex_lock(&mgr->lock);
> > > > > > > -	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
> > > > > > > +	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
> > > > > > >  	mutex_unlock(&mgr->lock);
> > > > > > >  
> > > > > > >  	if (send_remove)
> > > > > > > -		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
> > > > > > > +		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
> > > > > > >  	else
> > > > > > >  		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
> > > > > > > -			    payload->vcpi);
> > > > > > > +			    new_payload->vcpi);
> > > > > > >  
> > > > > > >  	list_for_each_entry(pos, &mst_state->payloads, next) {
> > > > > > > -		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
> > > > > > > -			pos->vc_start_slot -= payload->time_slots;
> > > > > > > +		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
> > > > > > > +			pos->vc_start_slot -= old_payload->time_slots;
> > > > > > >  	}
> > > > > > > -	payload->vc_start_slot = -1;
> > > > > > > +	new_payload->vc_start_slot = -1;
> > > > > > >  
> > > > > > >  	mgr->payload_count--;
> > > > > > > -	mgr->next_start_slot -= payload->time_slots;
> > > > > > > +	mgr->next_start_slot -= old_payload->time_slots;
> > > > > > >  
> > > > > > > -	if (payload->delete)
> > > > > > > -		drm_dp_mst_put_port_malloc(payload->port);
> > > > > > > +	if (new_payload->delete)
> > > > > > > +		drm_dp_mst_put_port_malloc(new_payload->port);
> > > > > > >  }
> > > > > > >  EXPORT_SYMBOL(drm_dp_remove_payload);
> > > > > > >  
> > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > index f3cb12dcfe0a7..dc4e5ff1dbb31 100644
> > > > > > > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > > > > > > @@ -526,6 +526,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  		to_intel_connector(old_conn_state->connector);
> > > > > > >  	struct drm_dp_mst_topology_state *mst_state =
> > > > > > >  		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
> > > > > > > +	struct drm_dp_mst_atomic_payload *payload =
> > > > > > > +		drm_atomic_get_mst_payload_state(mst_state, connector->port);
> > > > > > >  	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> > > > > > >  
> > > > > > >  	drm_dbg_kms(&i915->drm, "active links %d\n",
> > > > > > > @@ -534,7 +536,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
> > > > > > >  	intel_hdcp_disable(intel_mst->connector);
> > > > > > >  
> > > > > > >  	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
> > > > > > > -			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
> > > > > > > +			      payload, payload);
> > > > > > >  
> > > > > > >  	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
> > > > > > >  }
> > > > > > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > index edcb2529b4025..ed9d374147b8d 100644
> > > > > > > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> > > > > > > @@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
> > > > > > >  
> > > > > > >  	// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
> > > > > > >  	if (msto->disabled) {
> > > > > > > -		drm_dp_remove_payload(mgr, mst_state, payload);
> > > > > > > +		drm_dp_remove_payload(mgr, mst_state, payload, payload);
> > > > > > >  
> > > > > > >  		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
> > > > > > >  	} else {
> > > > > > > diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > index 41fd8352ab656..f5eb9aa152b14 100644
> > > > > > > --- a/include/drm/display/drm_dp_mst_helper.h
> > > > > > > +++ b/include/drm/display/drm_dp_mst_helper.h
> > > > > > > @@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			     struct drm_dp_mst_atomic_payload *payload);
> > > > > > >  void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
> > > > > > >  			   struct drm_dp_mst_topology_state *mst_state,
> > > > > > > -			   struct drm_dp_mst_atomic_payload *payload);
> > > > > > > +			   const struct drm_dp_mst_atomic_payload *old_payload,
> > > > > > > +			   struct drm_dp_mst_atomic_payload *new_payload);
> > > > > > >  
> > > > > > >  int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
> > > > > > >  
> > > > > > 
> > > > > > -- 
> > > > > > Cheers,
> > > > > >  Lyude Paul (she/her)
> > > > > >  Software Engineer at Red Hat
> > > > > > 
> > > > > 
> > > > 
> > > > -- 
> > > > Cheers,
> > > >  Lyude Paul (she/her)
> > > >  Software Engineer at Red Hat
> > > > 
> > > 
> > 
> > -- 
> > Cheers,
> >  Lyude Paul (she/her)
> >  Software Engineer at Red Hat
> > 
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

end of thread, other threads:[~2023-02-09 21:44 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-31 15:05 [Intel-gfx] [PATCH v2 00/17] drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/dp_mst: Add the MST topology state for modesetted CRTCs Imre Deak
2023-01-31 15:05   ` Imre Deak
2023-01-31 15:05 ` [PATCH v2 02/17] drm/display/dp_mst: Handle old/new payload states in drm_dp_remove_payload() Imre Deak
2023-01-31 15:05   ` Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 23:13   ` Lyude Paul
2023-01-31 23:13     ` Lyude Paul
2023-01-31 23:13     ` [Intel-gfx] " Lyude Paul
2023-02-01 15:04     ` Imre Deak
2023-02-01 15:04       ` Imre Deak
2023-02-01 15:04       ` [Intel-gfx] " Imre Deak
2023-02-07  0:42       ` Lyude Paul
2023-02-07  0:42         ` Lyude Paul
2023-02-07  0:42         ` Lyude Paul
2023-02-07 12:11         ` Imre Deak
2023-02-07 12:11           ` [Intel-gfx] " Imre Deak
2023-02-07 12:11           ` Imre Deak
2023-02-08  0:21           ` [Intel-gfx] " Lyude Paul
2023-02-08  0:21             ` Lyude Paul
2023-02-08  0:21             ` Lyude Paul
2023-02-08  7:41             ` Imre Deak
2023-02-08  7:41               ` [Intel-gfx] " Imre Deak
2023-02-08  7:41               ` Imre Deak
2023-02-09 21:43               ` Lyude Paul
2023-02-09 21:43                 ` [Intel-gfx] " Lyude Paul
2023-02-09 21:43                 ` Lyude Paul
2023-01-31 15:05 ` [PATCH v2 03/17] drm/display/dp_mst: Add drm_atomic_get_old_mst_topology_state() Imre Deak
2023-01-31 15:05   ` Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 04/17] drm/i915/dp_mst: Fix payload removal during output disabling Imre Deak
2023-01-31 15:05   ` Imre Deak
2023-01-31 15:05 ` [PATCH v2 05/17] drm/display/dp_mst: Fix the payload VCPI check in drm_dp_mst_dump_topology() Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 06/17] drm/display/dp_mst: Sanitize payload iteration " Imre Deak
2023-01-31 23:14   ` Lyude Paul
2023-02-03 12:22   ` Ville Syrjälä
2023-02-03 13:12     ` Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 07/17] drm/i915: Factor out helpers for modesetting CRTCs and connectors Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 08/17] drm/i915/dp_mst: Move getting the MST topology state earlier to connector check Imre Deak
2023-01-31 15:05 ` [PATCH v2 09/17] drm/display/dp_mst: Add a helper to verify the MST payload state Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 10/17] drm/i915/dp_mst: Verify the MST state of modesetted outputs Imre Deak
2023-01-31 15:05 ` [PATCH v2 11/17] drm/display/dp_mst: Add helpers to query for payload allocation errors Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-02-02 10:13   ` kernel test robot
2023-02-02 12:15     ` [Intel-gfx] " Dan Carpenter
2023-02-02 12:15     ` Dan Carpenter
2023-02-02 12:15     ` Dan Carpenter
2023-02-02 12:35     ` Imre Deak
2023-02-02 12:35       ` [Intel-gfx] " Imre Deak
2023-02-02 12:35       ` Imre Deak
2023-01-31 15:05 ` [PATCH v2 12/17] drm/display/dp_mst: Add helpers to query payload allocation properties Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [PATCH v2 13/17] drm/display/dp_mst: Export the DP_PAYLOAD_TABLE_SIZE definition Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [PATCH v2 14/17] drm/display/dp_mst: Factor out a helper to reset the payload table Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [PATCH v2 15/17] drm/dp: Add a quirk for a DELL P2715Q MST payload allocation problem Imre Deak
2023-01-31 15:05   ` [Intel-gfx] " Imre Deak
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp_mst: Add workaround for a DELL P2715Q " Imre Deak
2023-01-31 22:47   ` Lyude Paul
2023-02-01 14:41     ` Imre Deak
2023-01-31 23:43   ` Lyude Paul
2023-01-31 15:05 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp_mst: Verify the HW state of MST encoders Imre Deak
2023-02-01  9:41   ` Jani Nikula
2023-02-01 14:03     ` Imre Deak
2023-01-31 15:27 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915: drm/i915/dp_mst: Fix MST payload removal during output disabling Patchwork
2023-01-31 15:59 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2023-01-31 20:42 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

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