All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion
@ 2022-11-14 22:17 Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
                   ` (3 more replies)
  0 siblings, 4 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx

There was a bit of unexpected fallout from the atomic-only conversion
patches that I had pushed a while ago, which mostly affected amdgpu.
This fixes most of the severe issues, although we're still investigating
some lingering issues (which I suspect may just fix themselves following
this patchset, but we'll see!).

This is -technically- a v2 as it's a continuation on this previous
series:

https://patchwork.freedesktop.org/series/110556/

and there were some rather important changes made since then that Wayne
pointed out, which may or may not fix the last few issues left on this
issue:

https://gitlab.freedesktop.org/drm/amd/-/issues/2171

Note I've omitted one KASAN fix, but that's because it was just getting
in the way of turning on KASAN and was definitely unrelated to this bug.
Will submit that one on it's own shortly.

Lyude Paul (4):
  drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return
    code
  drm/amdgpu/dm/mst: Use the correct topology mgr pointer in
    amdgpu_dm_connector
  drm/amdgpu/dm/dp_mst: Don't grab mst_mgr->lock when computing DSC
    state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 254 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 drivers/gpu/drm/display/drm_dp_mst_topology.c |   2 +-
 4 files changed, 155 insertions(+), 131 deletions(-)

-- 
2.37.3


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

* [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-14 22:17 [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
@ 2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  3 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Francis, Rodrigo Siqueira, Alex Hung, Fangzhi Zuo,
	Aurabindo Pillai, Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui,
	Roman Li, stable, Christian König, Thomas Zimmermann,
	Wayne Lin, Alex Deucher, Nicholas Kazlauskas

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7b..852a2100c6b38 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5c..bba2e8aaa2c20 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa2..97fd70df531bf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.37.3


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

* [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Alex Hung,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui, Roman Li, stable,
	Christian König, Thomas Zimmermann, Wayne Lin, Alex Deucher,
	Nicholas Kazlauskas

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7b..852a2100c6b38 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5c..bba2e8aaa2c20 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa2..97fd70df531bf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.37.3


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

* [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, stable, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, Pan, Xinhui, David Airlie, Daniel Vetter,
	Nicholas Kazlauskas, Aurabindo Pillai, Roman Li, Fangzhi Zuo,
	hersen wu, Wayne Lin, Thomas Zimmermann, Hamza Mahfooz,
	Alex Hung, Mikita Lipski, Wenjing Liu, David Francis,
	open list:DRM DRIVERS, open list

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7b..852a2100c6b38 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5c..bba2e8aaa2c20 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa2..97fd70df531bf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.37.3


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

* [PATCH v2 2/4] drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code
  2022-11-14 22:17 [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
@ 2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  3 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Jani Nikula, open list, stable, open list:DRM DRIVERS,
	Thomas Zimmermann, Wayne Lin, Alex Deucher, Mikita Lipski

Looks like that we're accidentally dropping a pretty important return code
here. For some reason, we just return -EINVAL if we fail to get the MST
topology state. This is wrong: error codes are important and should never
be squashed without being handled, which here seems to have the potential
to cause a deadlock.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Fixes: 8ec046716ca8 ("drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs")
Cc: <stable@vger.kernel.org> # v5.6+
---
 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 ecd22c038c8c0..51a46689cda70 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5186,7 +5186,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm
 	mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 
 	if (IS_ERR(mst_state))
-		return -EINVAL;
+		return PTR_ERR(mst_state);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
 
-- 
2.37.3


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

* [PATCH v2 2/4] drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Daniel Vetter, Jani Nikula, Imre Deak, open list, stable,
	open list:DRM DRIVERS, Thomas Zimmermann, Wayne Lin,
	Alex Deucher, Mikita Lipski, David Airlie

Looks like that we're accidentally dropping a pretty important return code
here. For some reason, we just return -EINVAL if we fail to get the MST
topology state. This is wrong: error codes are important and should never
be squashed without being handled, which here seems to have the potential
to cause a deadlock.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Fixes: 8ec046716ca8 ("drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs")
Cc: <stable@vger.kernel.org> # v5.6+
---
 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 ecd22c038c8c0..51a46689cda70 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5186,7 +5186,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm
 	mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 
 	if (IS_ERR(mst_state))
-		return -EINVAL;
+		return PTR_ERR(mst_state);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
 
-- 
2.37.3


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

* [PATCH v2 2/4] drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wayne Lin, stable, David Airlie, Daniel Vetter, Jani Nikula,
	Thomas Zimmermann, Imre Deak, Alex Deucher, Mikita Lipski,
	open list:DRM DRIVERS, open list

Looks like that we're accidentally dropping a pretty important return code
here. For some reason, we just return -EINVAL if we fail to get the MST
topology state. This is wrong: error codes are important and should never
be squashed without being handled, which here seems to have the potential
to cause a deadlock.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Fixes: 8ec046716ca8 ("drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs")
Cc: <stable@vger.kernel.org> # v5.6+
---
 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 ecd22c038c8c0..51a46689cda70 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -5186,7 +5186,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm
 	mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 
 	if (IS_ERR(mst_state))
-		return -EINVAL;
+		return PTR_ERR(mst_state);
 
 	list_for_each_entry(pos, &mst_state->payloads, next) {
 
-- 
2.37.3


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

* [PATCH v2 3/4] drm/amdgpu/dm/mst: Use the correct topology mgr pointer in amdgpu_dm_connector
  2022-11-14 22:17 [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
@ 2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  3 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: open list:DRM DRIVERS, Thomas Zimmermann, Leo Li, David Francis,
	Pan, Xinhui, Rodrigo Siqueira, Roman Li, stable, Wenjing Liu,
	Fangzhi Zuo, hersen wu, Hamza Mahfooz, Wayne Lin, Alex Deucher,
	Mikita Lipski, Christian König, open list

This bug hurt me. Basically, it appears that we've been grabbing the
entirely wrong mutex in the MST DSC computation code for amdgpu! While
we've been grabbing:

  amdgpu_dm_connector->mst_mgr

That's zero-initialized memory, because the only connectors we'll ever
actually be doing DSC computations for are MST ports. Which have mst_mgr
zero-initialized, and instead have the correct topology mgr pointer located
at:

  amdgpu_dm_connector->mst_port->mgr;

I'm a bit impressed that until now, this code has managed not to crash
anyone's systems! It does seem to cause a warning in LOCKDEP though:

  [   66.637670] DEBUG_LOCKS_WARN_ON(lock->magic != lock)

This was causing the problems that appeared to have been introduced by:

  commit 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")

This wasn't actually where they came from though. Presumably, before the
only thing we were doing with the topology mgr pointer was attempting to
grab mst_mgr->lock. Since the above commit however, we grab much more
information from mst_mgr including the atomic MST state and respective
modesetting locks.

This patch also implies that up until now, it's quite likely we could be
susceptible to race conditions when going through the MST topology state
for DSC computations since we technically will not have grabbed any lock
when going through it.

So, let's fix this by adjusting all the respective code paths to look at
the right pointer and skip things that aren't actual MST connectors from a
topology.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 37 +++++++++----------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index bba2e8aaa2c20..5196c9a0e432d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1117,6 +1117,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret = 0;
 
@@ -1131,7 +1132,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1146,16 +1147,13 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1182,6 +1180,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret;
 
@@ -1196,7 +1195,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1208,15 +1207,13 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1419,6 +1416,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
 	unsigned int max_compressed_bw_in_kbps = 0;
 	struct dc_dsc_bw_range bw_range = {0};
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 
 	/*
 	 * check if the mode could be supported if DSC pass-through is supported
@@ -1427,7 +1425,8 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	 */
 	if (is_dsc_common_config_possible(stream, &bw_range) &&
 	    aconnector->port->passthrough_aux) {
-		mutex_lock(&aconnector->mst_mgr.lock);
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
 
 		cur_link_settings = stream->link->verified_link_cap;
 
@@ -1440,7 +1439,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 		end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps,
 					    down_link_bw_in_kbps);
 
-		mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
 
 		/*
 		 * use the maximum dsc compression bandwidth as the required
-- 
2.37.3


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

* [PATCH v2 3/4] drm/amdgpu/dm/mst: Use the correct topology mgr pointer in amdgpu_dm_connector
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: open list:DRM DRIVERS, Thomas Zimmermann, Leo Li, David Airlie,
	David Francis, Pan, Xinhui, Rodrigo Siqueira, Roman Li, stable,
	Wenjing Liu, Fangzhi Zuo, hersen wu, Hamza Mahfooz,
	Daniel Vetter, Wayne Lin, Alex Deucher, Mikita Lipski,
	Harry Wentland, Christian König, open list

This bug hurt me. Basically, it appears that we've been grabbing the
entirely wrong mutex in the MST DSC computation code for amdgpu! While
we've been grabbing:

  amdgpu_dm_connector->mst_mgr

That's zero-initialized memory, because the only connectors we'll ever
actually be doing DSC computations for are MST ports. Which have mst_mgr
zero-initialized, and instead have the correct topology mgr pointer located
at:

  amdgpu_dm_connector->mst_port->mgr;

I'm a bit impressed that until now, this code has managed not to crash
anyone's systems! It does seem to cause a warning in LOCKDEP though:

  [   66.637670] DEBUG_LOCKS_WARN_ON(lock->magic != lock)

This was causing the problems that appeared to have been introduced by:

  commit 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")

This wasn't actually where they came from though. Presumably, before the
only thing we were doing with the topology mgr pointer was attempting to
grab mst_mgr->lock. Since the above commit however, we grab much more
information from mst_mgr including the atomic MST state and respective
modesetting locks.

This patch also implies that up until now, it's quite likely we could be
susceptible to race conditions when going through the MST topology state
for DSC computations since we technically will not have grabbed any lock
when going through it.

So, let's fix this by adjusting all the respective code paths to look at
the right pointer and skip things that aren't actual MST connectors from a
topology.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 37 +++++++++----------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index bba2e8aaa2c20..5196c9a0e432d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1117,6 +1117,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret = 0;
 
@@ -1131,7 +1132,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1146,16 +1147,13 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1182,6 +1180,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret;
 
@@ -1196,7 +1195,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1208,15 +1207,13 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1419,6 +1416,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
 	unsigned int max_compressed_bw_in_kbps = 0;
 	struct dc_dsc_bw_range bw_range = {0};
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 
 	/*
 	 * check if the mode could be supported if DSC pass-through is supported
@@ -1427,7 +1425,8 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	 */
 	if (is_dsc_common_config_possible(stream, &bw_range) &&
 	    aconnector->port->passthrough_aux) {
-		mutex_lock(&aconnector->mst_mgr.lock);
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
 
 		cur_link_settings = stream->link->verified_link_cap;
 
@@ -1440,7 +1439,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 		end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps,
 					    down_link_bw_in_kbps);
 
-		mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
 
 		/*
 		 * use the maximum dsc compression bandwidth as the required
-- 
2.37.3


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

* [PATCH v2 3/4] drm/amdgpu/dm/mst: Use the correct topology mgr pointer in amdgpu_dm_connector
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: stable, Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, Pan, Xinhui, David Airlie, Daniel Vetter,
	hersen wu, Fangzhi Zuo, Wayne Lin, Thomas Zimmermann, Roman Li,
	Hamza Mahfooz, Wenjing Liu, David Francis, Mikita Lipski,
	open list:DRM DRIVERS, open list

This bug hurt me. Basically, it appears that we've been grabbing the
entirely wrong mutex in the MST DSC computation code for amdgpu! While
we've been grabbing:

  amdgpu_dm_connector->mst_mgr

That's zero-initialized memory, because the only connectors we'll ever
actually be doing DSC computations for are MST ports. Which have mst_mgr
zero-initialized, and instead have the correct topology mgr pointer located
at:

  amdgpu_dm_connector->mst_port->mgr;

I'm a bit impressed that until now, this code has managed not to crash
anyone's systems! It does seem to cause a warning in LOCKDEP though:

  [   66.637670] DEBUG_LOCKS_WARN_ON(lock->magic != lock)

This was causing the problems that appeared to have been introduced by:

  commit 4d07b0bc4034 ("drm/display/dp_mst: Move all payload info into the atomic state")

This wasn't actually where they came from though. Presumably, before the
only thing we were doing with the topology mgr pointer was attempting to
grab mst_mgr->lock. Since the above commit however, we grab much more
information from mst_mgr including the atomic MST state and respective
modesetting locks.

This patch also implies that up until now, it's quite likely we could be
susceptible to race conditions when going through the MST topology state
for DSC computations since we technically will not have grabbed any lock
when going through it.

So, let's fix this by adjusting all the respective code paths to look at
the right pointer and skip things that aren't actual MST connectors from a
topology.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 37 +++++++++----------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index bba2e8aaa2c20..5196c9a0e432d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1117,6 +1117,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret = 0;
 
@@ -1131,7 +1132,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1146,16 +1147,13 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1182,6 +1180,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 	int link_vars_start_index = 0;
 	int ret;
 
@@ -1196,7 +1195,7 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
-		if (!aconnector || !aconnector->dc_sink)
+		if (!aconnector || !aconnector->dc_sink || !aconnector->port)
 			continue;
 
 		if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
@@ -1208,15 +1207,13 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
-		mutex_lock(&aconnector->mst_mgr.lock);
-		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						       &aconnector->mst_mgr,
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		if (ret != 0) {
-			mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
+		if (ret != 0)
 			return ret;
-		}
-		mutex_unlock(&aconnector->mst_mgr.lock);
 
 		for (j = 0; j < dc_state->stream_count; j++) {
 			if (dc_state->streams[j]->link == stream->link)
@@ -1419,6 +1416,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
 	unsigned int max_compressed_bw_in_kbps = 0;
 	struct dc_dsc_bw_range bw_range = {0};
+	struct drm_dp_mst_topology_mgr *mst_mgr;
 
 	/*
 	 * check if the mode could be supported if DSC pass-through is supported
@@ -1427,7 +1425,8 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 	 */
 	if (is_dsc_common_config_possible(stream, &bw_range) &&
 	    aconnector->port->passthrough_aux) {
-		mutex_lock(&aconnector->mst_mgr.lock);
+		mst_mgr = aconnector->port->mgr;
+		mutex_lock(&mst_mgr->lock);
 
 		cur_link_settings = stream->link->verified_link_cap;
 
@@ -1440,7 +1439,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
 		end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps,
 					    down_link_bw_in_kbps);
 
-		mutex_unlock(&aconnector->mst_mgr.lock);
+		mutex_unlock(&mst_mgr->lock);
 
 		/*
 		 * use the maximum dsc compression bandwidth as the required
-- 
2.37.3


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

* [PATCH v2 4/4] drm/amdgpu/dm/dp_mst: Don't grab mst_mgr->lock when computing DSC state
  2022-11-14 22:17 [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
@ 2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  2022-11-14 22:17   ` Lyude Paul
  3 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: open list:DRM DRIVERS, Leo Li, David Francis, Pan, Xinhui,
	Rodrigo Siqueira, Roman Li, stable, Nicholas Kazlauskas,
	Wenjing Liu, Fangzhi Zuo, hersen wu, Hamza Mahfooz, Wayne Lin,
	Alex Deucher, Mikita Lipski, Christian König, open list

Now that we've fixed the issue with using the incorrect topology manager,
we're actually grabbing the topology manager's lock - and consequently
deadlocking. Luckily for us though, there's actually nothing in AMD's DSC
state computation code that really should need this lock. The one exception
is the mutex_lock() in dm_dp_mst_is_port_support_mode(), however we grab no
locks beneath &mgr->lock there so that should be fine to leave be.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5196c9a0e432d..59648f5ffb59d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1148,10 +1148,8 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
@@ -1208,10 +1206,8 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
-- 
2.37.3


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

* [PATCH v2 4/4] drm/amdgpu/dm/dp_mst: Don't grab mst_mgr->lock when computing DSC state
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: open list:DRM DRIVERS, Leo Li, David Airlie, David Francis, Pan,
	Xinhui, Rodrigo Siqueira, Roman Li, stable, Nicholas Kazlauskas,
	Wenjing Liu, Fangzhi Zuo, hersen wu, Hamza Mahfooz,
	Daniel Vetter, Wayne Lin, Alex Deucher, Mikita Lipski,
	Harry Wentland, Christian König, open list

Now that we've fixed the issue with using the incorrect topology manager,
we're actually grabbing the topology manager's lock - and consequently
deadlocking. Luckily for us though, there's actually nothing in AMD's DSC
state computation code that really should need this lock. The one exception
is the mutex_lock() in dm_dp_mst_is_port_support_mode(), however we grab no
locks beneath &mgr->lock there so that should be fine to leave be.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5196c9a0e432d..59648f5ffb59d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1148,10 +1148,8 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
@@ -1208,10 +1206,8 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
-- 
2.37.3


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

* [PATCH v2 4/4] drm/amdgpu/dm/dp_mst: Don't grab mst_mgr->lock when computing DSC state
@ 2022-11-14 22:17   ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-14 22:17 UTC (permalink / raw)
  To: amd-gfx
  Cc: stable, Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, Pan, Xinhui, David Airlie, Daniel Vetter,
	hersen wu, Fangzhi Zuo, Wayne Lin, Nicholas Kazlauskas, Roman Li,
	Hamza Mahfooz, David Francis, Wenjing Liu, Mikita Lipski,
	open list:DRM DRIVERS, open list

Now that we've fixed the issue with using the incorrect topology manager,
we're actually grabbing the topology manager's lock - and consequently
deadlocking. Luckily for us though, there's actually nothing in AMD's DSC
state computation code that really should need this lock. The one exception
is the mutex_lock() in dm_dp_mst_is_port_support_mode(), however we grab no
locks beneath &mgr->lock there so that should be fine to leave be.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Gitlab issue: https://gitlab.freedesktop.org/drm/amd/-/issues/2171
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Cc: <stable@vger.kernel.org> # v5.6+
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5196c9a0e432d..59648f5ffb59d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -1148,10 +1148,8 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
@@ -1208,10 +1206,8 @@ static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		mst_mgr = aconnector->port->mgr;
-		mutex_lock(&mst_mgr->lock);
 		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, mst_mgr,
 						       &link_vars_start_index);
-		mutex_unlock(&mst_mgr->lock);
 		if (ret != 0)
 			return ret;
 
-- 
2.37.3


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

* RE: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-14 22:17   ` Lyude Paul
  (?)
@ 2022-11-16  4:39     ` Lin, Wayne
  -1 siblings, 0 replies; 43+ messages in thread
From: Lin, Wayne @ 2022-11-16  4:39 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Wentland, Harry, stable, Li, Sun peng (Leo),
	Siqueira, Rodrigo, Deucher, Alexander, Koenig, Christian, Pan,
	Xinhui, David Airlie, Daniel Vetter, Kazlauskas, Nicholas,
	Pillai, Aurabindo, Li, Roman, Zuo, Jerry, Wu, Hersen,
	Thomas Zimmermann, Mahfooz, Hamza, Hung, Alex, Mikita Lipski,
	Liu, Wenjing, Francis, David, open list:DRM DRIVERS, open list

[Public]

All the patch set looks good to me. Feel free to add:
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>

Again, thank you Lyude for helping on this!!!

Regards,
Wayne
> -----Original Message-----
> From: Lyude Paul <lyude@redhat.com>
> Sent: Tuesday, November 15, 2022 6:18 AM
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> Wenjing <Wenjing.Liu@amd.com>; Francis, David
> <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> deadlocking
> 
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple true/false.
> In this case, it seems to have come back to bite us because as a result of
> simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> had no way of telling when a deadlock happened from these helpers. This
> could definitely result in some kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>   passing down return codes)
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> --
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>  3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7b..852a2100c6b38 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  	struct drm_connector_state *new_con_state;
>  	struct amdgpu_dm_connector *aconnector;
>  	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>  	int vcpi, pbn_div, pbn, slot_num = 0;
> 
>  	for_each_new_connector_in_state(state, connector,
> new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  			dm_conn_state->pbn = pbn;
>  			dm_conn_state->vcpi_slots = slot_num;
> 
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> >port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state,
> aconnector->port,
> +							   dm_conn_state-
> >pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>  			continue;
>  		}
> 
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
>  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>  			goto fail;
> -		}
>  	}
>  #endif
> 
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
>  		}
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars);
> +		if (ret) {
> 
> 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> failed\n");
> -			ret = -EINVAL;
>  			goto fail;
>  		}
> 
> diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> dsc_mst_fairness_params param, int pbn)
>  	return dsc_config.bits_per_pixel;
>  }
> 
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>  {
>  	int i;
>  	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
>  	int remaining_to_increase = 0;
>  	int link_timeslots_used;
>  	int fair_pbn_alloc;
> +	int ret = 0;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
> 
>  		if (initial_slack[next_index] > fair_pbn_alloc) {
>  			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>  			} else {
>  				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		} else {
>  			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> params[next_index].bw_range.max_target_bpp_x16;
>  			} else {
>  				vars[next_index].pbn -=
> initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		}
> 
>  		bpp_increased[next_index] = true;
>  		remaining_to_increase--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>  {
>  	int i;
>  	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> *state,
>  	int max_kbps_increase;
>  	int next_index;
>  	int remaining_to_try = 0;
> +	int ret;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> drm_atomic_state *state,
>  			break;
> 
>  		vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port-
> >mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port-
> >mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
> 
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>  			vars[next_index].dsc_enabled = false;
>  			vars[next_index].bpp_x16 = 0;
>  		} else {
>  			vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
> 
>  		tried[next_index] = true;
>  		remaining_to_try--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr
> *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr
> *mgr,
> +					    int *link_vars_start_index)
>  {
>  	struct dc_stream_state *stream;
>  	struct dsc_mst_fairness_params params[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	struct drm_dp_mst_topology_state *mst_state =
> drm_atomic_get_mst_topology_state(state, mgr);
>  	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>  	bool debugfs_overwrite = false;
> 
>  	memset(params, 0, sizeof(params));
> 
>  	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
> 
>  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> 
>  	if (count == 0) {
>  		ASSERT(0);
> -		return true;
> +		return 0;
>  	}
> 
>  	/* k is start index of vars for current phy link used by mst hub */ @@
> -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> drm_atomic_state *state,
>  		vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  		vars[i + k].dsc_enabled = false;
>  		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>  	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>  	}
> 
>  	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>  			vars[i + k].dsc_enabled = true;
>  			vars[i + k].bpp_x16 =
> params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		} else {
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  			vars[i + k].dsc_enabled = false;
>  			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
>  	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
> 
>  	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> count, k);
> +	if (ret < 0)
> +		return ret;
> 
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
> 
>  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> 
> -	return true;
> +	return 0;
>  }
> 
>  static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>  	return is_dsc_need_re_compute;
>  }
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret = 0;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
>  			continue;
> 
>  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
> 
>  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> 
>  		if (stream->timing.flags.DSC == 1)
>  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> >dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars
> *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars
> *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1198,7 +1224,7 @@ static bool
>  		}
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
>  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> *state, @@ -1253,9 +1279,9 @@ static bool
> is_dsc_precompute_needed(struct drm_atomic_state *state)
>  	return ret;
>  }
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>  {
>  	int i;
>  	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	if (!is_dsc_precompute_needed(state)) {
>  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>  	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>  	}
>  	dm_state = *dm_state_ptr;
> 
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> dc_state), GFP_KERNEL);
>  	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
> 
>  	for (i = 0; i < local_dc_state->stream_count; i++) {
>  		struct dc_stream_state *stream = dm_state->context-
> >streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> drm_atomic_state *state,
>  	if (ret != 0)
>  		goto clean_exit;
> 
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars);
> +	if (ret != 0) {
> 
> 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> failed\n");
> -		ret = -EINVAL;
>  		goto clean_exit;
>  	}
> 
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	kfree(local_dc_state);
> 
> -	return (ret == 0);
> +	return ret;
>  }
> 
>  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa2..97fd70df531bf 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>  	struct amdgpu_dm_connector *aconnector;  };
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
> 
>  bool needs_dsc_aux_workaround(struct dc_link *link);
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
> 
>  enum dc_status dm_dp_mst_is_port_support_mode(
>  	struct amdgpu_dm_connector *aconnector,
> --
> 2.37.3

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

* RE: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-16  4:39     ` Lin, Wayne
  0 siblings, 0 replies; 43+ messages in thread
From: Lin, Wayne @ 2022-11-16  4:39 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, Hung, Alex, Zuo, Jerry,
	Pillai, Aurabindo, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

[Public]

All the patch set looks good to me. Feel free to add:
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>

Again, thank you Lyude for helping on this!!!

Regards,
Wayne
> -----Original Message-----
> From: Lyude Paul <lyude@redhat.com>
> Sent: Tuesday, November 15, 2022 6:18 AM
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> Wenjing <Wenjing.Liu@amd.com>; Francis, David
> <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> deadlocking
> 
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple true/false.
> In this case, it seems to have come back to bite us because as a result of
> simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> had no way of telling when a deadlock happened from these helpers. This
> could definitely result in some kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>   passing down return codes)
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> --
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>  3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7b..852a2100c6b38 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  	struct drm_connector_state *new_con_state;
>  	struct amdgpu_dm_connector *aconnector;
>  	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>  	int vcpi, pbn_div, pbn, slot_num = 0;
> 
>  	for_each_new_connector_in_state(state, connector,
> new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  			dm_conn_state->pbn = pbn;
>  			dm_conn_state->vcpi_slots = slot_num;
> 
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> >port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state,
> aconnector->port,
> +							   dm_conn_state-
> >pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>  			continue;
>  		}
> 
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
>  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>  			goto fail;
> -		}
>  	}
>  #endif
> 
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
>  		}
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars);
> +		if (ret) {
> 
> 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> failed\n");
> -			ret = -EINVAL;
>  			goto fail;
>  		}
> 
> diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> dsc_mst_fairness_params param, int pbn)
>  	return dsc_config.bits_per_pixel;
>  }
> 
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>  {
>  	int i;
>  	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
>  	int remaining_to_increase = 0;
>  	int link_timeslots_used;
>  	int fair_pbn_alloc;
> +	int ret = 0;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
> 
>  		if (initial_slack[next_index] > fair_pbn_alloc) {
>  			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>  			} else {
>  				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		} else {
>  			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> params[next_index].bw_range.max_target_bpp_x16;
>  			} else {
>  				vars[next_index].pbn -=
> initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		}
> 
>  		bpp_increased[next_index] = true;
>  		remaining_to_increase--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>  {
>  	int i;
>  	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> *state,
>  	int max_kbps_increase;
>  	int next_index;
>  	int remaining_to_try = 0;
> +	int ret;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> drm_atomic_state *state,
>  			break;
> 
>  		vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port-
> >mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port-
> >mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
> 
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>  			vars[next_index].dsc_enabled = false;
>  			vars[next_index].bpp_x16 = 0;
>  		} else {
>  			vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
> 
>  		tried[next_index] = true;
>  		remaining_to_try--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr
> *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr
> *mgr,
> +					    int *link_vars_start_index)
>  {
>  	struct dc_stream_state *stream;
>  	struct dsc_mst_fairness_params params[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	struct drm_dp_mst_topology_state *mst_state =
> drm_atomic_get_mst_topology_state(state, mgr);
>  	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>  	bool debugfs_overwrite = false;
> 
>  	memset(params, 0, sizeof(params));
> 
>  	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
> 
>  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> 
>  	if (count == 0) {
>  		ASSERT(0);
> -		return true;
> +		return 0;
>  	}
> 
>  	/* k is start index of vars for current phy link used by mst hub */ @@
> -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> drm_atomic_state *state,
>  		vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  		vars[i + k].dsc_enabled = false;
>  		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>  	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>  	}
> 
>  	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>  			vars[i + k].dsc_enabled = true;
>  			vars[i + k].bpp_x16 =
> params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		} else {
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  			vars[i + k].dsc_enabled = false;
>  			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
>  	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
> 
>  	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> count, k);
> +	if (ret < 0)
> +		return ret;
> 
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
> 
>  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> 
> -	return true;
> +	return 0;
>  }
> 
>  static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>  	return is_dsc_need_re_compute;
>  }
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret = 0;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
>  			continue;
> 
>  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
> 
>  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> 
>  		if (stream->timing.flags.DSC == 1)
>  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> >dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars
> *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars
> *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1198,7 +1224,7 @@ static bool
>  		}
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
>  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> *state, @@ -1253,9 +1279,9 @@ static bool
> is_dsc_precompute_needed(struct drm_atomic_state *state)
>  	return ret;
>  }
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>  {
>  	int i;
>  	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	if (!is_dsc_precompute_needed(state)) {
>  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>  	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>  	}
>  	dm_state = *dm_state_ptr;
> 
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> dc_state), GFP_KERNEL);
>  	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
> 
>  	for (i = 0; i < local_dc_state->stream_count; i++) {
>  		struct dc_stream_state *stream = dm_state->context-
> >streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> drm_atomic_state *state,
>  	if (ret != 0)
>  		goto clean_exit;
> 
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars);
> +	if (ret != 0) {
> 
> 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> failed\n");
> -		ret = -EINVAL;
>  		goto clean_exit;
>  	}
> 
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	kfree(local_dc_state);
> 
> -	return (ret == 0);
> +	return ret;
>  }
> 
>  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa2..97fd70df531bf 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>  	struct amdgpu_dm_connector *aconnector;  };
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
> 
>  bool needs_dsc_aux_workaround(struct dc_link *link);
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
> 
>  enum dc_status dm_dp_mst_is_port_support_mode(
>  	struct amdgpu_dm_connector *aconnector,
> --
> 2.37.3

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

* RE: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-16  4:39     ` Lin, Wayne
  0 siblings, 0 replies; 43+ messages in thread
From: Lin, Wayne @ 2022-11-16  4:39 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, Hung, Alex, Zuo,
	Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter, Li,
	Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

[Public]

All the patch set looks good to me. Feel free to add:
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>

Again, thank you Lyude for helping on this!!!

Regards,
Wayne
> -----Original Message-----
> From: Lyude Paul <lyude@redhat.com>
> Sent: Tuesday, November 15, 2022 6:18 AM
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> Wenjing <Wenjing.Liu@amd.com>; Francis, David
> <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> deadlocking
> 
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple true/false.
> In this case, it seems to have come back to bite us because as a result of
> simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> had no way of telling when a deadlock happened from these helpers. This
> could definitely result in some kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>   passing down return codes)
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> --
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>  3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7b..852a2100c6b38 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  	struct drm_connector_state *new_con_state;
>  	struct amdgpu_dm_connector *aconnector;
>  	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>  	int vcpi, pbn_div, pbn, slot_num = 0;
> 
>  	for_each_new_connector_in_state(state, connector,
> new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>  			dm_conn_state->pbn = pbn;
>  			dm_conn_state->vcpi_slots = slot_num;
> 
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> >port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state,
> aconnector->port,
> +							   dm_conn_state-
> >pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>  			continue;
>  		}
> 
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
>  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>  			goto fail;
> -		}
>  	}
>  #endif
> 
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> drm_device *dev,
>  		}
> 
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> >context, vars);
> +		if (ret) {
> 
> 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> failed\n");
> -			ret = -EINVAL;
>  			goto fail;
>  		}
> 
> diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> dsc_mst_fairness_params param, int pbn)
>  	return dsc_config.bits_per_pixel;
>  }
> 
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>  {
>  	int i;
>  	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
>  	int remaining_to_increase = 0;
>  	int link_timeslots_used;
>  	int fair_pbn_alloc;
> +	int ret = 0;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> drm_atomic_state *state,
> 
>  		if (initial_slack[next_index] > fair_pbn_alloc) {
>  			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>  			} else {
>  				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		} else {
>  			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>  				vars[next_index].bpp_x16 =
> params[next_index].bw_range.max_target_bpp_x16;
>  			} else {
>  				vars[next_index].pbn -=
> initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>  			}
>  		}
> 
>  		bpp_increased[next_index] = true;
>  		remaining_to_increase--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>  {
>  	int i;
>  	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> *state,
>  	int max_kbps_increase;
>  	int next_index;
>  	int remaining_to_try = 0;
> +	int ret;
> 
>  	for (i = 0; i < count; i++) {
>  		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> drm_atomic_state *state,
>  			break;
> 
>  		vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port-
> >mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port-
> >mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
> 
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>  			vars[next_index].dsc_enabled = false;
>  			vars[next_index].bpp_x16 = 0;
>  		} else {
>  			vars[next_index].pbn =
> kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -
> params[next_index].port->mgr,
> -
> params[next_index].port,
> -
> vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +
> params[next_index].port->mgr,
> +
> params[next_index].port,
> +
> vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
> 
>  		tried[next_index] = true;
>  		remaining_to_try--;
>  	}
> -	return true;
> +	return 0;
>  }
> 
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr
> *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr
> *mgr,
> +					    int *link_vars_start_index)
>  {
>  	struct dc_stream_state *stream;
>  	struct dsc_mst_fairness_params params[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	struct drm_dp_mst_topology_state *mst_state =
> drm_atomic_get_mst_topology_state(state, mgr);
>  	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>  	bool debugfs_overwrite = false;
> 
>  	memset(params, 0, sizeof(params));
> 
>  	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
> 
>  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> 
>  	if (count == 0) {
>  		ASSERT(0);
> -		return true;
> +		return 0;
>  	}
> 
>  	/* k is start index of vars for current phy link used by mst hub */ @@
> -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> drm_atomic_state *state,
>  		vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  		vars[i + k].dsc_enabled = false;
>  		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> >mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>  	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>  	}
> 
>  	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool
> compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>  			vars[i + k].dsc_enabled = true;
>  			vars[i + k].bpp_x16 =
> params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		} else {
>  			vars[i + k].pbn =
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>  			vars[i + k].dsc_enabled = false;
>  			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> -							  params[i].port, vars[i
> + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> params[i].port->mgr,
> +							    params[i].port,
> vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>  		}
>  	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
> 
>  	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> count, k);
> +	if (ret < 0)
> +		return ret;
> 
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
> 
>  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> 
> -	return true;
> +	return 0;
>  }
> 
>  static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>  	return is_dsc_need_re_compute;
>  }
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret = 0;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
>  			continue;
> 
>  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
> 
>  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> 
>  		if (stream->timing.flags.DSC == 1)
>  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> >dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars
> *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct
> drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars
> *vars)
>  {
>  	int i, j;
>  	struct dc_stream_state *stream;
>  	bool computed_streams[MAX_PIPES];
>  	struct amdgpu_dm_connector *aconnector;
>  	int link_vars_start_index = 0;
> +	int ret;
> 
>  	for (i = 0; i < dc_state->stream_count; i++)
>  		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>  			continue;
> 
>  		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>  			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>  		}
>  		mutex_unlock(&aconnector->mst_mgr.lock);
> 
> @@ -1198,7 +1224,7 @@ static bool
>  		}
>  	}
> 
> -	return true;
> +	return ret;
>  }
> 
>  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> *state, @@ -1253,9 +1279,9 @@ static bool
> is_dsc_precompute_needed(struct drm_atomic_state *state)
>  	return ret;
>  }
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>  {
>  	int i;
>  	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	if (!is_dsc_precompute_needed(state)) {
>  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>  	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>  	}
>  	dm_state = *dm_state_ptr;
> 
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> dc_state), GFP_KERNEL);
>  	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
> 
>  	for (i = 0; i < local_dc_state->stream_count; i++) {
>  		struct dc_stream_state *stream = dm_state->context-
> >streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> drm_atomic_state *state,
>  	if (ret != 0)
>  		goto clean_exit;
> 
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> vars);
> +	if (ret != 0) {
> 
> 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> failed\n");
> -		ret = -EINVAL;
>  		goto clean_exit;
>  	}
> 
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> *state,
> 
>  	kfree(local_dc_state);
> 
> -	return (ret == 0);
> +	return ret;
>  }
> 
>  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa2..97fd70df531bf 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>  	struct amdgpu_dm_connector *aconnector;  };
> 
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
> 
>  bool needs_dsc_aux_workaround(struct dc_link *link);
> 
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
> 
>  enum dc_status dm_dp_mst_is_port_support_mode(
>  	struct amdgpu_dm_connector *aconnector,
> --
> 2.37.3

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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-16  4:39     ` Lin, Wayne
  (?)
@ 2022-11-16 22:43       ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-16 22:43 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, Hung,  Alex,
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas,  Nicholas

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!

No problem! I was the one who introduced the bug anyway :P, I'm just glad we
were able to fix this on time.

Harry, Alex - feel free to merge this on whatever branch you want (I'm fine
with the mst-helper bits going through amd's branch, especially since AMD is
the only driver using the dsc stuff right now)

> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-16 22:43       ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-16 22:43 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, Hung,  Alex, Zuo, Jerry,
	Pillai, Aurabindo, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas,  Nicholas

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!

No problem! I was the one who introduced the bug anyway :P, I'm just glad we
were able to fix this on time.

Harry, Alex - feel free to merge this on whatever branch you want (I'm fine
with the mst-helper bits going through amd's branch, especially since AMD is
the only driver using the dsc stuff right now)

> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-16 22:43       ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-16 22:43 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Wentland, Harry, stable, Li, Sun peng (Leo),
	Siqueira, Rodrigo, Deucher, Alexander, Koenig, Christian, Pan,
	Xinhui, David Airlie, Daniel Vetter, Kazlauskas, Nicholas,
	Pillai, Aurabindo, Li, Roman, Zuo, Jerry, Wu, Hersen,
	Thomas Zimmermann, Mahfooz, Hamza, Hung, Alex, Mikita Lipski,
	Liu, Wenjing, Francis, David, open list:DRM DRIVERS, open list

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!

No problem! I was the one who introduced the bug anyway :P, I'm just glad we
were able to fix this on time.

Harry, Alex - feel free to merge this on whatever branch you want (I'm fine
with the mst-helper bits going through amd's branch, especially since AMD is
the only driver using the dsc stuff right now)

> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-16  4:39     ` Lin, Wayne
  (?)
@ 2022-11-18 19:17       ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:17 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, Hung,  Alex, Zuo, Jerry,
	Pillai, Aurabindo, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas,  Nicholas

JFYI, Coverity pointed out one more issue with this series so I'm going to
send out a respin real quick to fix it. It's just a missing variable
assignment (we leave ret unassigned by mistake in
pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!
> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:17       ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:17 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Liu, Wenjing, open list:DRM DRIVERS, open list, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, Hung,  Alex,
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas,  Nicholas

JFYI, Coverity pointed out one more issue with this series so I'm going to
send out a respin real quick to fix it. It's just a missing variable
assignment (we leave ret unassigned by mistake in
pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!
> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:17       ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:17 UTC (permalink / raw)
  To: Lin, Wayne, amd-gfx
  Cc: Wentland, Harry, stable, Li, Sun peng (Leo),
	Siqueira, Rodrigo, Deucher, Alexander, Koenig, Christian, Pan,
	Xinhui, David Airlie, Daniel Vetter, Kazlauskas, Nicholas,
	Pillai, Aurabindo, Li, Roman, Zuo, Jerry, Wu, Hersen,
	Thomas Zimmermann, Mahfooz, Hamza, Hung, Alex, Mikita Lipski,
	Liu, Wenjing, Francis, David, open list:DRM DRIVERS, open list

JFYI, Coverity pointed out one more issue with this series so I'm going to
send out a respin real quick to fix it. It's just a missing variable
assignment (we leave ret unassigned by mistake in
pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.

On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> [Public]
> 
> All the patch set looks good to me. Feel free to add:
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> 
> Again, thank you Lyude for helping on this!!!
> 
> Regards,
> Wayne
> > -----Original Message-----
> > From: Lyude Paul <lyude@redhat.com>
> > Sent: Tuesday, November 15, 2022 6:18 AM
> > To: amd-gfx@lists.freedesktop.org
> > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > <Alexander.Deucher@amd.com>; Koenig, Christian
> > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > deadlocking
> > 
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple true/false.
> > In this case, it seems to have come back to bite us because as a result of
> > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > had no way of telling when a deadlock happened from these helpers. This
> > could definitely result in some kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >   passing down return codes)
> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > --
> >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >  3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7b..852a2100c6b38 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  	struct drm_connector_state *new_con_state;
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >  	int vcpi, pbn_div, pbn, slot_num = 0;
> > 
> >  	for_each_new_connector_in_state(state, connector,
> > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >  			dm_conn_state->pbn = pbn;
> >  			dm_conn_state->vcpi_slots = slot_num;
> > 
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state,
> > aconnector->port,
> > +							   dm_conn_state-
> > > pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >  			continue;
> >  		}
> > 
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> >  	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >  			goto fail;
> > -		}
> >  	}
> >  #endif
> > 
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > drm_device *dev,
> >  		}
> > 
> >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > context, vars);
> > +		if (ret) {
> > 
> > 	DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > failed\n");
> > -			ret = -EINVAL;
> >  			goto fail;
> >  		}
> > 
> > diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > dsc_mst_fairness_params param, int pbn)
> >  	return dsc_config.bits_per_pixel;
> >  }
> > 
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >  {
> >  	int i;
> >  	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> >  	int remaining_to_increase = 0;
> >  	int link_timeslots_used;
> >  	int fair_pbn_alloc;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > drm_atomic_state *state,
> > 
> >  		if (initial_slack[next_index] > fair_pbn_alloc) {
> >  			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >  			} else {
> >  				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		} else {
> >  			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >  				vars[next_index].bpp_x16 =
> > params[next_index].bw_range.max_target_bpp_x16;
> >  			} else {
> >  				vars[next_index].pbn -=
> > initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >  			}
> >  		}
> > 
> >  		bpp_increased[next_index] = true;
> >  		remaining_to_increase--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >  {
> >  	int i;
> >  	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > *state,
> >  	int max_kbps_increase;
> >  	int next_index;
> >  	int remaining_to_try = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < count; i++) {
> >  		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > drm_atomic_state *state,
> >  			break;
> > 
> >  		vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port-
> > > mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port-
> > > mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> > 
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >  			vars[next_index].dsc_enabled = false;
> >  			vars[next_index].bpp_x16 = 0;
> >  		} else {
> >  			vars[next_index].pbn =
> > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -
> > params[next_index].port->mgr,
> > -
> > params[next_index].port,
> > -
> > vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +
> > params[next_index].port->mgr,
> > +
> > params[next_index].port,
> > +
> > vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> > 
> >  		tried[next_index] = true;
> >  		remaining_to_try--;
> >  	}
> > -	return true;
> > +	return 0;
> >  }
> > 
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr
> > *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr
> > *mgr,
> > +					    int *link_vars_start_index)
> >  {
> >  	struct dc_stream_state *stream;
> >  	struct dsc_mst_fairness_params params[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	struct drm_dp_mst_topology_state *mst_state =
> > drm_atomic_get_mst_topology_state(state, mgr);
> >  	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >  	bool debugfs_overwrite = false;
> > 
> >  	memset(params, 0, sizeof(params));
> > 
> >  	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> > 
> >  	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > 
> >  	if (count == 0) {
> >  		ASSERT(0);
> > -		return true;
> > +		return 0;
> >  	}
> > 
> >  	/* k is start index of vars for current phy link used by mst hub */ @@
> > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > drm_atomic_state *state,
> >  		vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  		vars[i + k].dsc_enabled = false;
> >  		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >  	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >  		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >  	}
> > 
> >  	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool
> > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >  			vars[i + k].dsc_enabled = true;
> >  			vars[i + k].bpp_x16 =
> > params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		} else {
> >  			vars[i + k].pbn =
> > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >  			vars[i + k].dsc_enabled = false;
> >  			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > -							  params[i].port, vars[i
> > + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > params[i].port->mgr,
> > +							    params[i].port,
> > vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >  		}
> >  	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> > 
> >  	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> > 
> >  	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > 
> > -	return true;
> > +	return 0;
> >  }
> > 
> >  static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >  	return is_dsc_need_re_compute;
> >  }
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret = 0;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> >  			continue;
> > 
> >  		if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> > 
> >  		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > 
> >  		if (stream->timing.flags.DSC == 1)
> >  			if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars
> > *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct
> > drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars
> > *vars)
> >  {
> >  	int i, j;
> >  	struct dc_stream_state *stream;
> >  	bool computed_streams[MAX_PIPES];
> >  	struct amdgpu_dm_connector *aconnector;
> >  	int link_vars_start_index = 0;
> > +	int ret;
> > 
> >  	for (i = 0; i < dc_state->stream_count; i++)
> >  		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >  			continue;
> > 
> >  		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >  			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >  		}
> >  		mutex_unlock(&aconnector->mst_mgr.lock);
> > 
> > @@ -1198,7 +1224,7 @@ static bool
> >  		}
> >  	}
> > 
> > -	return true;
> > +	return ret;
> >  }
> > 
> >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > *state, @@ -1253,9 +1279,9 @@ static bool
> > is_dsc_precompute_needed(struct drm_atomic_state *state)
> >  	return ret;
> >  }
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >  {
> >  	int i;
> >  	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	if (!is_dsc_precompute_needed(state)) {
> >  		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >  	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >  		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >  	}
> >  	dm_state = *dm_state_ptr;
> > 
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > dc_state), GFP_KERNEL);
> >  	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> > 
> >  	for (i = 0; i < local_dc_state->stream_count; i++) {
> >  		struct dc_stream_state *stream = dm_state->context-
> > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > drm_atomic_state *state,
> >  	if (ret != 0)
> >  		goto clean_exit;
> > 
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > vars);
> > +	if (ret != 0) {
> > 
> > 	DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > failed\n");
> > -		ret = -EINVAL;
> >  		goto clean_exit;
> >  	}
> > 
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > *state,
> > 
> >  	kfree(local_dc_state);
> > 
> > -	return (ret == 0);
> > +	return ret;
> >  }
> > 
> >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa2..97fd70df531bf 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++
> > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >  	struct amdgpu_dm_connector *aconnector;  };
> > 
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> > 
> >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > 
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> > 
> >  enum dc_status dm_dp_mst_is_port_support_mode(
> >  	struct amdgpu_dm_connector *aconnector,
> > --
> > 2.37.3
> 

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


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

* [PATCH v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-14 22:17   ` Lyude Paul
  (?)
@ 2022-11-18 19:25     ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:25 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Francis, Rodrigo Siqueira, Alex Hung, Fangzhi Zuo,
	Aurabindo Pillai, Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui,
	Roman Li, stable, Christian König, Thomas Zimmermann,
	Wayne Lin, Alex Deucher, Nicholas Kazlauskas

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)
V3:
* Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7..852a2100c6b3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5..2f72745660fb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa..97fd70df531b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.38.1


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

* [PATCH v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:25     ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:25 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Alex Hung,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui, Roman Li, stable,
	Christian König, Thomas Zimmermann, Wayne Lin, Alex Deucher,
	Nicholas Kazlauskas

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)
V3:
* Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7..852a2100c6b3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5..2f72745660fb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa..97fd70df531b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.38.1


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

* [PATCH v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:25     ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:25 UTC (permalink / raw)
  To: amd-gfx
  Cc: Wayne Lin, Harry Wentland, stable, Leo Li, Rodrigo Siqueira,
	Alex Deucher, Christian König, Pan, Xinhui, David Airlie,
	Daniel Vetter, Nicholas Kazlauskas, Aurabindo Pillai, Roman Li,
	Fangzhi Zuo, hersen wu, Thomas Zimmermann, Hamza Mahfooz,
	Alex Hung, David Francis, Wenjing Liu, Mikita Lipski,
	open list:DRM DRIVERS, open list

It appears that amdgpu makes the mistake of completely ignoring the return
values from the DP MST helpers, and instead just returns a simple
true/false. In this case, it seems to have come back to bite us because as
a result of simply returning false from
compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
deadlock happened from these helpers. This could definitely result in some
kernel splats.

V2:
* Address Wayne's comments (fix another bunch of spots where we weren't
  passing down return codes)
V3:
* Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

Signed-off-by: Lyude Paul <lyude@redhat.com>
Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: <stable@vger.kernel.org> # v5.6+
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
 3 files changed, 147 insertions(+), 118 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0db2a88cd4d7..852a2100c6b3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 	struct drm_connector_state *new_con_state;
 	struct amdgpu_dm_connector *aconnector;
 	struct dm_connector_state *dm_conn_state;
-	int i, j;
+	int i, j, ret;
 	int vcpi, pbn_div, pbn, slot_num = 0;
 
 	for_each_new_connector_in_state(state, connector, new_con_state, i) {
@@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 			dm_conn_state->pbn = pbn;
 			dm_conn_state->vcpi_slots = slot_num;
 
-			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
-						     false);
+			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+							   dm_conn_state->pbn, false);
+			if (ret < 0)
+				return ret;
+
 			continue;
 		}
 
@@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (dc_resource_is_dsc_encoding_supported(dc)) {
-		if (!pre_validate_dsc(state, &dm_state, vars)) {
-			ret = -EINVAL;
+		ret = pre_validate_dsc(state, &dm_state, vars);
+		if (ret != 0)
 			goto fail;
-		}
 	}
 #endif
 
@@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
+		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
+		if (ret) {
 			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
-			ret = -EINVAL;
 			goto fail;
 		}
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6ff96b4bdda5..2f72745660fb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
 	return dsc_config.bits_per_pixel;
 }
 
-static bool increase_dsc_bpp(struct drm_atomic_state *state,
-			     struct drm_dp_mst_topology_state *mst_state,
-			     struct dc_link *dc_link,
-			     struct dsc_mst_fairness_params *params,
-			     struct dsc_mst_fairness_vars *vars,
-			     int count,
-			     int k)
+static int increase_dsc_bpp(struct drm_atomic_state *state,
+			    struct drm_dp_mst_topology_state *mst_state,
+			    struct dc_link *dc_link,
+			    struct dsc_mst_fairness_params *params,
+			    struct dsc_mst_fairness_vars *vars,
+			    int count,
+			    int k)
 {
 	int i;
 	bool bpp_increased[MAX_PIPES];
@@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 	int remaining_to_increase = 0;
 	int link_timeslots_used;
 	int fair_pbn_alloc;
+	int ret = 0;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled) {
@@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
 
 		if (initial_slack[next_index] > fair_pbn_alloc) {
 			vars[next_index].pbn += fair_pbn_alloc;
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
 			} else {
 				vars[next_index].pbn -= fair_pbn_alloc;
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		} else {
 			vars[next_index].pbn += initial_slack[next_index];
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
-			if (!drm_dp_mst_atomic_check(state)) {
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
+
+			ret = drm_dp_mst_atomic_check(state);
+			if (ret == 0) {
 				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
 			} else {
 				vars[next_index].pbn -= initial_slack[next_index];
-				if (drm_dp_atomic_find_time_slots(state,
-								  params[next_index].port->mgr,
-								  params[next_index].port,
-								  vars[next_index].pbn) < 0)
-					return false;
+				ret = drm_dp_atomic_find_time_slots(state,
+								    params[next_index].port->mgr,
+								    params[next_index].port,
+								    vars[next_index].pbn);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
 		bpp_increased[next_index] = true;
 		remaining_to_increase--;
 	}
-	return true;
+	return 0;
 }
 
-static bool try_disable_dsc(struct drm_atomic_state *state,
-			    struct dc_link *dc_link,
-			    struct dsc_mst_fairness_params *params,
-			    struct dsc_mst_fairness_vars *vars,
-			    int count,
-			    int k)
+static int try_disable_dsc(struct drm_atomic_state *state,
+			   struct dc_link *dc_link,
+			   struct dsc_mst_fairness_params *params,
+			   struct dsc_mst_fairness_vars *vars,
+			   int count,
+			   int k)
 {
 	int i;
 	bool tried[MAX_PIPES];
@@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 	int max_kbps_increase;
 	int next_index;
 	int remaining_to_try = 0;
+	int ret;
 
 	for (i = 0; i < count; i++) {
 		if (vars[i + k].dsc_enabled
@@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
 			break;
 
 		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
-		if (drm_dp_atomic_find_time_slots(state,
-						  params[next_index].port->mgr,
-						  params[next_index].port,
-						  vars[next_index].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state,
+						    params[next_index].port->mgr,
+						    params[next_index].port,
+						    vars[next_index].pbn);
+		if (ret < 0)
+			return ret;
 
-		if (!drm_dp_mst_atomic_check(state)) {
+		ret = drm_dp_mst_atomic_check(state);
+		if (ret == 0) {
 			vars[next_index].dsc_enabled = false;
 			vars[next_index].bpp_x16 = 0;
 		} else {
 			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
-			if (drm_dp_atomic_find_time_slots(state,
-							  params[next_index].port->mgr,
-							  params[next_index].port,
-							  vars[next_index].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state,
+							    params[next_index].port->mgr,
+							    params[next_index].port,
+							    vars[next_index].pbn);
+			if (ret < 0)
+				return ret;
 		}
 
 		tried[next_index] = true;
 		remaining_to_try--;
 	}
-	return true;
+	return 0;
 }
 
-static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
-					     struct dc_state *dc_state,
-					     struct dc_link *dc_link,
-					     struct dsc_mst_fairness_vars *vars,
-					     struct drm_dp_mst_topology_mgr *mgr,
-					     int *link_vars_start_index)
+static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
+					    struct dc_state *dc_state,
+					    struct dc_link *dc_link,
+					    struct dsc_mst_fairness_vars *vars,
+					    struct drm_dp_mst_topology_mgr *mgr,
+					    int *link_vars_start_index)
 {
 	struct dc_stream_state *stream;
 	struct dsc_mst_fairness_params params[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
 	int count = 0;
-	int i, k;
+	int i, k, ret;
 	bool debugfs_overwrite = false;
 
 	memset(params, 0, sizeof(params));
 
 	if (IS_ERR(mst_state))
-		return false;
+		return PTR_ERR(mst_state);
 
 	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
@@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 
 	if (count == 0) {
 		ASSERT(0);
-		return true;
+		return 0;
 	}
 
 	/* k is start index of vars for current phy link used by mst hub */
@@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 		vars[i + k].dsc_enabled = false;
 		vars[i + k].bpp_x16 = 0;
-		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
-						  vars[i + k].pbn) < 0)
-			return false;
+		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
+						    vars[i + k].pbn);
+		if (ret < 0)
+			return ret;
 	}
-	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret == 0 && !debugfs_overwrite) {
 		set_dsc_configs_from_fairness_vars(params, vars, count, k);
-		return true;
+		return 0;
+	} else if (ret != -ENOSPC) {
+		return ret;
 	}
 
 	/* Try max compression */
@@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
 			vars[i + k].dsc_enabled = true;
 			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		} else {
 			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
 			vars[i + k].dsc_enabled = false;
 			vars[i + k].bpp_x16 = 0;
-			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
-							  params[i].port, vars[i + k].pbn) < 0)
-				return false;
+			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
+							    params[i].port, vars[i + k].pbn);
+			if (ret < 0)
+				return ret;
 		}
 	}
-	if (drm_dp_mst_atomic_check(state))
-		return false;
+	ret = drm_dp_mst_atomic_check(state);
+	if (ret != 0)
+		return ret;
 
 	/* Optimize degree of compression */
-	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
-		return false;
+	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
-	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
-		return false;
+	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
+	if (ret < 0)
+		return ret;
 
 	set_dsc_configs_from_fairness_vars(params, vars, count, k);
 
-	return true;
+	return 0;
 }
 
 static bool is_dsc_need_re_compute(
@@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
 	return is_dsc_need_re_compute;
 }
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars)
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 			continue;
 
 		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
-			return false;
+			return -EINVAL;
 
 		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
 
 		if (stream->timing.flags.DSC == 1)
 			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
-				return false;
+				return -EINVAL;
 	}
 
-	return true;
+	return ret;
 }
 
-static bool
-	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-					      struct dc_state *dc_state,
-					      struct dsc_mst_fairness_vars *vars)
+static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+						 struct dc_state *dc_state,
+						 struct dsc_mst_fairness_vars *vars)
 {
 	int i, j;
 	struct dc_stream_state *stream;
 	bool computed_streams[MAX_PIPES];
 	struct amdgpu_dm_connector *aconnector;
 	int link_vars_start_index = 0;
+	int ret = 0;
 
 	for (i = 0; i < dc_state->stream_count; i++)
 		computed_streams[i] = false;
@@ -1184,11 +1209,12 @@ static bool
 			continue;
 
 		mutex_lock(&aconnector->mst_mgr.lock);
-		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
-						      &aconnector->mst_mgr,
-						      &link_vars_start_index)) {
+		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
+						       &aconnector->mst_mgr,
+						       &link_vars_start_index);
+		if (ret != 0) {
 			mutex_unlock(&aconnector->mst_mgr.lock);
-			return false;
+			return ret;
 		}
 		mutex_unlock(&aconnector->mst_mgr.lock);
 
@@ -1198,7 +1224,7 @@ static bool
 		}
 	}
 
-	return true;
+	return ret;
 }
 
 static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
@@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
 	return ret;
 }
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars)
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars)
 {
 	int i;
 	struct dm_atomic_state *dm_state;
@@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	if (!is_dsc_precompute_needed(state)) {
 		DRM_INFO_ONCE("DSC precompute is not needed.\n");
-		return true;
+		return 0;
 	}
-	if (dm_atomic_get_state(state, dm_state_ptr)) {
+	ret = dm_atomic_get_state(state, dm_state_ptr);
+	if (ret != 0) {
 		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
-		return false;
+		return ret;
 	}
 	dm_state = *dm_state_ptr;
 
@@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
 	if (!local_dc_state)
-		return false;
+		return -ENOMEM;
 
 	for (i = 0; i < local_dc_state->stream_count; i++) {
 		struct dc_stream_state *stream = dm_state->context->streams[i];
@@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 	if (ret != 0)
 		goto clean_exit;
 
-	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
+	if (ret != 0) {
 		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
-		ret = -EINVAL;
 		goto clean_exit;
 	}
 
@@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
 
 	kfree(local_dc_state);
 
-	return (ret == 0);
+	return ret;
 }
 
 static unsigned int kbps_from_pbn(unsigned int pbn)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index b92a7c5671aa..97fd70df531b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
 	struct amdgpu_dm_connector *aconnector;
 };
 
-bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
-				       struct dc_state *dc_state,
-				       struct dsc_mst_fairness_vars *vars);
+int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+				      struct dc_state *dc_state,
+				      struct dsc_mst_fairness_vars *vars);
 
 bool needs_dsc_aux_workaround(struct dc_link *link);
 
-bool pre_validate_dsc(struct drm_atomic_state *state,
-		      struct dm_atomic_state **dm_state_ptr,
-		      struct dsc_mst_fairness_vars *vars);
+int pre_validate_dsc(struct drm_atomic_state *state,
+		     struct dm_atomic_state **dm_state_ptr,
+		     struct dsc_mst_fairness_vars *vars);
 
 enum dc_status dm_dp_mst_is_port_support_mode(
 	struct amdgpu_dm_connector *aconnector,
-- 
2.38.1


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:17       ` Lyude Paul
  (?)
@ 2022-11-18 19:46         ` Alex Deucher
  -1 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 19:46 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Lin, Wayne, amd-gfx, Liu, Wenjing, open list:DRM DRIVERS,
	open list, Mahfooz, Hamza, David Airlie, Francis, David,
	Siqueira, Rodrigo, Hung, Alex, Zuo, Jerry, Pillai, Aurabindo,
	Wentland, Harry, Daniel Vetter, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

I've already picked this up.  Can you send a follow up patch with just
the coverity fix?

Alex

On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI, Coverity pointed out one more issue with this series so I'm going to
> send out a respin real quick to fix it. It's just a missing variable
> assignment (we leave ret unassigned by mistake in
> pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
>
> On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > [Public]
> >
> > All the patch set looks good to me. Feel free to add:
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> >
> > Again, thank you Lyude for helping on this!!!
> >
> > Regards,
> > Wayne
> > > -----Original Message-----
> > > From: Lyude Paul <lyude@redhat.com>
> > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > To: amd-gfx@lists.freedesktop.org
> > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > deadlocking
> > >
> > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > In this case, it seems to have come back to bite us because as a result of
> > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > had no way of telling when a deadlock happened from these helpers. This
> > > could definitely result in some kernel splats.
> > >
> > > V2:
> > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > >   passing down return codes)
> > >
> > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: <stable@vger.kernel.org> # v5.6+
> > > ---
> > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > --
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > @@ -6462,7 +6462,7 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >     struct drm_connector_state *new_con_state;
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct dm_connector_state *dm_conn_state;
> > > -   int i, j;
> > > +   int i, j, ret;
> > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > >
> > >     for_each_new_connector_in_state(state, connector,
> > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >                     dm_conn_state->pbn = pbn;
> > >                     dm_conn_state->vcpi_slots = slot_num;
> > >
> > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > port, dm_conn_state->pbn,
> > > -                                                false);
> > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > aconnector->port,
> > > +                                                      dm_conn_state-
> > > > pbn, false);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > >                     continue;
> > >             }
> > >
> > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > -                   ret = -EINVAL;
> > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > +           if (ret != 0)
> > >                     goto fail;
> > > -           }
> > >     }
> > >  #endif
> > >
> > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >             }
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars)) {
> > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars);
> > > +           if (ret) {
> > >
> > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -                   ret = -EINVAL;
> > >                     goto fail;
> > >             }
> > >
> > > diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > dsc_mst_fairness_params param, int pbn)
> > >     return dsc_config.bits_per_pixel;
> > >  }
> > >
> > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > -                        struct dc_link *dc_link,
> > > -                        struct dsc_mst_fairness_params *params,
> > > -                        struct dsc_mst_fairness_vars *vars,
> > > -                        int count,
> > > -                        int k)
> > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > +                       struct dc_link *dc_link,
> > > +                       struct dsc_mst_fairness_params *params,
> > > +                       struct dsc_mst_fairness_vars *vars,
> > > +                       int count,
> > > +                       int k)
> > >  {
> > >     int i;
> > >     bool bpp_increased[MAX_PIPES];
> > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >     int remaining_to_increase = 0;
> > >     int link_timeslots_used;
> > >     int fair_pbn_alloc;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled) {
> > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >
> > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > >                     } else {
> > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             } else {
> > >                     vars[next_index].pbn += initial_slack[next_index];
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > params[next_index].bw_range.max_target_bpp_x16;
> > >                     } else {
> > >                             vars[next_index].pbn -=
> > > initial_slack[next_index];
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             }
> > >
> > >             bpp_increased[next_index] = true;
> > >             remaining_to_increase--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > -                       struct dc_link *dc_link,
> > > -                       struct dsc_mst_fairness_params *params,
> > > -                       struct dsc_mst_fairness_vars *vars,
> > > -                       int count,
> > > -                       int k)
> > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > +                      struct dc_link *dc_link,
> > > +                      struct dsc_mst_fairness_params *params,
> > > +                      struct dsc_mst_fairness_vars *vars,
> > > +                      int count,
> > > +                      int k)
> > >  {
> > >     int i;
> > >     bool tried[MAX_PIPES];
> > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > *state,
> > >     int max_kbps_increase;
> > >     int next_index;
> > >     int remaining_to_try = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled
> > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > drm_atomic_state *state,
> > >                     break;
> > >
> > >             vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > -           if (drm_dp_atomic_find_time_slots(state,
> > > -                                             params[next_index].port-
> > > > mgr,
> > > -                                             params[next_index].port,
> > > -                                             vars[next_index].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > +                                               params[next_index].port-
> > > > mgr,
> > > +                                               params[next_index].port,
> > > +                                               vars[next_index].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >
> > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > +           ret = drm_dp_mst_atomic_check(state);
> > > +           if (ret == 0) {
> > >                     vars[next_index].dsc_enabled = false;
> > >                     vars[next_index].bpp_x16 = 0;
> > >             } else {
> > >                     vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >
> > >             tried[next_index] = true;
> > >             remaining_to_try--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > -                                        struct dc_state *dc_state,
> > > -                                        struct dc_link *dc_link,
> > > -                                        struct dsc_mst_fairness_vars *vars,
> > > -                                        struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > -                                        int *link_vars_start_index)
> > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > +                                       struct dc_state *dc_state,
> > > +                                       struct dc_link *dc_link,
> > > +                                       struct dsc_mst_fairness_vars *vars,
> > > +                                       struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > +                                       int *link_vars_start_index)
> > >  {
> > >     struct dc_stream_state *stream;
> > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct drm_dp_mst_topology_state *mst_state =
> > > drm_atomic_get_mst_topology_state(state, mgr);
> > >     int count = 0;
> > > -   int i, k;
> > > +   int i, k, ret;
> > >     bool debugfs_overwrite = false;
> > >
> > >     memset(params, 0, sizeof(params));
> > >
> > >     if (IS_ERR(mst_state))
> > > -           return false;
> > > +           return PTR_ERR(mst_state);
> > >
> > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >
> > >     if (count == 0) {
> > >             ASSERT(0);
> > > -           return true;
> > > +           return 0;
> > >     }
> > >
> > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > drm_atomic_state *state,
> > >             vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >             vars[i + k].dsc_enabled = false;
> > >             vars[i + k].bpp_x16 = 0;
> > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > -                                             vars[i + k].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > +                                               vars[i + k].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >     }
> > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret == 0 && !debugfs_overwrite) {
> > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > -           return true;
> > > +           return 0;
> > > +   } else if (ret != -ENOSPC) {
> > > +           return ret;
> > >     }
> > >
> > >     /* Try max compression */
> > > @@ -962,31 +979,36 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > >                     vars[i + k].dsc_enabled = true;
> > >                     vars[i + k].bpp_x16 =
> > > params[i].bw_range.min_target_bpp_x16;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             } else {
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >                     vars[i + k].dsc_enabled = false;
> > >                     vars[i + k].bpp_x16 = 0;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >     }
> > > -   if (drm_dp_mst_atomic_check(state))
> > > -           return false;
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret != 0)
> > > +           return ret;
> > >
> > >     /* Optimize degree of compression */
> > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > k))
> > > -           return false;
> > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > -           return false;
> > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > >
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > >  static bool is_dsc_need_re_compute(
> > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > >     return is_dsc_need_re_compute;
> > >  }
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars)
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >                     continue;
> > >
> > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > dc_state, stream) != DC_OK)
> > > -                   return false;
> > > +                   return -EINVAL;
> > >
> > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >
> > >             if (stream->timing.flags.DSC == 1)
> > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > dc, dc_state, stream) != DC_OK)
> > > -                           return false;
> > > +                           return -EINVAL;
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > > -static bool
> > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > *state,
> > > -                                         struct dc_state *dc_state,
> > > -                                         struct dsc_mst_fairness_vars
> > > *vars)
> > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > > +                                            struct dc_state *dc_state,
> > > +                                            struct dsc_mst_fairness_vars
> > > *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1184,11 +1209,12 @@ static bool
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1198,7 +1224,7 @@ static bool
> > >             }
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > >     return ret;
> > >  }
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars)
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i;
> > >     struct dm_atomic_state *dm_state;
> > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     if (!is_dsc_precompute_needed(state)) {
> > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > -           return true;
> > > +           return 0;
> > >     }
> > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > +   if (ret != 0) {
> > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > -           return false;
> > > +           return ret;
> > >     }
> > >     dm_state = *dm_state_ptr;
> > >
> > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > dc_state), GFP_KERNEL);
> > >     if (!local_dc_state)
> > > -           return false;
> > > +           return -ENOMEM;
> > >
> > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > >             struct dc_stream_state *stream = dm_state->context-
> > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > drm_atomic_state *state,
> > >     if (ret != 0)
> > >             goto clean_exit;
> > >
> > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars)) {
> > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars);
> > > +   if (ret != 0) {
> > >
> > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -           ret = -EINVAL;
> > >             goto clean_exit;
> > >     }
> > >
> > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     kfree(local_dc_state);
> > >
> > > -   return (ret == 0);
> > > +   return ret;
> > >  }
> > >
> > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > index b92a7c5671aa2..97fd70df531bf 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > >     struct amdgpu_dm_connector *aconnector;  };
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars);
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars);
> > >
> > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars);
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars);
> > >
> > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > >     struct amdgpu_dm_connector *aconnector,
> > > --
> > > 2.37.3
> >
>
> --
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
>

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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:46         ` Alex Deucher
  0 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 19:46 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, amd-gfx, Li, Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Hung, Alex, Wu, Hersen,
	Mikita Lipski, Pan, Xinhui, open list, stable, Kazlauskas,
	Nicholas, Thomas Zimmermann, Lin, Wayne, Deucher, Alexander,
	Koenig, Christian

I've already picked this up.  Can you send a follow up patch with just
the coverity fix?

Alex

On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI, Coverity pointed out one more issue with this series so I'm going to
> send out a respin real quick to fix it. It's just a missing variable
> assignment (we leave ret unassigned by mistake in
> pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
>
> On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > [Public]
> >
> > All the patch set looks good to me. Feel free to add:
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> >
> > Again, thank you Lyude for helping on this!!!
> >
> > Regards,
> > Wayne
> > > -----Original Message-----
> > > From: Lyude Paul <lyude@redhat.com>
> > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > To: amd-gfx@lists.freedesktop.org
> > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > deadlocking
> > >
> > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > In this case, it seems to have come back to bite us because as a result of
> > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > had no way of telling when a deadlock happened from these helpers. This
> > > could definitely result in some kernel splats.
> > >
> > > V2:
> > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > >   passing down return codes)
> > >
> > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: <stable@vger.kernel.org> # v5.6+
> > > ---
> > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > --
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > @@ -6462,7 +6462,7 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >     struct drm_connector_state *new_con_state;
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct dm_connector_state *dm_conn_state;
> > > -   int i, j;
> > > +   int i, j, ret;
> > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > >
> > >     for_each_new_connector_in_state(state, connector,
> > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >                     dm_conn_state->pbn = pbn;
> > >                     dm_conn_state->vcpi_slots = slot_num;
> > >
> > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > port, dm_conn_state->pbn,
> > > -                                                false);
> > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > aconnector->port,
> > > +                                                      dm_conn_state-
> > > > pbn, false);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > >                     continue;
> > >             }
> > >
> > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > -                   ret = -EINVAL;
> > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > +           if (ret != 0)
> > >                     goto fail;
> > > -           }
> > >     }
> > >  #endif
> > >
> > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >             }
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars)) {
> > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars);
> > > +           if (ret) {
> > >
> > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -                   ret = -EINVAL;
> > >                     goto fail;
> > >             }
> > >
> > > diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > dsc_mst_fairness_params param, int pbn)
> > >     return dsc_config.bits_per_pixel;
> > >  }
> > >
> > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > -                        struct dc_link *dc_link,
> > > -                        struct dsc_mst_fairness_params *params,
> > > -                        struct dsc_mst_fairness_vars *vars,
> > > -                        int count,
> > > -                        int k)
> > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > +                       struct dc_link *dc_link,
> > > +                       struct dsc_mst_fairness_params *params,
> > > +                       struct dsc_mst_fairness_vars *vars,
> > > +                       int count,
> > > +                       int k)
> > >  {
> > >     int i;
> > >     bool bpp_increased[MAX_PIPES];
> > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >     int remaining_to_increase = 0;
> > >     int link_timeslots_used;
> > >     int fair_pbn_alloc;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled) {
> > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >
> > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > >                     } else {
> > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             } else {
> > >                     vars[next_index].pbn += initial_slack[next_index];
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > params[next_index].bw_range.max_target_bpp_x16;
> > >                     } else {
> > >                             vars[next_index].pbn -=
> > > initial_slack[next_index];
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             }
> > >
> > >             bpp_increased[next_index] = true;
> > >             remaining_to_increase--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > -                       struct dc_link *dc_link,
> > > -                       struct dsc_mst_fairness_params *params,
> > > -                       struct dsc_mst_fairness_vars *vars,
> > > -                       int count,
> > > -                       int k)
> > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > +                      struct dc_link *dc_link,
> > > +                      struct dsc_mst_fairness_params *params,
> > > +                      struct dsc_mst_fairness_vars *vars,
> > > +                      int count,
> > > +                      int k)
> > >  {
> > >     int i;
> > >     bool tried[MAX_PIPES];
> > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > *state,
> > >     int max_kbps_increase;
> > >     int next_index;
> > >     int remaining_to_try = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled
> > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > drm_atomic_state *state,
> > >                     break;
> > >
> > >             vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > -           if (drm_dp_atomic_find_time_slots(state,
> > > -                                             params[next_index].port-
> > > > mgr,
> > > -                                             params[next_index].port,
> > > -                                             vars[next_index].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > +                                               params[next_index].port-
> > > > mgr,
> > > +                                               params[next_index].port,
> > > +                                               vars[next_index].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >
> > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > +           ret = drm_dp_mst_atomic_check(state);
> > > +           if (ret == 0) {
> > >                     vars[next_index].dsc_enabled = false;
> > >                     vars[next_index].bpp_x16 = 0;
> > >             } else {
> > >                     vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >
> > >             tried[next_index] = true;
> > >             remaining_to_try--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > -                                        struct dc_state *dc_state,
> > > -                                        struct dc_link *dc_link,
> > > -                                        struct dsc_mst_fairness_vars *vars,
> > > -                                        struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > -                                        int *link_vars_start_index)
> > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > +                                       struct dc_state *dc_state,
> > > +                                       struct dc_link *dc_link,
> > > +                                       struct dsc_mst_fairness_vars *vars,
> > > +                                       struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > +                                       int *link_vars_start_index)
> > >  {
> > >     struct dc_stream_state *stream;
> > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct drm_dp_mst_topology_state *mst_state =
> > > drm_atomic_get_mst_topology_state(state, mgr);
> > >     int count = 0;
> > > -   int i, k;
> > > +   int i, k, ret;
> > >     bool debugfs_overwrite = false;
> > >
> > >     memset(params, 0, sizeof(params));
> > >
> > >     if (IS_ERR(mst_state))
> > > -           return false;
> > > +           return PTR_ERR(mst_state);
> > >
> > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >
> > >     if (count == 0) {
> > >             ASSERT(0);
> > > -           return true;
> > > +           return 0;
> > >     }
> > >
> > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > drm_atomic_state *state,
> > >             vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >             vars[i + k].dsc_enabled = false;
> > >             vars[i + k].bpp_x16 = 0;
> > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > -                                             vars[i + k].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > +                                               vars[i + k].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >     }
> > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret == 0 && !debugfs_overwrite) {
> > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > -           return true;
> > > +           return 0;
> > > +   } else if (ret != -ENOSPC) {
> > > +           return ret;
> > >     }
> > >
> > >     /* Try max compression */
> > > @@ -962,31 +979,36 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > >                     vars[i + k].dsc_enabled = true;
> > >                     vars[i + k].bpp_x16 =
> > > params[i].bw_range.min_target_bpp_x16;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             } else {
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >                     vars[i + k].dsc_enabled = false;
> > >                     vars[i + k].bpp_x16 = 0;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >     }
> > > -   if (drm_dp_mst_atomic_check(state))
> > > -           return false;
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret != 0)
> > > +           return ret;
> > >
> > >     /* Optimize degree of compression */
> > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > k))
> > > -           return false;
> > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > -           return false;
> > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > >
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > >  static bool is_dsc_need_re_compute(
> > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > >     return is_dsc_need_re_compute;
> > >  }
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars)
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >                     continue;
> > >
> > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > dc_state, stream) != DC_OK)
> > > -                   return false;
> > > +                   return -EINVAL;
> > >
> > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >
> > >             if (stream->timing.flags.DSC == 1)
> > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > dc, dc_state, stream) != DC_OK)
> > > -                           return false;
> > > +                           return -EINVAL;
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > > -static bool
> > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > *state,
> > > -                                         struct dc_state *dc_state,
> > > -                                         struct dsc_mst_fairness_vars
> > > *vars)
> > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > > +                                            struct dc_state *dc_state,
> > > +                                            struct dsc_mst_fairness_vars
> > > *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1184,11 +1209,12 @@ static bool
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1198,7 +1224,7 @@ static bool
> > >             }
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > >     return ret;
> > >  }
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars)
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i;
> > >     struct dm_atomic_state *dm_state;
> > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     if (!is_dsc_precompute_needed(state)) {
> > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > -           return true;
> > > +           return 0;
> > >     }
> > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > +   if (ret != 0) {
> > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > -           return false;
> > > +           return ret;
> > >     }
> > >     dm_state = *dm_state_ptr;
> > >
> > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > dc_state), GFP_KERNEL);
> > >     if (!local_dc_state)
> > > -           return false;
> > > +           return -ENOMEM;
> > >
> > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > >             struct dc_stream_state *stream = dm_state->context-
> > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > drm_atomic_state *state,
> > >     if (ret != 0)
> > >             goto clean_exit;
> > >
> > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars)) {
> > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars);
> > > +   if (ret != 0) {
> > >
> > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -           ret = -EINVAL;
> > >             goto clean_exit;
> > >     }
> > >
> > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     kfree(local_dc_state);
> > >
> > > -   return (ret == 0);
> > > +   return ret;
> > >  }
> > >
> > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > index b92a7c5671aa2..97fd70df531bf 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > >     struct amdgpu_dm_connector *aconnector;  };
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars);
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars);
> > >
> > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars);
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars);
> > >
> > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > >     struct amdgpu_dm_connector *aconnector,
> > > --
> > > 2.37.3
> >
>
> --
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
>

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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:46         ` Alex Deucher
  0 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 19:46 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, amd-gfx, Li,
	Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Hung, Alex, Wu, Hersen, Mikita Lipski, Pan, Xinhui, open list,
	stable, Kazlauskas, Nicholas, Thomas Zimmermann, Lin, Wayne,
	Deucher, Alexander, Koenig, Christian

I've already picked this up.  Can you send a follow up patch with just
the coverity fix?

Alex

On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI, Coverity pointed out one more issue with this series so I'm going to
> send out a respin real quick to fix it. It's just a missing variable
> assignment (we leave ret unassigned by mistake in
> pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
>
> On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > [Public]
> >
> > All the patch set looks good to me. Feel free to add:
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> >
> > Again, thank you Lyude for helping on this!!!
> >
> > Regards,
> > Wayne
> > > -----Original Message-----
> > > From: Lyude Paul <lyude@redhat.com>
> > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > To: amd-gfx@lists.freedesktop.org
> > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > deadlocking
> > >
> > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > In this case, it seems to have come back to bite us because as a result of
> > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > had no way of telling when a deadlock happened from these helpers. This
> > > could definitely result in some kernel splats.
> > >
> > > V2:
> > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > >   passing down return codes)
> > >
> > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > Cc: <stable@vger.kernel.org> # v5.6+
> > > ---
> > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > --
> > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > @@ -6462,7 +6462,7 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >     struct drm_connector_state *new_con_state;
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct dm_connector_state *dm_conn_state;
> > > -   int i, j;
> > > +   int i, j, ret;
> > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > >
> > >     for_each_new_connector_in_state(state, connector,
> > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > >                     dm_conn_state->pbn = pbn;
> > >                     dm_conn_state->vcpi_slots = slot_num;
> > >
> > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > port, dm_conn_state->pbn,
> > > -                                                false);
> > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > aconnector->port,
> > > +                                                      dm_conn_state-
> > > > pbn, false);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > >                     continue;
> > >             }
> > >
> > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > -                   ret = -EINVAL;
> > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > +           if (ret != 0)
> > >                     goto fail;
> > > -           }
> > >     }
> > >  #endif
> > >
> > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > drm_device *dev,
> > >             }
> > >
> > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars)) {
> > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > context, vars);
> > > +           if (ret) {
> > >
> > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -                   ret = -EINVAL;
> > >                     goto fail;
> > >             }
> > >
> > > diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > dsc_mst_fairness_params param, int pbn)
> > >     return dsc_config.bits_per_pixel;
> > >  }
> > >
> > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > -                        struct dc_link *dc_link,
> > > -                        struct dsc_mst_fairness_params *params,
> > > -                        struct dsc_mst_fairness_vars *vars,
> > > -                        int count,
> > > -                        int k)
> > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > +                       struct dc_link *dc_link,
> > > +                       struct dsc_mst_fairness_params *params,
> > > +                       struct dsc_mst_fairness_vars *vars,
> > > +                       int count,
> > > +                       int k)
> > >  {
> > >     int i;
> > >     bool bpp_increased[MAX_PIPES];
> > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >     int remaining_to_increase = 0;
> > >     int link_timeslots_used;
> > >     int fair_pbn_alloc;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled) {
> > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > drm_atomic_state *state,
> > >
> > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > >                     } else {
> > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             } else {
> > >                     vars[next_index].pbn += initial_slack[next_index];
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > > +
> > > +                   ret = drm_dp_mst_atomic_check(state);
> > > +                   if (ret == 0) {
> > >                             vars[next_index].bpp_x16 =
> > > params[next_index].bw_range.max_target_bpp_x16;
> > >                     } else {
> > >                             vars[next_index].pbn -=
> > > initial_slack[next_index];
> > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                                   return false;
> > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                           if (ret < 0)
> > > +                                   return ret;
> > >                     }
> > >             }
> > >
> > >             bpp_increased[next_index] = true;
> > >             remaining_to_increase--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > -                       struct dc_link *dc_link,
> > > -                       struct dsc_mst_fairness_params *params,
> > > -                       struct dsc_mst_fairness_vars *vars,
> > > -                       int count,
> > > -                       int k)
> > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > +                      struct dc_link *dc_link,
> > > +                      struct dsc_mst_fairness_params *params,
> > > +                      struct dsc_mst_fairness_vars *vars,
> > > +                      int count,
> > > +                      int k)
> > >  {
> > >     int i;
> > >     bool tried[MAX_PIPES];
> > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > *state,
> > >     int max_kbps_increase;
> > >     int next_index;
> > >     int remaining_to_try = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < count; i++) {
> > >             if (vars[i + k].dsc_enabled
> > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > drm_atomic_state *state,
> > >                     break;
> > >
> > >             vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > -           if (drm_dp_atomic_find_time_slots(state,
> > > -                                             params[next_index].port-
> > > > mgr,
> > > -                                             params[next_index].port,
> > > -                                             vars[next_index].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > +                                               params[next_index].port-
> > > > mgr,
> > > +                                               params[next_index].port,
> > > +                                               vars[next_index].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >
> > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > +           ret = drm_dp_mst_atomic_check(state);
> > > +           if (ret == 0) {
> > >                     vars[next_index].dsc_enabled = false;
> > >                     vars[next_index].bpp_x16 = 0;
> > >             } else {
> > >                     vars[next_index].pbn =
> > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > -
> > > params[next_index].port->mgr,
> > > -
> > > params[next_index].port,
> > > -
> > > vars[next_index].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > +
> > > params[next_index].port->mgr,
> > > +
> > > params[next_index].port,
> > > +
> > > vars[next_index].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >
> > >             tried[next_index] = true;
> > >             remaining_to_try--;
> > >     }
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > -                                        struct dc_state *dc_state,
> > > -                                        struct dc_link *dc_link,
> > > -                                        struct dsc_mst_fairness_vars *vars,
> > > -                                        struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > -                                        int *link_vars_start_index)
> > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > *state,
> > > +                                       struct dc_state *dc_state,
> > > +                                       struct dc_link *dc_link,
> > > +                                       struct dsc_mst_fairness_vars *vars,
> > > +                                       struct drm_dp_mst_topology_mgr
> > > *mgr,
> > > +                                       int *link_vars_start_index)
> > >  {
> > >     struct dc_stream_state *stream;
> > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     struct drm_dp_mst_topology_state *mst_state =
> > > drm_atomic_get_mst_topology_state(state, mgr);
> > >     int count = 0;
> > > -   int i, k;
> > > +   int i, k, ret;
> > >     bool debugfs_overwrite = false;
> > >
> > >     memset(params, 0, sizeof(params));
> > >
> > >     if (IS_ERR(mst_state))
> > > -           return false;
> > > +           return PTR_ERR(mst_state);
> > >
> > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >
> > >     if (count == 0) {
> > >             ASSERT(0);
> > > -           return true;
> > > +           return 0;
> > >     }
> > >
> > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > drm_atomic_state *state,
> > >             vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >             vars[i + k].dsc_enabled = false;
> > >             vars[i + k].bpp_x16 = 0;
> > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > -                                             vars[i + k].pbn) < 0)
> > > -                   return false;
> > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > mgr, params[i].port,
> > > +                                               vars[i + k].pbn);
> > > +           if (ret < 0)
> > > +                   return ret;
> > >     }
> > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret == 0 && !debugfs_overwrite) {
> > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > -           return true;
> > > +           return 0;
> > > +   } else if (ret != -ENOSPC) {
> > > +           return ret;
> > >     }
> > >
> > >     /* Try max compression */
> > > @@ -962,31 +979,36 @@ static bool
> > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > >                     vars[i + k].dsc_enabled = true;
> > >                     vars[i + k].bpp_x16 =
> > > params[i].bw_range.min_target_bpp_x16;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             } else {
> > >                     vars[i + k].pbn =
> > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > >                     vars[i + k].dsc_enabled = false;
> > >                     vars[i + k].bpp_x16 = 0;
> > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > -                                                     params[i].port, vars[i
> > > + k].pbn) < 0)
> > > -                           return false;
> > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > params[i].port->mgr,
> > > +                                                       params[i].port,
> > > vars[i + k].pbn);
> > > +                   if (ret < 0)
> > > +                           return ret;
> > >             }
> > >     }
> > > -   if (drm_dp_mst_atomic_check(state))
> > > -           return false;
> > > +   ret = drm_dp_mst_atomic_check(state);
> > > +   if (ret != 0)
> > > +           return ret;
> > >
> > >     /* Optimize degree of compression */
> > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > k))
> > > -           return false;
> > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > -           return false;
> > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > +   if (ret < 0)
> > > +           return ret;
> > >
> > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > >
> > > -   return true;
> > > +   return 0;
> > >  }
> > >
> > >  static bool is_dsc_need_re_compute(
> > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > >     return is_dsc_need_re_compute;
> > >  }
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars)
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret = 0;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >                     continue;
> > >
> > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > dc_state, stream) != DC_OK)
> > > -                   return false;
> > > +                   return -EINVAL;
> > >
> > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > >
> > >             if (stream->timing.flags.DSC == 1)
> > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > dc, dc_state, stream) != DC_OK)
> > > -                           return false;
> > > +                           return -EINVAL;
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > > -static bool
> > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > *state,
> > > -                                         struct dc_state *dc_state,
> > > -                                         struct dsc_mst_fairness_vars
> > > *vars)
> > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > drm_atomic_state *state,
> > > +                                            struct dc_state *dc_state,
> > > +                                            struct dsc_mst_fairness_vars
> > > *vars)
> > >  {
> > >     int i, j;
> > >     struct dc_stream_state *stream;
> > >     bool computed_streams[MAX_PIPES];
> > >     struct amdgpu_dm_connector *aconnector;
> > >     int link_vars_start_index = 0;
> > > +   int ret;
> > >
> > >     for (i = 0; i < dc_state->stream_count; i++)
> > >             computed_streams[i] = false;
> > > @@ -1184,11 +1209,12 @@ static bool
> > >                     continue;
> > >
> > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > -                                                 &aconnector->mst_mgr,
> > > -                                                 &link_vars_start_index)) {
> > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > stream->link, vars,
> > > +                                                  &aconnector->mst_mgr,
> > > +                                                  &link_vars_start_index);
> > > +           if (ret != 0) {
> > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > -                   return false;
> > > +                   return ret;
> > >             }
> > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > >
> > > @@ -1198,7 +1224,7 @@ static bool
> > >             }
> > >     }
> > >
> > > -   return true;
> > > +   return ret;
> > >  }
> > >
> > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > >     return ret;
> > >  }
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars)
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars)
> > >  {
> > >     int i;
> > >     struct dm_atomic_state *dm_state;
> > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     if (!is_dsc_precompute_needed(state)) {
> > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > -           return true;
> > > +           return 0;
> > >     }
> > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > +   if (ret != 0) {
> > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > -           return false;
> > > +           return ret;
> > >     }
> > >     dm_state = *dm_state_ptr;
> > >
> > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > dc_state), GFP_KERNEL);
> > >     if (!local_dc_state)
> > > -           return false;
> > > +           return -ENOMEM;
> > >
> > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > >             struct dc_stream_state *stream = dm_state->context-
> > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > drm_atomic_state *state,
> > >     if (ret != 0)
> > >             goto clean_exit;
> > >
> > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars)) {
> > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > vars);
> > > +   if (ret != 0) {
> > >
> > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > failed\n");
> > > -           ret = -EINVAL;
> > >             goto clean_exit;
> > >     }
> > >
> > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > *state,
> > >
> > >     kfree(local_dc_state);
> > >
> > > -   return (ret == 0);
> > > +   return ret;
> > >  }
> > >
> > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > index b92a7c5671aa2..97fd70df531bf 100644
> > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > +++
> > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > >     struct amdgpu_dm_connector *aconnector;  };
> > >
> > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > -                                  struct dc_state *dc_state,
> > > -                                  struct dsc_mst_fairness_vars *vars);
> > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > +                                 struct dc_state *dc_state,
> > > +                                 struct dsc_mst_fairness_vars *vars);
> > >
> > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > >
> > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > -                 struct dm_atomic_state **dm_state_ptr,
> > > -                 struct dsc_mst_fairness_vars *vars);
> > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > +                struct dm_atomic_state **dm_state_ptr,
> > > +                struct dsc_mst_fairness_vars *vars);
> > >
> > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > >     struct amdgpu_dm_connector *aconnector,
> > > --
> > > 2.37.3
> >
>
> --
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
>

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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:46         ` Alex Deucher
  (?)
@ 2022-11-18 19:47           ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:47 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, amd-gfx, Li, Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Hung, Alex, Wu, Hersen,
	Mikita Lipski, Pan, Xinhui, open list, stable, Kazlauskas,
	Nicholas, Thomas Zimmermann, Lin, Wayne, Deucher, Alexander,
	Koenig, Christian

of course, will do in just a moment

On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> I've already picked this up.  Can you send a follow up patch with just
> the coverity fix?
> 
> Alex
> 
> On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > 
> > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > send out a respin real quick to fix it. It's just a missing variable
> > assignment (we leave ret unassigned by mistake in
> > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > 
> > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > [Public]
> > > 
> > > All the patch set looks good to me. Feel free to add:
> > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > 
> > > Again, thank you Lyude for helping on this!!!
> > > 
> > > Regards,
> > > Wayne
> > > > -----Original Message-----
> > > > From: Lyude Paul <lyude@redhat.com>
> > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > To: amd-gfx@lists.freedesktop.org
> > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > deadlocking
> > > > 
> > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > In this case, it seems to have come back to bite us because as a result of
> > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > had no way of telling when a deadlock happened from these helpers. This
> > > > could definitely result in some kernel splats.
> > > > 
> > > > V2:
> > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > >   passing down return codes)
> > > > 
> > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > ---
> > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > --
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > @@ -6462,7 +6462,7 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >     struct drm_connector_state *new_con_state;
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct dm_connector_state *dm_conn_state;
> > > > -   int i, j;
> > > > +   int i, j, ret;
> > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > 
> > > >     for_each_new_connector_in_state(state, connector,
> > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >                     dm_conn_state->pbn = pbn;
> > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > 
> > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > port, dm_conn_state->pbn,
> > > > -                                                false);
> > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > aconnector->port,
> > > > +                                                      dm_conn_state-
> > > > > pbn, false);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > >                     continue;
> > > >             }
> > > > 
> > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > -                   ret = -EINVAL;
> > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > +           if (ret != 0)
> > > >                     goto fail;
> > > > -           }
> > > >     }
> > > >  #endif
> > > > 
> > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > >             }
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars)) {
> > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars);
> > > > +           if (ret) {
> > > > 
> > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -                   ret = -EINVAL;
> > > >                     goto fail;
> > > >             }
> > > > 
> > > > diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > dsc_mst_fairness_params param, int pbn)
> > > >     return dsc_config.bits_per_pixel;
> > > >  }
> > > > 
> > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > -                        struct dc_link *dc_link,
> > > > -                        struct dsc_mst_fairness_params *params,
> > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > -                        int count,
> > > > -                        int k)
> > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > +                       struct dc_link *dc_link,
> > > > +                       struct dsc_mst_fairness_params *params,
> > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > +                       int count,
> > > > +                       int k)
> > > >  {
> > > >     int i;
> > > >     bool bpp_increased[MAX_PIPES];
> > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > >     int remaining_to_increase = 0;
> > > >     int link_timeslots_used;
> > > >     int fair_pbn_alloc;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled) {
> > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > >                     } else {
> > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             } else {
> > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > params[next_index].bw_range.max_target_bpp_x16;
> > > >                     } else {
> > > >                             vars[next_index].pbn -=
> > > > initial_slack[next_index];
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             }
> > > > 
> > > >             bpp_increased[next_index] = true;
> > > >             remaining_to_increase--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > -                       struct dc_link *dc_link,
> > > > -                       struct dsc_mst_fairness_params *params,
> > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > -                       int count,
> > > > -                       int k)
> > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > +                      struct dc_link *dc_link,
> > > > +                      struct dsc_mst_fairness_params *params,
> > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > +                      int count,
> > > > +                      int k)
> > > >  {
> > > >     int i;
> > > >     bool tried[MAX_PIPES];
> > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > *state,
> > > >     int max_kbps_increase;
> > > >     int next_index;
> > > >     int remaining_to_try = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled
> > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > drm_atomic_state *state,
> > > >                     break;
> > > > 
> > > >             vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > -                                             params[next_index].port-
> > > > > mgr,
> > > > -                                             params[next_index].port,
> > > > -                                             vars[next_index].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > +                                               params[next_index].port-
> > > > > mgr,
> > > > +                                               params[next_index].port,
> > > > +                                               vars[next_index].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > > 
> > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > +           if (ret == 0) {
> > > >                     vars[next_index].dsc_enabled = false;
> > > >                     vars[next_index].bpp_x16 = 0;
> > > >             } else {
> > > >                     vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > > 
> > > >             tried[next_index] = true;
> > > >             remaining_to_try--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > -                                        struct dc_state *dc_state,
> > > > -                                        struct dc_link *dc_link,
> > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > -                                        struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > -                                        int *link_vars_start_index)
> > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > +                                       struct dc_state *dc_state,
> > > > +                                       struct dc_link *dc_link,
> > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > +                                       struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > +                                       int *link_vars_start_index)
> > > >  {
> > > >     struct dc_stream_state *stream;
> > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > >     int count = 0;
> > > > -   int i, k;
> > > > +   int i, k, ret;
> > > >     bool debugfs_overwrite = false;
> > > > 
> > > >     memset(params, 0, sizeof(params));
> > > > 
> > > >     if (IS_ERR(mst_state))
> > > > -           return false;
> > > > +           return PTR_ERR(mst_state);
> > > > 
> > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > 
> > > >     if (count == 0) {
> > > >             ASSERT(0);
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > 
> > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > drm_atomic_state *state,
> > > >             vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >             vars[i + k].dsc_enabled = false;
> > > >             vars[i + k].bpp_x16 = 0;
> > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > -                                             vars[i + k].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > +                                               vars[i + k].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > >     }
> > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > -           return true;
> > > > +           return 0;
> > > > +   } else if (ret != -ENOSPC) {
> > > > +           return ret;
> > > >     }
> > > > 
> > > >     /* Try max compression */
> > > > @@ -962,31 +979,36 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > >                     vars[i + k].dsc_enabled = true;
> > > >                     vars[i + k].bpp_x16 =
> > > > params[i].bw_range.min_target_bpp_x16;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             } else {
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >                     vars[i + k].dsc_enabled = false;
> > > >                     vars[i + k].bpp_x16 = 0;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > >     }
> > > > -   if (drm_dp_mst_atomic_check(state))
> > > > -           return false;
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret != 0)
> > > > +           return ret;
> > > > 
> > > >     /* Optimize degree of compression */
> > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > k))
> > > > -           return false;
> > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > -           return false;
> > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > 
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > >  static bool is_dsc_need_re_compute(
> > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > >     return is_dsc_need_re_compute;
> > > >  }
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > >                     continue;
> > > > 
> > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > dc_state, stream) != DC_OK)
> > > > -                   return false;
> > > > +                   return -EINVAL;
> > > > 
> > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (stream->timing.flags.DSC == 1)
> > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > dc, dc_state, stream) != DC_OK)
> > > > -                           return false;
> > > > +                           return -EINVAL;
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > > -static bool
> > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > *state,
> > > > -                                         struct dc_state *dc_state,
> > > > -                                         struct dsc_mst_fairness_vars
> > > > *vars)
> > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > +                                            struct dc_state *dc_state,
> > > > +                                            struct dsc_mst_fairness_vars
> > > > *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1184,11 +1209,12 @@ static bool
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1198,7 +1224,7 @@ static bool
> > > >             }
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > >     return ret;
> > > >  }
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i;
> > > >     struct dm_atomic_state *dm_state;
> > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     if (!is_dsc_precompute_needed(state)) {
> > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > +   if (ret != 0) {
> > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > -           return false;
> > > > +           return ret;
> > > >     }
> > > >     dm_state = *dm_state_ptr;
> > > > 
> > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > dc_state), GFP_KERNEL);
> > > >     if (!local_dc_state)
> > > > -           return false;
> > > > +           return -ENOMEM;
> > > > 
> > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > drm_atomic_state *state,
> > > >     if (ret != 0)
> > > >             goto clean_exit;
> > > > 
> > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars)) {
> > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars);
> > > > +   if (ret != 0) {
> > > > 
> > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -           ret = -EINVAL;
> > > >             goto clean_exit;
> > > >     }
> > > > 
> > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     kfree(local_dc_state);
> > > > 
> > > > -   return (ret == 0);
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > >     struct amdgpu_dm_connector *aconnector,
> > > > --
> > > > 2.37.3
> > > 
> > 
> > --
> > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:47           ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:47 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, amd-gfx, Li,
	Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Hung, Alex, Wu, Hersen, Mikita Lipski, Pan, Xinhui, open list,
	stable, Kazlauskas, Nicholas, Thomas Zimmermann, Lin, Wayne,
	Deucher, Alexander, Koenig, Christian

of course, will do in just a moment

On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> I've already picked this up.  Can you send a follow up patch with just
> the coverity fix?
> 
> Alex
> 
> On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > 
> > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > send out a respin real quick to fix it. It's just a missing variable
> > assignment (we leave ret unassigned by mistake in
> > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > 
> > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > [Public]
> > > 
> > > All the patch set looks good to me. Feel free to add:
> > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > 
> > > Again, thank you Lyude for helping on this!!!
> > > 
> > > Regards,
> > > Wayne
> > > > -----Original Message-----
> > > > From: Lyude Paul <lyude@redhat.com>
> > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > To: amd-gfx@lists.freedesktop.org
> > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > deadlocking
> > > > 
> > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > In this case, it seems to have come back to bite us because as a result of
> > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > had no way of telling when a deadlock happened from these helpers. This
> > > > could definitely result in some kernel splats.
> > > > 
> > > > V2:
> > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > >   passing down return codes)
> > > > 
> > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > ---
> > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > --
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > @@ -6462,7 +6462,7 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >     struct drm_connector_state *new_con_state;
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct dm_connector_state *dm_conn_state;
> > > > -   int i, j;
> > > > +   int i, j, ret;
> > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > 
> > > >     for_each_new_connector_in_state(state, connector,
> > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >                     dm_conn_state->pbn = pbn;
> > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > 
> > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > port, dm_conn_state->pbn,
> > > > -                                                false);
> > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > aconnector->port,
> > > > +                                                      dm_conn_state-
> > > > > pbn, false);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > >                     continue;
> > > >             }
> > > > 
> > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > -                   ret = -EINVAL;
> > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > +           if (ret != 0)
> > > >                     goto fail;
> > > > -           }
> > > >     }
> > > >  #endif
> > > > 
> > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > >             }
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars)) {
> > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars);
> > > > +           if (ret) {
> > > > 
> > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -                   ret = -EINVAL;
> > > >                     goto fail;
> > > >             }
> > > > 
> > > > diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > dsc_mst_fairness_params param, int pbn)
> > > >     return dsc_config.bits_per_pixel;
> > > >  }
> > > > 
> > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > -                        struct dc_link *dc_link,
> > > > -                        struct dsc_mst_fairness_params *params,
> > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > -                        int count,
> > > > -                        int k)
> > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > +                       struct dc_link *dc_link,
> > > > +                       struct dsc_mst_fairness_params *params,
> > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > +                       int count,
> > > > +                       int k)
> > > >  {
> > > >     int i;
> > > >     bool bpp_increased[MAX_PIPES];
> > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > >     int remaining_to_increase = 0;
> > > >     int link_timeslots_used;
> > > >     int fair_pbn_alloc;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled) {
> > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > >                     } else {
> > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             } else {
> > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > params[next_index].bw_range.max_target_bpp_x16;
> > > >                     } else {
> > > >                             vars[next_index].pbn -=
> > > > initial_slack[next_index];
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             }
> > > > 
> > > >             bpp_increased[next_index] = true;
> > > >             remaining_to_increase--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > -                       struct dc_link *dc_link,
> > > > -                       struct dsc_mst_fairness_params *params,
> > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > -                       int count,
> > > > -                       int k)
> > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > +                      struct dc_link *dc_link,
> > > > +                      struct dsc_mst_fairness_params *params,
> > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > +                      int count,
> > > > +                      int k)
> > > >  {
> > > >     int i;
> > > >     bool tried[MAX_PIPES];
> > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > *state,
> > > >     int max_kbps_increase;
> > > >     int next_index;
> > > >     int remaining_to_try = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled
> > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > drm_atomic_state *state,
> > > >                     break;
> > > > 
> > > >             vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > -                                             params[next_index].port-
> > > > > mgr,
> > > > -                                             params[next_index].port,
> > > > -                                             vars[next_index].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > +                                               params[next_index].port-
> > > > > mgr,
> > > > +                                               params[next_index].port,
> > > > +                                               vars[next_index].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > > 
> > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > +           if (ret == 0) {
> > > >                     vars[next_index].dsc_enabled = false;
> > > >                     vars[next_index].bpp_x16 = 0;
> > > >             } else {
> > > >                     vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > > 
> > > >             tried[next_index] = true;
> > > >             remaining_to_try--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > -                                        struct dc_state *dc_state,
> > > > -                                        struct dc_link *dc_link,
> > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > -                                        struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > -                                        int *link_vars_start_index)
> > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > +                                       struct dc_state *dc_state,
> > > > +                                       struct dc_link *dc_link,
> > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > +                                       struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > +                                       int *link_vars_start_index)
> > > >  {
> > > >     struct dc_stream_state *stream;
> > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > >     int count = 0;
> > > > -   int i, k;
> > > > +   int i, k, ret;
> > > >     bool debugfs_overwrite = false;
> > > > 
> > > >     memset(params, 0, sizeof(params));
> > > > 
> > > >     if (IS_ERR(mst_state))
> > > > -           return false;
> > > > +           return PTR_ERR(mst_state);
> > > > 
> > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > 
> > > >     if (count == 0) {
> > > >             ASSERT(0);
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > 
> > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > drm_atomic_state *state,
> > > >             vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >             vars[i + k].dsc_enabled = false;
> > > >             vars[i + k].bpp_x16 = 0;
> > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > -                                             vars[i + k].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > +                                               vars[i + k].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > >     }
> > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > -           return true;
> > > > +           return 0;
> > > > +   } else if (ret != -ENOSPC) {
> > > > +           return ret;
> > > >     }
> > > > 
> > > >     /* Try max compression */
> > > > @@ -962,31 +979,36 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > >                     vars[i + k].dsc_enabled = true;
> > > >                     vars[i + k].bpp_x16 =
> > > > params[i].bw_range.min_target_bpp_x16;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             } else {
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >                     vars[i + k].dsc_enabled = false;
> > > >                     vars[i + k].bpp_x16 = 0;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > >     }
> > > > -   if (drm_dp_mst_atomic_check(state))
> > > > -           return false;
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret != 0)
> > > > +           return ret;
> > > > 
> > > >     /* Optimize degree of compression */
> > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > k))
> > > > -           return false;
> > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > -           return false;
> > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > 
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > >  static bool is_dsc_need_re_compute(
> > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > >     return is_dsc_need_re_compute;
> > > >  }
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > >                     continue;
> > > > 
> > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > dc_state, stream) != DC_OK)
> > > > -                   return false;
> > > > +                   return -EINVAL;
> > > > 
> > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (stream->timing.flags.DSC == 1)
> > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > dc, dc_state, stream) != DC_OK)
> > > > -                           return false;
> > > > +                           return -EINVAL;
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > > -static bool
> > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > *state,
> > > > -                                         struct dc_state *dc_state,
> > > > -                                         struct dsc_mst_fairness_vars
> > > > *vars)
> > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > +                                            struct dc_state *dc_state,
> > > > +                                            struct dsc_mst_fairness_vars
> > > > *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1184,11 +1209,12 @@ static bool
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1198,7 +1224,7 @@ static bool
> > > >             }
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > >     return ret;
> > > >  }
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i;
> > > >     struct dm_atomic_state *dm_state;
> > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     if (!is_dsc_precompute_needed(state)) {
> > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > +   if (ret != 0) {
> > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > -           return false;
> > > > +           return ret;
> > > >     }
> > > >     dm_state = *dm_state_ptr;
> > > > 
> > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > dc_state), GFP_KERNEL);
> > > >     if (!local_dc_state)
> > > > -           return false;
> > > > +           return -ENOMEM;
> > > > 
> > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > drm_atomic_state *state,
> > > >     if (ret != 0)
> > > >             goto clean_exit;
> > > > 
> > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars)) {
> > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars);
> > > > +   if (ret != 0) {
> > > > 
> > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -           ret = -EINVAL;
> > > >             goto clean_exit;
> > > >     }
> > > > 
> > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     kfree(local_dc_state);
> > > > 
> > > > -   return (ret == 0);
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > >     struct amdgpu_dm_connector *aconnector,
> > > > --
> > > > 2.37.3
> > > 
> > 
> > --
> > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:47           ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:47 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Lin, Wayne, amd-gfx, Liu, Wenjing, open list:DRM DRIVERS,
	open list, Mahfooz, Hamza, David Airlie, Francis, David,
	Siqueira, Rodrigo, Hung, Alex, Zuo, Jerry, Pillai, Aurabindo,
	Wentland, Harry, Daniel Vetter, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

of course, will do in just a moment

On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> I've already picked this up.  Can you send a follow up patch with just
> the coverity fix?
> 
> Alex
> 
> On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > 
> > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > send out a respin real quick to fix it. It's just a missing variable
> > assignment (we leave ret unassigned by mistake in
> > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > 
> > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > [Public]
> > > 
> > > All the patch set looks good to me. Feel free to add:
> > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > 
> > > Again, thank you Lyude for helping on this!!!
> > > 
> > > Regards,
> > > Wayne
> > > > -----Original Message-----
> > > > From: Lyude Paul <lyude@redhat.com>
> > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > To: amd-gfx@lists.freedesktop.org
> > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > deadlocking
> > > > 
> > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > In this case, it seems to have come back to bite us because as a result of
> > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > had no way of telling when a deadlock happened from these helpers. This
> > > > could definitely result in some kernel splats.
> > > > 
> > > > V2:
> > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > >   passing down return codes)
> > > > 
> > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > ---
> > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > --
> > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > @@ -6462,7 +6462,7 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >     struct drm_connector_state *new_con_state;
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct dm_connector_state *dm_conn_state;
> > > > -   int i, j;
> > > > +   int i, j, ret;
> > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > 
> > > >     for_each_new_connector_in_state(state, connector,
> > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > >                     dm_conn_state->pbn = pbn;
> > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > 
> > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > port, dm_conn_state->pbn,
> > > > -                                                false);
> > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > aconnector->port,
> > > > +                                                      dm_conn_state-
> > > > > pbn, false);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > >                     continue;
> > > >             }
> > > > 
> > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > -                   ret = -EINVAL;
> > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > +           if (ret != 0)
> > > >                     goto fail;
> > > > -           }
> > > >     }
> > > >  #endif
> > > > 
> > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > drm_device *dev,
> > > >             }
> > > > 
> > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars)) {
> > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > context, vars);
> > > > +           if (ret) {
> > > > 
> > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -                   ret = -EINVAL;
> > > >                     goto fail;
> > > >             }
> > > > 
> > > > diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > dsc_mst_fairness_params param, int pbn)
> > > >     return dsc_config.bits_per_pixel;
> > > >  }
> > > > 
> > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > -                        struct dc_link *dc_link,
> > > > -                        struct dsc_mst_fairness_params *params,
> > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > -                        int count,
> > > > -                        int k)
> > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > +                       struct dc_link *dc_link,
> > > > +                       struct dsc_mst_fairness_params *params,
> > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > +                       int count,
> > > > +                       int k)
> > > >  {
> > > >     int i;
> > > >     bool bpp_increased[MAX_PIPES];
> > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > >     int remaining_to_increase = 0;
> > > >     int link_timeslots_used;
> > > >     int fair_pbn_alloc;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled) {
> > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > >                     } else {
> > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             } else {
> > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > > +
> > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > +                   if (ret == 0) {
> > > >                             vars[next_index].bpp_x16 =
> > > > params[next_index].bw_range.max_target_bpp_x16;
> > > >                     } else {
> > > >                             vars[next_index].pbn -=
> > > > initial_slack[next_index];
> > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                                   return false;
> > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                           if (ret < 0)
> > > > +                                   return ret;
> > > >                     }
> > > >             }
> > > > 
> > > >             bpp_increased[next_index] = true;
> > > >             remaining_to_increase--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > -                       struct dc_link *dc_link,
> > > > -                       struct dsc_mst_fairness_params *params,
> > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > -                       int count,
> > > > -                       int k)
> > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > +                      struct dc_link *dc_link,
> > > > +                      struct dsc_mst_fairness_params *params,
> > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > +                      int count,
> > > > +                      int k)
> > > >  {
> > > >     int i;
> > > >     bool tried[MAX_PIPES];
> > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > *state,
> > > >     int max_kbps_increase;
> > > >     int next_index;
> > > >     int remaining_to_try = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < count; i++) {
> > > >             if (vars[i + k].dsc_enabled
> > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > drm_atomic_state *state,
> > > >                     break;
> > > > 
> > > >             vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > -                                             params[next_index].port-
> > > > > mgr,
> > > > -                                             params[next_index].port,
> > > > -                                             vars[next_index].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > +                                               params[next_index].port-
> > > > > mgr,
> > > > +                                               params[next_index].port,
> > > > +                                               vars[next_index].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > > 
> > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > +           if (ret == 0) {
> > > >                     vars[next_index].dsc_enabled = false;
> > > >                     vars[next_index].bpp_x16 = 0;
> > > >             } else {
> > > >                     vars[next_index].pbn =
> > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > -
> > > > params[next_index].port->mgr,
> > > > -
> > > > params[next_index].port,
> > > > -
> > > > vars[next_index].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > +
> > > > params[next_index].port->mgr,
> > > > +
> > > > params[next_index].port,
> > > > +
> > > > vars[next_index].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > > 
> > > >             tried[next_index] = true;
> > > >             remaining_to_try--;
> > > >     }
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > -                                        struct dc_state *dc_state,
> > > > -                                        struct dc_link *dc_link,
> > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > -                                        struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > -                                        int *link_vars_start_index)
> > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > *state,
> > > > +                                       struct dc_state *dc_state,
> > > > +                                       struct dc_link *dc_link,
> > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > +                                       struct drm_dp_mst_topology_mgr
> > > > *mgr,
> > > > +                                       int *link_vars_start_index)
> > > >  {
> > > >     struct dc_stream_state *stream;
> > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > >     int count = 0;
> > > > -   int i, k;
> > > > +   int i, k, ret;
> > > >     bool debugfs_overwrite = false;
> > > > 
> > > >     memset(params, 0, sizeof(params));
> > > > 
> > > >     if (IS_ERR(mst_state))
> > > > -           return false;
> > > > +           return PTR_ERR(mst_state);
> > > > 
> > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > 
> > > >     if (count == 0) {
> > > >             ASSERT(0);
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > 
> > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > drm_atomic_state *state,
> > > >             vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >             vars[i + k].dsc_enabled = false;
> > > >             vars[i + k].bpp_x16 = 0;
> > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > -                                             vars[i + k].pbn) < 0)
> > > > -                   return false;
> > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > mgr, params[i].port,
> > > > +                                               vars[i + k].pbn);
> > > > +           if (ret < 0)
> > > > +                   return ret;
> > > >     }
> > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > -           return true;
> > > > +           return 0;
> > > > +   } else if (ret != -ENOSPC) {
> > > > +           return ret;
> > > >     }
> > > > 
> > > >     /* Try max compression */
> > > > @@ -962,31 +979,36 @@ static bool
> > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > >                     vars[i + k].dsc_enabled = true;
> > > >                     vars[i + k].bpp_x16 =
> > > > params[i].bw_range.min_target_bpp_x16;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             } else {
> > > >                     vars[i + k].pbn =
> > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > >                     vars[i + k].dsc_enabled = false;
> > > >                     vars[i + k].bpp_x16 = 0;
> > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > -                                                     params[i].port, vars[i
> > > > + k].pbn) < 0)
> > > > -                           return false;
> > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > params[i].port->mgr,
> > > > +                                                       params[i].port,
> > > > vars[i + k].pbn);
> > > > +                   if (ret < 0)
> > > > +                           return ret;
> > > >             }
> > > >     }
> > > > -   if (drm_dp_mst_atomic_check(state))
> > > > -           return false;
> > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > +   if (ret != 0)
> > > > +           return ret;
> > > > 
> > > >     /* Optimize degree of compression */
> > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > k))
> > > > -           return false;
> > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > -           return false;
> > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > +   if (ret < 0)
> > > > +           return ret;
> > > > 
> > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > 
> > > > -   return true;
> > > > +   return 0;
> > > >  }
> > > > 
> > > >  static bool is_dsc_need_re_compute(
> > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > >     return is_dsc_need_re_compute;
> > > >  }
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret = 0;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > >                     continue;
> > > > 
> > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > dc_state, stream) != DC_OK)
> > > > -                   return false;
> > > > +                   return -EINVAL;
> > > > 
> > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > 
> > > >             if (stream->timing.flags.DSC == 1)
> > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > dc, dc_state, stream) != DC_OK)
> > > > -                           return false;
> > > > +                           return -EINVAL;
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > > -static bool
> > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > *state,
> > > > -                                         struct dc_state *dc_state,
> > > > -                                         struct dsc_mst_fairness_vars
> > > > *vars)
> > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > drm_atomic_state *state,
> > > > +                                            struct dc_state *dc_state,
> > > > +                                            struct dsc_mst_fairness_vars
> > > > *vars)
> > > >  {
> > > >     int i, j;
> > > >     struct dc_stream_state *stream;
> > > >     bool computed_streams[MAX_PIPES];
> > > >     struct amdgpu_dm_connector *aconnector;
> > > >     int link_vars_start_index = 0;
> > > > +   int ret;
> > > > 
> > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > >             computed_streams[i] = false;
> > > > @@ -1184,11 +1209,12 @@ static bool
> > > >                     continue;
> > > > 
> > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > -                                                 &aconnector->mst_mgr,
> > > > -                                                 &link_vars_start_index)) {
> > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > stream->link, vars,
> > > > +                                                  &aconnector->mst_mgr,
> > > > +                                                  &link_vars_start_index);
> > > > +           if (ret != 0) {
> > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > -                   return false;
> > > > +                   return ret;
> > > >             }
> > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > 
> > > > @@ -1198,7 +1224,7 @@ static bool
> > > >             }
> > > >     }
> > > > 
> > > > -   return true;
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > >     return ret;
> > > >  }
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars)
> > > >  {
> > > >     int i;
> > > >     struct dm_atomic_state *dm_state;
> > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     if (!is_dsc_precompute_needed(state)) {
> > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > -           return true;
> > > > +           return 0;
> > > >     }
> > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > +   if (ret != 0) {
> > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > -           return false;
> > > > +           return ret;
> > > >     }
> > > >     dm_state = *dm_state_ptr;
> > > > 
> > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > dc_state), GFP_KERNEL);
> > > >     if (!local_dc_state)
> > > > -           return false;
> > > > +           return -ENOMEM;
> > > > 
> > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > drm_atomic_state *state,
> > > >     if (ret != 0)
> > > >             goto clean_exit;
> > > > 
> > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars)) {
> > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > vars);
> > > > +   if (ret != 0) {
> > > > 
> > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > failed\n");
> > > > -           ret = -EINVAL;
> > > >             goto clean_exit;
> > > >     }
> > > > 
> > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > *state,
> > > > 
> > > >     kfree(local_dc_state);
> > > > 
> > > > -   return (ret == 0);
> > > > +   return ret;
> > > >  }
> > > > 
> > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > +++
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > 
> > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > -                                  struct dc_state *dc_state,
> > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > +                                 struct dc_state *dc_state,
> > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > 
> > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > +                struct dsc_mst_fairness_vars *vars);
> > > > 
> > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > >     struct amdgpu_dm_connector *aconnector,
> > > > --
> > > > 2.37.3
> > > 
> > 
> > --
> > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:47           ` Lyude Paul
  (?)
@ 2022-11-18 19:53             ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:53 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, amd-gfx, Li, Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Hung, Alex, Wu, Hersen,
	Mikita Lipski, Pan, Xinhui, open list, stable, Kazlauskas,
	Nicholas, Thomas Zimmermann, Lin, Wayne, Deucher, Alexander,
	Koenig, Christian

JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
it's in your branch, so I'll omit that and let you add it into the patch

On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> of course, will do in just a moment
> 
> On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > I've already picked this up.  Can you send a follow up patch with just
> > the coverity fix?
> > 
> > Alex
> > 
> > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > 
> > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > send out a respin real quick to fix it. It's just a missing variable
> > > assignment (we leave ret unassigned by mistake in
> > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > 
> > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > [Public]
> > > > 
> > > > All the patch set looks good to me. Feel free to add:
> > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > 
> > > > Again, thank you Lyude for helping on this!!!
> > > > 
> > > > Regards,
> > > > Wayne
> > > > > -----Original Message-----
> > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > To: amd-gfx@lists.freedesktop.org
> > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > deadlocking
> > > > > 
> > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > could definitely result in some kernel splats.
> > > > > 
> > > > > V2:
> > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > >   passing down return codes)
> > > > > 
> > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > ---
> > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > --
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >     struct drm_connector_state *new_con_state;
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct dm_connector_state *dm_conn_state;
> > > > > -   int i, j;
> > > > > +   int i, j, ret;
> > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > 
> > > > >     for_each_new_connector_in_state(state, connector,
> > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >                     dm_conn_state->pbn = pbn;
> > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > 
> > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > port, dm_conn_state->pbn,
> > > > > -                                                false);
> > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > aconnector->port,
> > > > > +                                                      dm_conn_state-
> > > > > > pbn, false);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > >                     continue;
> > > > >             }
> > > > > 
> > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > -                   ret = -EINVAL;
> > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > +           if (ret != 0)
> > > > >                     goto fail;
> > > > > -           }
> > > > >     }
> > > > >  #endif
> > > > > 
> > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > >             }
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars)) {
> > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars);
> > > > > +           if (ret) {
> > > > > 
> > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -                   ret = -EINVAL;
> > > > >                     goto fail;
> > > > >             }
> > > > > 
> > > > > diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > dsc_mst_fairness_params param, int pbn)
> > > > >     return dsc_config.bits_per_pixel;
> > > > >  }
> > > > > 
> > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > -                        struct dc_link *dc_link,
> > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > -                        int count,
> > > > > -                        int k)
> > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > +                       struct dc_link *dc_link,
> > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > +                       int count,
> > > > > +                       int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool bpp_increased[MAX_PIPES];
> > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > >     int remaining_to_increase = 0;
> > > > >     int link_timeslots_used;
> > > > >     int fair_pbn_alloc;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled) {
> > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             } else {
> > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -=
> > > > > initial_slack[next_index];
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             }
> > > > > 
> > > > >             bpp_increased[next_index] = true;
> > > > >             remaining_to_increase--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > -                       struct dc_link *dc_link,
> > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > -                       int count,
> > > > > -                       int k)
> > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > +                      struct dc_link *dc_link,
> > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > +                      int count,
> > > > > +                      int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool tried[MAX_PIPES];
> > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > *state,
> > > > >     int max_kbps_increase;
> > > > >     int next_index;
> > > > >     int remaining_to_try = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled
> > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >                     break;
> > > > > 
> > > > >             vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > -                                             params[next_index].port-
> > > > > > mgr,
> > > > > -                                             params[next_index].port,
> > > > > -                                             vars[next_index].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +                                               params[next_index].port-
> > > > > > mgr,
> > > > > +                                               params[next_index].port,
> > > > > +                                               vars[next_index].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > > 
> > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > +           if (ret == 0) {
> > > > >                     vars[next_index].dsc_enabled = false;
> > > > >                     vars[next_index].bpp_x16 = 0;
> > > > >             } else {
> > > > >                     vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > > 
> > > > >             tried[next_index] = true;
> > > > >             remaining_to_try--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > -                                        struct dc_state *dc_state,
> > > > > -                                        struct dc_link *dc_link,
> > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > -                                        int *link_vars_start_index)
> > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > +                                       struct dc_state *dc_state,
> > > > > +                                       struct dc_link *dc_link,
> > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > +                                       int *link_vars_start_index)
> > > > >  {
> > > > >     struct dc_stream_state *stream;
> > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > >     int count = 0;
> > > > > -   int i, k;
> > > > > +   int i, k, ret;
> > > > >     bool debugfs_overwrite = false;
> > > > > 
> > > > >     memset(params, 0, sizeof(params));
> > > > > 
> > > > >     if (IS_ERR(mst_state))
> > > > > -           return false;
> > > > > +           return PTR_ERR(mst_state);
> > > > > 
> > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > 
> > > > >     if (count == 0) {
> > > > >             ASSERT(0);
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > 
> > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > drm_atomic_state *state,
> > > > >             vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >             vars[i + k].dsc_enabled = false;
> > > > >             vars[i + k].bpp_x16 = 0;
> > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > -                                             vars[i + k].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > +                                               vars[i + k].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > >     }
> > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > -           return true;
> > > > > +           return 0;
> > > > > +   } else if (ret != -ENOSPC) {
> > > > > +           return ret;
> > > > >     }
> > > > > 
> > > > >     /* Try max compression */
> > > > > @@ -962,31 +979,36 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > >                     vars[i + k].dsc_enabled = true;
> > > > >                     vars[i + k].bpp_x16 =
> > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             } else {
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >                     vars[i + k].dsc_enabled = false;
> > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > >     }
> > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > -           return false;
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret != 0)
> > > > > +           return ret;
> > > > > 
> > > > >     /* Optimize degree of compression */
> > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > k))
> > > > > -           return false;
> > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > -           return false;
> > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > 
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > >  static bool is_dsc_need_re_compute(
> > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > >     return is_dsc_need_re_compute;
> > > > >  }
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > >                     continue;
> > > > > 
> > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > dc_state, stream) != DC_OK)
> > > > > -                   return false;
> > > > > +                   return -EINVAL;
> > > > > 
> > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (stream->timing.flags.DSC == 1)
> > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > dc, dc_state, stream) != DC_OK)
> > > > > -                           return false;
> > > > > +                           return -EINVAL;
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > > -static bool
> > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > *state,
> > > > > -                                         struct dc_state *dc_state,
> > > > > -                                         struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > +                                            struct dc_state *dc_state,
> > > > > +                                            struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > >             }
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > >     return ret;
> > > > >  }
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i;
> > > > >     struct dm_atomic_state *dm_state;
> > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > +   if (ret != 0) {
> > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > -           return false;
> > > > > +           return ret;
> > > > >     }
> > > > >     dm_state = *dm_state_ptr;
> > > > > 
> > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > dc_state), GFP_KERNEL);
> > > > >     if (!local_dc_state)
> > > > > -           return false;
> > > > > +           return -ENOMEM;
> > > > > 
> > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >     if (ret != 0)
> > > > >             goto clean_exit;
> > > > > 
> > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars)) {
> > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars);
> > > > > +   if (ret != 0) {
> > > > > 
> > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -           ret = -EINVAL;
> > > > >             goto clean_exit;
> > > > >     }
> > > > > 
> > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     kfree(local_dc_state);
> > > > > 
> > > > > -   return (ret == 0);
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > --
> > > > > 2.37.3
> > > > 
> > > 
> > > --
> > > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:53             ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:53 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, amd-gfx, Li,
	Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Hung, Alex, Wu, Hersen, Mikita Lipski, Pan, Xinhui, open list,
	stable, Kazlauskas, Nicholas, Thomas Zimmermann, Lin, Wayne,
	Deucher, Alexander, Koenig, Christian

JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
it's in your branch, so I'll omit that and let you add it into the patch

On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> of course, will do in just a moment
> 
> On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > I've already picked this up.  Can you send a follow up patch with just
> > the coverity fix?
> > 
> > Alex
> > 
> > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > 
> > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > send out a respin real quick to fix it. It's just a missing variable
> > > assignment (we leave ret unassigned by mistake in
> > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > 
> > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > [Public]
> > > > 
> > > > All the patch set looks good to me. Feel free to add:
> > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > 
> > > > Again, thank you Lyude for helping on this!!!
> > > > 
> > > > Regards,
> > > > Wayne
> > > > > -----Original Message-----
> > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > To: amd-gfx@lists.freedesktop.org
> > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > deadlocking
> > > > > 
> > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > could definitely result in some kernel splats.
> > > > > 
> > > > > V2:
> > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > >   passing down return codes)
> > > > > 
> > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > ---
> > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > --
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >     struct drm_connector_state *new_con_state;
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct dm_connector_state *dm_conn_state;
> > > > > -   int i, j;
> > > > > +   int i, j, ret;
> > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > 
> > > > >     for_each_new_connector_in_state(state, connector,
> > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >                     dm_conn_state->pbn = pbn;
> > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > 
> > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > port, dm_conn_state->pbn,
> > > > > -                                                false);
> > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > aconnector->port,
> > > > > +                                                      dm_conn_state-
> > > > > > pbn, false);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > >                     continue;
> > > > >             }
> > > > > 
> > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > -                   ret = -EINVAL;
> > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > +           if (ret != 0)
> > > > >                     goto fail;
> > > > > -           }
> > > > >     }
> > > > >  #endif
> > > > > 
> > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > >             }
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars)) {
> > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars);
> > > > > +           if (ret) {
> > > > > 
> > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -                   ret = -EINVAL;
> > > > >                     goto fail;
> > > > >             }
> > > > > 
> > > > > diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > dsc_mst_fairness_params param, int pbn)
> > > > >     return dsc_config.bits_per_pixel;
> > > > >  }
> > > > > 
> > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > -                        struct dc_link *dc_link,
> > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > -                        int count,
> > > > > -                        int k)
> > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > +                       struct dc_link *dc_link,
> > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > +                       int count,
> > > > > +                       int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool bpp_increased[MAX_PIPES];
> > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > >     int remaining_to_increase = 0;
> > > > >     int link_timeslots_used;
> > > > >     int fair_pbn_alloc;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled) {
> > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             } else {
> > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -=
> > > > > initial_slack[next_index];
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             }
> > > > > 
> > > > >             bpp_increased[next_index] = true;
> > > > >             remaining_to_increase--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > -                       struct dc_link *dc_link,
> > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > -                       int count,
> > > > > -                       int k)
> > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > +                      struct dc_link *dc_link,
> > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > +                      int count,
> > > > > +                      int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool tried[MAX_PIPES];
> > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > *state,
> > > > >     int max_kbps_increase;
> > > > >     int next_index;
> > > > >     int remaining_to_try = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled
> > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >                     break;
> > > > > 
> > > > >             vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > -                                             params[next_index].port-
> > > > > > mgr,
> > > > > -                                             params[next_index].port,
> > > > > -                                             vars[next_index].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +                                               params[next_index].port-
> > > > > > mgr,
> > > > > +                                               params[next_index].port,
> > > > > +                                               vars[next_index].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > > 
> > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > +           if (ret == 0) {
> > > > >                     vars[next_index].dsc_enabled = false;
> > > > >                     vars[next_index].bpp_x16 = 0;
> > > > >             } else {
> > > > >                     vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > > 
> > > > >             tried[next_index] = true;
> > > > >             remaining_to_try--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > -                                        struct dc_state *dc_state,
> > > > > -                                        struct dc_link *dc_link,
> > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > -                                        int *link_vars_start_index)
> > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > +                                       struct dc_state *dc_state,
> > > > > +                                       struct dc_link *dc_link,
> > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > +                                       int *link_vars_start_index)
> > > > >  {
> > > > >     struct dc_stream_state *stream;
> > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > >     int count = 0;
> > > > > -   int i, k;
> > > > > +   int i, k, ret;
> > > > >     bool debugfs_overwrite = false;
> > > > > 
> > > > >     memset(params, 0, sizeof(params));
> > > > > 
> > > > >     if (IS_ERR(mst_state))
> > > > > -           return false;
> > > > > +           return PTR_ERR(mst_state);
> > > > > 
> > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > 
> > > > >     if (count == 0) {
> > > > >             ASSERT(0);
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > 
> > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > drm_atomic_state *state,
> > > > >             vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >             vars[i + k].dsc_enabled = false;
> > > > >             vars[i + k].bpp_x16 = 0;
> > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > -                                             vars[i + k].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > +                                               vars[i + k].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > >     }
> > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > -           return true;
> > > > > +           return 0;
> > > > > +   } else if (ret != -ENOSPC) {
> > > > > +           return ret;
> > > > >     }
> > > > > 
> > > > >     /* Try max compression */
> > > > > @@ -962,31 +979,36 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > >                     vars[i + k].dsc_enabled = true;
> > > > >                     vars[i + k].bpp_x16 =
> > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             } else {
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >                     vars[i + k].dsc_enabled = false;
> > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > >     }
> > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > -           return false;
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret != 0)
> > > > > +           return ret;
> > > > > 
> > > > >     /* Optimize degree of compression */
> > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > k))
> > > > > -           return false;
> > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > -           return false;
> > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > 
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > >  static bool is_dsc_need_re_compute(
> > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > >     return is_dsc_need_re_compute;
> > > > >  }
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > >                     continue;
> > > > > 
> > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > dc_state, stream) != DC_OK)
> > > > > -                   return false;
> > > > > +                   return -EINVAL;
> > > > > 
> > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (stream->timing.flags.DSC == 1)
> > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > dc, dc_state, stream) != DC_OK)
> > > > > -                           return false;
> > > > > +                           return -EINVAL;
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > > -static bool
> > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > *state,
> > > > > -                                         struct dc_state *dc_state,
> > > > > -                                         struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > +                                            struct dc_state *dc_state,
> > > > > +                                            struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > >             }
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > >     return ret;
> > > > >  }
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i;
> > > > >     struct dm_atomic_state *dm_state;
> > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > +   if (ret != 0) {
> > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > -           return false;
> > > > > +           return ret;
> > > > >     }
> > > > >     dm_state = *dm_state_ptr;
> > > > > 
> > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > dc_state), GFP_KERNEL);
> > > > >     if (!local_dc_state)
> > > > > -           return false;
> > > > > +           return -ENOMEM;
> > > > > 
> > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >     if (ret != 0)
> > > > >             goto clean_exit;
> > > > > 
> > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars)) {
> > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars);
> > > > > +   if (ret != 0) {
> > > > > 
> > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -           ret = -EINVAL;
> > > > >             goto clean_exit;
> > > > >     }
> > > > > 
> > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     kfree(local_dc_state);
> > > > > 
> > > > > -   return (ret == 0);
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > --
> > > > > 2.37.3
> > > > 
> > > 
> > > --
> > > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:53             ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:53 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Lin, Wayne, amd-gfx, Liu, Wenjing, open list:DRM DRIVERS,
	open list, Mahfooz, Hamza, David Airlie, Francis, David,
	Siqueira, Rodrigo, Hung, Alex, Zuo, Jerry, Pillai, Aurabindo,
	Wentland, Harry, Daniel Vetter, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
it's in your branch, so I'll omit that and let you add it into the patch

On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> of course, will do in just a moment
> 
> On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > I've already picked this up.  Can you send a follow up patch with just
> > the coverity fix?
> > 
> > Alex
> > 
> > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > 
> > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > send out a respin real quick to fix it. It's just a missing variable
> > > assignment (we leave ret unassigned by mistake in
> > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > 
> > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > [Public]
> > > > 
> > > > All the patch set looks good to me. Feel free to add:
> > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > 
> > > > Again, thank you Lyude for helping on this!!!
> > > > 
> > > > Regards,
> > > > Wayne
> > > > > -----Original Message-----
> > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > To: amd-gfx@lists.freedesktop.org
> > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > deadlocking
> > > > > 
> > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > could definitely result in some kernel splats.
> > > > > 
> > > > > V2:
> > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > >   passing down return codes)
> > > > > 
> > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > ---
> > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > --
> > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >     struct drm_connector_state *new_con_state;
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct dm_connector_state *dm_conn_state;
> > > > > -   int i, j;
> > > > > +   int i, j, ret;
> > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > 
> > > > >     for_each_new_connector_in_state(state, connector,
> > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > >                     dm_conn_state->pbn = pbn;
> > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > 
> > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > port, dm_conn_state->pbn,
> > > > > -                                                false);
> > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > aconnector->port,
> > > > > +                                                      dm_conn_state-
> > > > > > pbn, false);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > >                     continue;
> > > > >             }
> > > > > 
> > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > -                   ret = -EINVAL;
> > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > +           if (ret != 0)
> > > > >                     goto fail;
> > > > > -           }
> > > > >     }
> > > > >  #endif
> > > > > 
> > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > drm_device *dev,
> > > > >             }
> > > > > 
> > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars)) {
> > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > context, vars);
> > > > > +           if (ret) {
> > > > > 
> > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -                   ret = -EINVAL;
> > > > >                     goto fail;
> > > > >             }
> > > > > 
> > > > > diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > dsc_mst_fairness_params param, int pbn)
> > > > >     return dsc_config.bits_per_pixel;
> > > > >  }
> > > > > 
> > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > -                        struct dc_link *dc_link,
> > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > -                        int count,
> > > > > -                        int k)
> > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > +                       struct dc_link *dc_link,
> > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > +                       int count,
> > > > > +                       int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool bpp_increased[MAX_PIPES];
> > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > >     int remaining_to_increase = 0;
> > > > >     int link_timeslots_used;
> > > > >     int fair_pbn_alloc;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled) {
> > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             } else {
> > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > > +
> > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > +                   if (ret == 0) {
> > > > >                             vars[next_index].bpp_x16 =
> > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > >                     } else {
> > > > >                             vars[next_index].pbn -=
> > > > > initial_slack[next_index];
> > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                                   return false;
> > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                           if (ret < 0)
> > > > > +                                   return ret;
> > > > >                     }
> > > > >             }
> > > > > 
> > > > >             bpp_increased[next_index] = true;
> > > > >             remaining_to_increase--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > -                       struct dc_link *dc_link,
> > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > -                       int count,
> > > > > -                       int k)
> > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > +                      struct dc_link *dc_link,
> > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > +                      int count,
> > > > > +                      int k)
> > > > >  {
> > > > >     int i;
> > > > >     bool tried[MAX_PIPES];
> > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > *state,
> > > > >     int max_kbps_increase;
> > > > >     int next_index;
> > > > >     int remaining_to_try = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < count; i++) {
> > > > >             if (vars[i + k].dsc_enabled
> > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >                     break;
> > > > > 
> > > > >             vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > -                                             params[next_index].port-
> > > > > > mgr,
> > > > > -                                             params[next_index].port,
> > > > > -                                             vars[next_index].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > +                                               params[next_index].port-
> > > > > > mgr,
> > > > > +                                               params[next_index].port,
> > > > > +                                               vars[next_index].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > > 
> > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > +           if (ret == 0) {
> > > > >                     vars[next_index].dsc_enabled = false;
> > > > >                     vars[next_index].bpp_x16 = 0;
> > > > >             } else {
> > > > >                     vars[next_index].pbn =
> > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > -
> > > > > params[next_index].port->mgr,
> > > > > -
> > > > > params[next_index].port,
> > > > > -
> > > > > vars[next_index].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > +
> > > > > params[next_index].port->mgr,
> > > > > +
> > > > > params[next_index].port,
> > > > > +
> > > > > vars[next_index].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > > 
> > > > >             tried[next_index] = true;
> > > > >             remaining_to_try--;
> > > > >     }
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > -                                        struct dc_state *dc_state,
> > > > > -                                        struct dc_link *dc_link,
> > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > -                                        int *link_vars_start_index)
> > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > *state,
> > > > > +                                       struct dc_state *dc_state,
> > > > > +                                       struct dc_link *dc_link,
> > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > *mgr,
> > > > > +                                       int *link_vars_start_index)
> > > > >  {
> > > > >     struct dc_stream_state *stream;
> > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > >     int count = 0;
> > > > > -   int i, k;
> > > > > +   int i, k, ret;
> > > > >     bool debugfs_overwrite = false;
> > > > > 
> > > > >     memset(params, 0, sizeof(params));
> > > > > 
> > > > >     if (IS_ERR(mst_state))
> > > > > -           return false;
> > > > > +           return PTR_ERR(mst_state);
> > > > > 
> > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > 
> > > > >     if (count == 0) {
> > > > >             ASSERT(0);
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > 
> > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > drm_atomic_state *state,
> > > > >             vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >             vars[i + k].dsc_enabled = false;
> > > > >             vars[i + k].bpp_x16 = 0;
> > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > -                                             vars[i + k].pbn) < 0)
> > > > > -                   return false;
> > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > mgr, params[i].port,
> > > > > +                                               vars[i + k].pbn);
> > > > > +           if (ret < 0)
> > > > > +                   return ret;
> > > > >     }
> > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > -           return true;
> > > > > +           return 0;
> > > > > +   } else if (ret != -ENOSPC) {
> > > > > +           return ret;
> > > > >     }
> > > > > 
> > > > >     /* Try max compression */
> > > > > @@ -962,31 +979,36 @@ static bool
> > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > >                     vars[i + k].dsc_enabled = true;
> > > > >                     vars[i + k].bpp_x16 =
> > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             } else {
> > > > >                     vars[i + k].pbn =
> > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > >                     vars[i + k].dsc_enabled = false;
> > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > -                                                     params[i].port, vars[i
> > > > > + k].pbn) < 0)
> > > > > -                           return false;
> > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > params[i].port->mgr,
> > > > > +                                                       params[i].port,
> > > > > vars[i + k].pbn);
> > > > > +                   if (ret < 0)
> > > > > +                           return ret;
> > > > >             }
> > > > >     }
> > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > -           return false;
> > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > +   if (ret != 0)
> > > > > +           return ret;
> > > > > 
> > > > >     /* Optimize degree of compression */
> > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > k))
> > > > > -           return false;
> > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > -           return false;
> > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > +   if (ret < 0)
> > > > > +           return ret;
> > > > > 
> > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > 
> > > > > -   return true;
> > > > > +   return 0;
> > > > >  }
> > > > > 
> > > > >  static bool is_dsc_need_re_compute(
> > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > >     return is_dsc_need_re_compute;
> > > > >  }
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret = 0;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > >                     continue;
> > > > > 
> > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > dc_state, stream) != DC_OK)
> > > > > -                   return false;
> > > > > +                   return -EINVAL;
> > > > > 
> > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > 
> > > > >             if (stream->timing.flags.DSC == 1)
> > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > dc, dc_state, stream) != DC_OK)
> > > > > -                           return false;
> > > > > +                           return -EINVAL;
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > > -static bool
> > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > *state,
> > > > > -                                         struct dc_state *dc_state,
> > > > > -                                         struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > drm_atomic_state *state,
> > > > > +                                            struct dc_state *dc_state,
> > > > > +                                            struct dsc_mst_fairness_vars
> > > > > *vars)
> > > > >  {
> > > > >     int i, j;
> > > > >     struct dc_stream_state *stream;
> > > > >     bool computed_streams[MAX_PIPES];
> > > > >     struct amdgpu_dm_connector *aconnector;
> > > > >     int link_vars_start_index = 0;
> > > > > +   int ret;
> > > > > 
> > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > >             computed_streams[i] = false;
> > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > >                     continue;
> > > > > 
> > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > -                                                 &aconnector->mst_mgr,
> > > > > -                                                 &link_vars_start_index)) {
> > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > stream->link, vars,
> > > > > +                                                  &aconnector->mst_mgr,
> > > > > +                                                  &link_vars_start_index);
> > > > > +           if (ret != 0) {
> > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > -                   return false;
> > > > > +                   return ret;
> > > > >             }
> > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > 
> > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > >             }
> > > > >     }
> > > > > 
> > > > > -   return true;
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > >     return ret;
> > > > >  }
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > >  {
> > > > >     int i;
> > > > >     struct dm_atomic_state *dm_state;
> > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > -           return true;
> > > > > +           return 0;
> > > > >     }
> > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > +   if (ret != 0) {
> > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > -           return false;
> > > > > +           return ret;
> > > > >     }
> > > > >     dm_state = *dm_state_ptr;
> > > > > 
> > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > dc_state), GFP_KERNEL);
> > > > >     if (!local_dc_state)
> > > > > -           return false;
> > > > > +           return -ENOMEM;
> > > > > 
> > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > drm_atomic_state *state,
> > > > >     if (ret != 0)
> > > > >             goto clean_exit;
> > > > > 
> > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars)) {
> > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > vars);
> > > > > +   if (ret != 0) {
> > > > > 
> > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > failed\n");
> > > > > -           ret = -EINVAL;
> > > > >             goto clean_exit;
> > > > >     }
> > > > > 
> > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > *state,
> > > > > 
> > > > >     kfree(local_dc_state);
> > > > > 
> > > > > -   return (ret == 0);
> > > > > +   return ret;
> > > > >  }
> > > > > 
> > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > +++
> > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > 
> > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > -                                  struct dc_state *dc_state,
> > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > +                                 struct dc_state *dc_state,
> > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > 
> > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > 
> > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > --
> > > > > 2.37.3
> > > > 
> > > 
> > > --
> > > 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] 43+ messages in thread

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:25     ` Lyude Paul
  (?)
@ 2022-11-18 19:54       ` Limonciello, Mario
  -1 siblings, 0 replies; 43+ messages in thread
From: Limonciello, Mario @ 2022-11-18 19:54 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, Roman Li, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Leo Li,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Alex Hung, hersen wu, Mikita Lipski, Pan, Xinhui, open list,
	stable, Nicholas Kazlauskas, Thomas Zimmermann, Wayne Lin,
	Alex Deucher, Christian König

On 11/18/2022 13:25, Lyude Paul wrote:
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple
> true/false. In this case, it seems to have come back to bite us because as
> a result of simply returning false from
> compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> deadlock happened from these helpers. This could definitely result in some
> kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>    passing down return codes)
> V3:
> * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

FYI v2 was just merged recently, it's in the 6.2 pull request that was 
sent out and Alex planned to add it to 6.1-fixes next week too.

Can you send just the delta from v2->v3 as another patch so it can layer 
in cleanly?
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>   3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7..852a2100c6b3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   	struct drm_connector_state *new_con_state;
>   	struct amdgpu_dm_connector *aconnector;
>   	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>   	int vcpi, pbn_div, pbn, slot_num = 0;
>   
>   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   			dm_conn_state->pbn = pbn;
>   			dm_conn_state->vcpi_slots = slot_num;
>   
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> +							   dm_conn_state->pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>   			continue;
>   		}
>   
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
>   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>   			goto fail;
> -		}
>   	}
>   #endif
>   
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   		}
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> +		if (ret) {
>   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> -			ret = -EINVAL;
>   			goto fail;
>   		}
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5..2f72745660fb 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
>   	return dsc_config.bits_per_pixel;
>   }
>   
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>   {
>   	int i;
>   	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   	int remaining_to_increase = 0;
>   	int link_timeslots_used;
>   	int fair_pbn_alloc;
> +	int ret = 0;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   
>   		if (initial_slack[next_index] > fair_pbn_alloc) {
>   			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>   			} else {
>   				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		} else {
>   			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
>   			} else {
>   				vars[next_index].pbn -= initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		}
>   
>   		bpp_increased[next_index] = true;
>   		remaining_to_increase--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>   {
>   	int i;
>   	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   	int max_kbps_increase;
>   	int next_index;
>   	int remaining_to_try = 0;
> +	int ret;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   			break;
>   
>   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port->mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port->mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
>   
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>   			vars[next_index].dsc_enabled = false;
>   			vars[next_index].bpp_x16 = 0;
>   		} else {
>   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   
>   		tried[next_index] = true;
>   		remaining_to_try--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr *mgr,
> +					    int *link_vars_start_index)
>   {
>   	struct dc_stream_state *stream;
>   	struct dsc_mst_fairness_params params[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
>   	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>   	bool debugfs_overwrite = false;
>   
>   	memset(params, 0, sizeof(params));
>   
>   	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
>   
>   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   
>   	if (count == 0) {
>   		ASSERT(0);
> -		return true;
> +		return 0;
>   	}
>   
>   	/* k is start index of vars for current phy link used by mst hub */
> @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   		vars[i + k].dsc_enabled = false;
>   		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>   	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>   	}
>   
>   	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>   			vars[i + k].dsc_enabled = true;
>   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		} else {
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   			vars[i + k].dsc_enabled = false;
>   			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
>   
>   	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
>   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
>   
> -	return true;
> +	return 0;
>   }
>   
>   static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>   	return is_dsc_need_re_compute;
>   }
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   			continue;
>   
>   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
>   
>   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   
>   		if (stream->timing.flags.DSC == 1)
>   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1198,7 +1224,7 @@ static bool
>   		}
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
>   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
>   	return ret;
>   }
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>   {
>   	int i;
>   	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	if (!is_dsc_precompute_needed(state)) {
>   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>   	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>   	}
>   	dm_state = *dm_state_ptr;
>   
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
>   	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
>   
>   	for (i = 0; i < local_dc_state->stream_count; i++) {
>   		struct dc_stream_state *stream = dm_state->context->streams[i];
> @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   	if (ret != 0)
>   		goto clean_exit;
>   
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> -		ret = -EINVAL;
>   		goto clean_exit;
>   	}
>   
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	kfree(local_dc_state);
>   
> -	return (ret == 0);
> +	return ret;
>   }
>   
>   static unsigned int kbps_from_pbn(unsigned int pbn)
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa..97fd70df531b 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>   	struct amdgpu_dm_connector *aconnector;
>   };
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
>   
>   bool needs_dsc_aux_workaround(struct dc_link *link);
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
>   
>   enum dc_status dm_dp_mst_is_port_support_mode(
>   	struct amdgpu_dm_connector *aconnector,


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

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:54       ` Limonciello, Mario
  0 siblings, 0 replies; 43+ messages in thread
From: Limonciello, Mario @ 2022-11-18 19:54 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Alex Hung,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui, Roman Li, stable,
	Christian König, Thomas Zimmermann, Wayne Lin, Alex Deucher,
	Nicholas Kazlauskas

On 11/18/2022 13:25, Lyude Paul wrote:
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple
> true/false. In this case, it seems to have come back to bite us because as
> a result of simply returning false from
> compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> deadlock happened from these helpers. This could definitely result in some
> kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>    passing down return codes)
> V3:
> * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

FYI v2 was just merged recently, it's in the 6.2 pull request that was 
sent out and Alex planned to add it to 6.1-fixes next week too.

Can you send just the delta from v2->v3 as another patch so it can layer 
in cleanly?
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>   3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7..852a2100c6b3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   	struct drm_connector_state *new_con_state;
>   	struct amdgpu_dm_connector *aconnector;
>   	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>   	int vcpi, pbn_div, pbn, slot_num = 0;
>   
>   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   			dm_conn_state->pbn = pbn;
>   			dm_conn_state->vcpi_slots = slot_num;
>   
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> +							   dm_conn_state->pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>   			continue;
>   		}
>   
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
>   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>   			goto fail;
> -		}
>   	}
>   #endif
>   
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   		}
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> +		if (ret) {
>   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> -			ret = -EINVAL;
>   			goto fail;
>   		}
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5..2f72745660fb 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
>   	return dsc_config.bits_per_pixel;
>   }
>   
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>   {
>   	int i;
>   	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   	int remaining_to_increase = 0;
>   	int link_timeslots_used;
>   	int fair_pbn_alloc;
> +	int ret = 0;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   
>   		if (initial_slack[next_index] > fair_pbn_alloc) {
>   			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>   			} else {
>   				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		} else {
>   			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
>   			} else {
>   				vars[next_index].pbn -= initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		}
>   
>   		bpp_increased[next_index] = true;
>   		remaining_to_increase--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>   {
>   	int i;
>   	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   	int max_kbps_increase;
>   	int next_index;
>   	int remaining_to_try = 0;
> +	int ret;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   			break;
>   
>   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port->mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port->mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
>   
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>   			vars[next_index].dsc_enabled = false;
>   			vars[next_index].bpp_x16 = 0;
>   		} else {
>   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   
>   		tried[next_index] = true;
>   		remaining_to_try--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr *mgr,
> +					    int *link_vars_start_index)
>   {
>   	struct dc_stream_state *stream;
>   	struct dsc_mst_fairness_params params[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
>   	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>   	bool debugfs_overwrite = false;
>   
>   	memset(params, 0, sizeof(params));
>   
>   	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
>   
>   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   
>   	if (count == 0) {
>   		ASSERT(0);
> -		return true;
> +		return 0;
>   	}
>   
>   	/* k is start index of vars for current phy link used by mst hub */
> @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   		vars[i + k].dsc_enabled = false;
>   		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>   	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>   	}
>   
>   	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>   			vars[i + k].dsc_enabled = true;
>   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		} else {
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   			vars[i + k].dsc_enabled = false;
>   			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
>   
>   	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
>   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
>   
> -	return true;
> +	return 0;
>   }
>   
>   static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>   	return is_dsc_need_re_compute;
>   }
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   			continue;
>   
>   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
>   
>   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   
>   		if (stream->timing.flags.DSC == 1)
>   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1198,7 +1224,7 @@ static bool
>   		}
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
>   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
>   	return ret;
>   }
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>   {
>   	int i;
>   	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	if (!is_dsc_precompute_needed(state)) {
>   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>   	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>   	}
>   	dm_state = *dm_state_ptr;
>   
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
>   	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
>   
>   	for (i = 0; i < local_dc_state->stream_count; i++) {
>   		struct dc_stream_state *stream = dm_state->context->streams[i];
> @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   	if (ret != 0)
>   		goto clean_exit;
>   
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> -		ret = -EINVAL;
>   		goto clean_exit;
>   	}
>   
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	kfree(local_dc_state);
>   
> -	return (ret == 0);
> +	return ret;
>   }
>   
>   static unsigned int kbps_from_pbn(unsigned int pbn)
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa..97fd70df531b 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>   	struct amdgpu_dm_connector *aconnector;
>   };
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
>   
>   bool needs_dsc_aux_workaround(struct dc_link *link);
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
>   
>   enum dc_status dm_dp_mst_is_port_support_mode(
>   	struct amdgpu_dm_connector *aconnector,


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

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:54       ` Limonciello, Mario
  0 siblings, 0 replies; 43+ messages in thread
From: Limonciello, Mario @ 2022-11-18 19:54 UTC (permalink / raw)
  To: Lyude Paul, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, Roman Li, Hamza Mahfooz,
	David Francis, Rodrigo Siqueira, Leo Li, Fangzhi Zuo,
	Aurabindo Pillai, Alex Hung, hersen wu, Mikita Lipski, Pan,
	Xinhui, open list, stable, Nicholas Kazlauskas,
	Thomas Zimmermann, Wayne Lin, Alex Deucher, Christian König

On 11/18/2022 13:25, Lyude Paul wrote:
> It appears that amdgpu makes the mistake of completely ignoring the return
> values from the DP MST helpers, and instead just returns a simple
> true/false. In this case, it seems to have come back to bite us because as
> a result of simply returning false from
> compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> deadlock happened from these helpers. This could definitely result in some
> kernel splats.
> 
> V2:
> * Address Wayne's comments (fix another bunch of spots where we weren't
>    passing down return codes)
> V3:
> * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()

FYI v2 was just merged recently, it's in the 6.2 pull request that was 
sent out and Alex planned to add it to 6.1-fixes next week too.

Can you send just the delta from v2->v3 as another patch so it can layer 
in cleanly?
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: <stable@vger.kernel.org> # v5.6+
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
>   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
>   3 files changed, 147 insertions(+), 118 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 0db2a88cd4d7..852a2100c6b3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   	struct drm_connector_state *new_con_state;
>   	struct amdgpu_dm_connector *aconnector;
>   	struct dm_connector_state *dm_conn_state;
> -	int i, j;
> +	int i, j, ret;
>   	int vcpi, pbn_div, pbn, slot_num = 0;
>   
>   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
>   			dm_conn_state->pbn = pbn;
>   			dm_conn_state->vcpi_slots = slot_num;
>   
> -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> -						     false);
> +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> +							   dm_conn_state->pbn, false);
> +			if (ret < 0)
> +				return ret;
> +
>   			continue;
>   		}
>   
> @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
>   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> -			ret = -EINVAL;
> +		ret = pre_validate_dsc(state, &dm_state, vars);
> +		if (ret != 0)
>   			goto fail;
> -		}
>   	}
>   #endif
>   
> @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>   		}
>   
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> +		if (ret) {
>   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> -			ret = -EINVAL;
>   			goto fail;
>   		}
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 6ff96b4bdda5..2f72745660fb 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
>   	return dsc_config.bits_per_pixel;
>   }
>   
> -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> -			     struct drm_dp_mst_topology_state *mst_state,
> -			     struct dc_link *dc_link,
> -			     struct dsc_mst_fairness_params *params,
> -			     struct dsc_mst_fairness_vars *vars,
> -			     int count,
> -			     int k)
> +static int increase_dsc_bpp(struct drm_atomic_state *state,
> +			    struct drm_dp_mst_topology_state *mst_state,
> +			    struct dc_link *dc_link,
> +			    struct dsc_mst_fairness_params *params,
> +			    struct dsc_mst_fairness_vars *vars,
> +			    int count,
> +			    int k)
>   {
>   	int i;
>   	bool bpp_increased[MAX_PIPES];
> @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   	int remaining_to_increase = 0;
>   	int link_timeslots_used;
>   	int fair_pbn_alloc;
> +	int ret = 0;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled) {
> @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
>   
>   		if (initial_slack[next_index] > fair_pbn_alloc) {
>   			vars[next_index].pbn += fair_pbn_alloc;
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
>   			} else {
>   				vars[next_index].pbn -= fair_pbn_alloc;
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		} else {
>   			vars[next_index].pbn += initial_slack[next_index];
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> -			if (!drm_dp_mst_atomic_check(state)) {
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = drm_dp_mst_atomic_check(state);
> +			if (ret == 0) {
>   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
>   			} else {
>   				vars[next_index].pbn -= initial_slack[next_index];
> -				if (drm_dp_atomic_find_time_slots(state,
> -								  params[next_index].port->mgr,
> -								  params[next_index].port,
> -								  vars[next_index].pbn) < 0)
> -					return false;
> +				ret = drm_dp_atomic_find_time_slots(state,
> +								    params[next_index].port->mgr,
> +								    params[next_index].port,
> +								    vars[next_index].pbn);
> +				if (ret < 0)
> +					return ret;
>   			}
>   		}
>   
>   		bpp_increased[next_index] = true;
>   		remaining_to_increase--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool try_disable_dsc(struct drm_atomic_state *state,
> -			    struct dc_link *dc_link,
> -			    struct dsc_mst_fairness_params *params,
> -			    struct dsc_mst_fairness_vars *vars,
> -			    int count,
> -			    int k)
> +static int try_disable_dsc(struct drm_atomic_state *state,
> +			   struct dc_link *dc_link,
> +			   struct dsc_mst_fairness_params *params,
> +			   struct dsc_mst_fairness_vars *vars,
> +			   int count,
> +			   int k)
>   {
>   	int i;
>   	bool tried[MAX_PIPES];
> @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   	int max_kbps_increase;
>   	int next_index;
>   	int remaining_to_try = 0;
> +	int ret;
>   
>   	for (i = 0; i < count; i++) {
>   		if (vars[i + k].dsc_enabled
> @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
>   			break;
>   
>   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> -		if (drm_dp_atomic_find_time_slots(state,
> -						  params[next_index].port->mgr,
> -						  params[next_index].port,
> -						  vars[next_index].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state,
> +						    params[next_index].port->mgr,
> +						    params[next_index].port,
> +						    vars[next_index].pbn);
> +		if (ret < 0)
> +			return ret;
>   
> -		if (!drm_dp_mst_atomic_check(state)) {
> +		ret = drm_dp_mst_atomic_check(state);
> +		if (ret == 0) {
>   			vars[next_index].dsc_enabled = false;
>   			vars[next_index].bpp_x16 = 0;
>   		} else {
>   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> -			if (drm_dp_atomic_find_time_slots(state,
> -							  params[next_index].port->mgr,
> -							  params[next_index].port,
> -							  vars[next_index].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state,
> +							    params[next_index].port->mgr,
> +							    params[next_index].port,
> +							    vars[next_index].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   
>   		tried[next_index] = true;
>   		remaining_to_try--;
>   	}
> -	return true;
> +	return 0;
>   }
>   
> -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> -					     struct dc_state *dc_state,
> -					     struct dc_link *dc_link,
> -					     struct dsc_mst_fairness_vars *vars,
> -					     struct drm_dp_mst_topology_mgr *mgr,
> -					     int *link_vars_start_index)
> +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> +					    struct dc_state *dc_state,
> +					    struct dc_link *dc_link,
> +					    struct dsc_mst_fairness_vars *vars,
> +					    struct drm_dp_mst_topology_mgr *mgr,
> +					    int *link_vars_start_index)
>   {
>   	struct dc_stream_state *stream;
>   	struct dsc_mst_fairness_params params[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
>   	int count = 0;
> -	int i, k;
> +	int i, k, ret;
>   	bool debugfs_overwrite = false;
>   
>   	memset(params, 0, sizeof(params));
>   
>   	if (IS_ERR(mst_state))
> -		return false;
> +		return PTR_ERR(mst_state);
>   
>   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
>   #if defined(CONFIG_DRM_AMD_DC_DCN)
> @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   
>   	if (count == 0) {
>   		ASSERT(0);
> -		return true;
> +		return 0;
>   	}
>   
>   	/* k is start index of vars for current phy link used by mst hub */
> @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   		vars[i + k].dsc_enabled = false;
>   		vars[i + k].bpp_x16 = 0;
> -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> -						  vars[i + k].pbn) < 0)
> -			return false;
> +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> +						    vars[i + k].pbn);
> +		if (ret < 0)
> +			return ret;
>   	}
> -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret == 0 && !debugfs_overwrite) {
>   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> -		return true;
> +		return 0;
> +	} else if (ret != -ENOSPC) {
> +		return ret;
>   	}
>   
>   	/* Try max compression */
> @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
>   			vars[i + k].dsc_enabled = true;
>   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		} else {
>   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
>   			vars[i + k].dsc_enabled = false;
>   			vars[i + k].bpp_x16 = 0;
> -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> -							  params[i].port, vars[i + k].pbn) < 0)
> -				return false;
> +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> +							    params[i].port, vars[i + k].pbn);
> +			if (ret < 0)
> +				return ret;
>   		}
>   	}
> -	if (drm_dp_mst_atomic_check(state))
> -		return false;
> +	ret = drm_dp_mst_atomic_check(state);
> +	if (ret != 0)
> +		return ret;
>   
>   	/* Optimize degree of compression */
> -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
> -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> -		return false;
> +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> +	if (ret < 0)
> +		return ret;
>   
>   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
>   
> -	return true;
> +	return 0;
>   }
>   
>   static bool is_dsc_need_re_compute(
> @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
>   	return is_dsc_need_re_compute;
>   }
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars)
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   			continue;
>   
>   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> -			return false;
> +			return -EINVAL;
>   
>   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
>   
>   		if (stream->timing.flags.DSC == 1)
>   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> -				return false;
> +				return -EINVAL;
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
> -static bool
> -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -					      struct dc_state *dc_state,
> -					      struct dsc_mst_fairness_vars *vars)
> +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +						 struct dc_state *dc_state,
> +						 struct dsc_mst_fairness_vars *vars)
>   {
>   	int i, j;
>   	struct dc_stream_state *stream;
>   	bool computed_streams[MAX_PIPES];
>   	struct amdgpu_dm_connector *aconnector;
>   	int link_vars_start_index = 0;
> +	int ret = 0;
>   
>   	for (i = 0; i < dc_state->stream_count; i++)
>   		computed_streams[i] = false;
> @@ -1184,11 +1209,12 @@ static bool
>   			continue;
>   
>   		mutex_lock(&aconnector->mst_mgr.lock);
> -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> -						      &aconnector->mst_mgr,
> -						      &link_vars_start_index)) {
> +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> +						       &aconnector->mst_mgr,
> +						       &link_vars_start_index);
> +		if (ret != 0) {
>   			mutex_unlock(&aconnector->mst_mgr.lock);
> -			return false;
> +			return ret;
>   		}
>   		mutex_unlock(&aconnector->mst_mgr.lock);
>   
> @@ -1198,7 +1224,7 @@ static bool
>   		}
>   	}
>   
> -	return true;
> +	return ret;
>   }
>   
>   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
>   	return ret;
>   }
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars)
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars)
>   {
>   	int i;
>   	struct dm_atomic_state *dm_state;
> @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	if (!is_dsc_precompute_needed(state)) {
>   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> -		return true;
> +		return 0;
>   	}
> -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> +	ret = dm_atomic_get_state(state, dm_state_ptr);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> -		return false;
> +		return ret;
>   	}
>   	dm_state = *dm_state_ptr;
>   
> @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
>   	if (!local_dc_state)
> -		return false;
> +		return -ENOMEM;
>   
>   	for (i = 0; i < local_dc_state->stream_count; i++) {
>   		struct dc_stream_state *stream = dm_state->context->streams[i];
> @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   	if (ret != 0)
>   		goto clean_exit;
>   
> -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> +	if (ret != 0) {
>   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> -		ret = -EINVAL;
>   		goto clean_exit;
>   	}
>   
> @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
>   
>   	kfree(local_dc_state);
>   
> -	return (ret == 0);
> +	return ret;
>   }
>   
>   static unsigned int kbps_from_pbn(unsigned int pbn)
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> index b92a7c5671aa..97fd70df531b 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
>   	struct amdgpu_dm_connector *aconnector;
>   };
>   
> -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> -				       struct dc_state *dc_state,
> -				       struct dsc_mst_fairness_vars *vars);
> +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> +				      struct dc_state *dc_state,
> +				      struct dsc_mst_fairness_vars *vars);
>   
>   bool needs_dsc_aux_workaround(struct dc_link *link);
>   
> -bool pre_validate_dsc(struct drm_atomic_state *state,
> -		      struct dm_atomic_state **dm_state_ptr,
> -		      struct dsc_mst_fairness_vars *vars);
> +int pre_validate_dsc(struct drm_atomic_state *state,
> +		     struct dm_atomic_state **dm_state_ptr,
> +		     struct dsc_mst_fairness_vars *vars);
>   
>   enum dc_status dm_dp_mst_is_port_support_mode(
>   	struct amdgpu_dm_connector *aconnector,


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

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:54       ` Limonciello, Mario
  (?)
@ 2022-11-18 19:56         ` Lyude Paul
  -1 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:56 UTC (permalink / raw)
  To: Limonciello, Mario, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, Roman Li, Hamza Mahfooz,
	David Francis, Rodrigo Siqueira, Leo Li, Fangzhi Zuo,
	Aurabindo Pillai, Alex Hung, hersen wu, Mikita Lipski, Pan,
	Xinhui, open list, stable, Nicholas Kazlauskas,
	Thomas Zimmermann, Wayne Lin, Alex Deucher, Christian König

On Fri, 2022-11-18 at 13:54 -0600, Limonciello, Mario wrote:
> On 11/18/2022 13:25, Lyude Paul wrote:
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple
> > true/false. In this case, it seems to have come back to bite us because as
> > a result of simply returning false from
> > compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> > deadlock happened from these helpers. This could definitely result in some
> > kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >    passing down return codes)
> > V3:
> > * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()
> 
> FYI v2 was just merged recently, it's in the 6.2 pull request that was 
> sent out and Alex planned to add it to 6.1-fixes next week too.
> 
> Can you send just the delta from v2->v3 as another patch so it can layer 
> in cleanly?

Just did that :), it should be on the list now

> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >   3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7..852a2100c6b3 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   	struct drm_connector_state *new_con_state;
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >   	int vcpi, pbn_div, pbn, slot_num = 0;
> >   
> >   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> > @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   			dm_conn_state->pbn = pbn;
> >   			dm_conn_state->vcpi_slots = slot_num;
> >   
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> > +							   dm_conn_state->pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >   			continue;
> >   		}
> >   
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> >   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >   			goto fail;
> > -		}
> >   	}
> >   #endif
> >   
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   		}
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> > +		if (ret) {
> >   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> > -			ret = -EINVAL;
> >   			goto fail;
> >   		}
> >   
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5..2f72745660fb 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
> >   	return dsc_config.bits_per_pixel;
> >   }
> >   
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >   {
> >   	int i;
> >   	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   	int remaining_to_increase = 0;
> >   	int link_timeslots_used;
> >   	int fair_pbn_alloc;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   
> >   		if (initial_slack[next_index] > fair_pbn_alloc) {
> >   			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >   			} else {
> >   				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		} else {
> >   			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
> >   			} else {
> >   				vars[next_index].pbn -= initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		}
> >   
> >   		bpp_increased[next_index] = true;
> >   		remaining_to_increase--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >   {
> >   	int i;
> >   	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   	int max_kbps_increase;
> >   	int next_index;
> >   	int remaining_to_try = 0;
> > +	int ret;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   			break;
> >   
> >   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port->mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port->mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >   			vars[next_index].dsc_enabled = false;
> >   			vars[next_index].bpp_x16 = 0;
> >   		} else {
> >   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   
> >   		tried[next_index] = true;
> >   		remaining_to_try--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr *mgr,
> > +					    int *link_vars_start_index)
> >   {
> >   	struct dc_stream_state *stream;
> >   	struct dsc_mst_fairness_params params[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
> >   	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >   	bool debugfs_overwrite = false;
> >   
> >   	memset(params, 0, sizeof(params));
> >   
> >   	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> >   
> >   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   
> >   	if (count == 0) {
> >   		ASSERT(0);
> > -		return true;
> > +		return 0;
> >   	}
> >   
> >   	/* k is start index of vars for current phy link used by mst hub */
> > @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   		vars[i + k].dsc_enabled = false;
> >   		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >   	}
> >   
> >   	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >   			vars[i + k].dsc_enabled = true;
> >   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		} else {
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   			vars[i + k].dsc_enabled = false;
> >   			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> >   
> >   	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> >   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> >   
> > -	return true;
> > +	return 0;
> >   }
> >   
> >   static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >   	return is_dsc_need_re_compute;
> >   }
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   			continue;
> >   
> >   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> >   
> >   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   
> >   		if (stream->timing.flags.DSC == 1)
> >   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1198,7 +1224,7 @@ static bool
> >   		}
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> >   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> > @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
> >   	return ret;
> >   }
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i;
> >   	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	if (!is_dsc_precompute_needed(state)) {
> >   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >   	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >   	}
> >   	dm_state = *dm_state_ptr;
> >   
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
> >   	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> >   
> >   	for (i = 0; i < local_dc_state->stream_count; i++) {
> >   		struct dc_stream_state *stream = dm_state->context->streams[i];
> > @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   	if (ret != 0)
> >   		goto clean_exit;
> >   
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> > -		ret = -EINVAL;
> >   		goto clean_exit;
> >   	}
> >   
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	kfree(local_dc_state);
> >   
> > -	return (ret == 0);
> > +	return ret;
> >   }
> >   
> >   static unsigned int kbps_from_pbn(unsigned int pbn)
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa..97fd70df531b 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >   	struct amdgpu_dm_connector *aconnector;
> >   };
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> >   
> >   bool needs_dsc_aux_workaround(struct dc_link *link);
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> >   
> >   enum dc_status dm_dp_mst_is_port_support_mode(
> >   	struct amdgpu_dm_connector *aconnector,
> 

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


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

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:56         ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:56 UTC (permalink / raw)
  To: Limonciello, Mario, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, Roman Li, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Leo Li,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Alex Hung, hersen wu, Mikita Lipski, Pan, Xinhui, open list,
	stable, Nicholas Kazlauskas, Thomas Zimmermann, Wayne Lin,
	Alex Deucher, Christian König

On Fri, 2022-11-18 at 13:54 -0600, Limonciello, Mario wrote:
> On 11/18/2022 13:25, Lyude Paul wrote:
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple
> > true/false. In this case, it seems to have come back to bite us because as
> > a result of simply returning false from
> > compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> > deadlock happened from these helpers. This could definitely result in some
> > kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >    passing down return codes)
> > V3:
> > * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()
> 
> FYI v2 was just merged recently, it's in the 6.2 pull request that was 
> sent out and Alex planned to add it to 6.1-fixes next week too.
> 
> Can you send just the delta from v2->v3 as another patch so it can layer 
> in cleanly?

Just did that :), it should be on the list now

> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >   3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7..852a2100c6b3 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   	struct drm_connector_state *new_con_state;
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >   	int vcpi, pbn_div, pbn, slot_num = 0;
> >   
> >   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> > @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   			dm_conn_state->pbn = pbn;
> >   			dm_conn_state->vcpi_slots = slot_num;
> >   
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> > +							   dm_conn_state->pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >   			continue;
> >   		}
> >   
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> >   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >   			goto fail;
> > -		}
> >   	}
> >   #endif
> >   
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   		}
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> > +		if (ret) {
> >   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> > -			ret = -EINVAL;
> >   			goto fail;
> >   		}
> >   
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5..2f72745660fb 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
> >   	return dsc_config.bits_per_pixel;
> >   }
> >   
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >   {
> >   	int i;
> >   	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   	int remaining_to_increase = 0;
> >   	int link_timeslots_used;
> >   	int fair_pbn_alloc;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   
> >   		if (initial_slack[next_index] > fair_pbn_alloc) {
> >   			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >   			} else {
> >   				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		} else {
> >   			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
> >   			} else {
> >   				vars[next_index].pbn -= initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		}
> >   
> >   		bpp_increased[next_index] = true;
> >   		remaining_to_increase--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >   {
> >   	int i;
> >   	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   	int max_kbps_increase;
> >   	int next_index;
> >   	int remaining_to_try = 0;
> > +	int ret;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   			break;
> >   
> >   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port->mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port->mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >   			vars[next_index].dsc_enabled = false;
> >   			vars[next_index].bpp_x16 = 0;
> >   		} else {
> >   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   
> >   		tried[next_index] = true;
> >   		remaining_to_try--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr *mgr,
> > +					    int *link_vars_start_index)
> >   {
> >   	struct dc_stream_state *stream;
> >   	struct dsc_mst_fairness_params params[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
> >   	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >   	bool debugfs_overwrite = false;
> >   
> >   	memset(params, 0, sizeof(params));
> >   
> >   	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> >   
> >   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   
> >   	if (count == 0) {
> >   		ASSERT(0);
> > -		return true;
> > +		return 0;
> >   	}
> >   
> >   	/* k is start index of vars for current phy link used by mst hub */
> > @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   		vars[i + k].dsc_enabled = false;
> >   		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >   	}
> >   
> >   	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >   			vars[i + k].dsc_enabled = true;
> >   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		} else {
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   			vars[i + k].dsc_enabled = false;
> >   			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> >   
> >   	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> >   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> >   
> > -	return true;
> > +	return 0;
> >   }
> >   
> >   static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >   	return is_dsc_need_re_compute;
> >   }
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   			continue;
> >   
> >   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> >   
> >   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   
> >   		if (stream->timing.flags.DSC == 1)
> >   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1198,7 +1224,7 @@ static bool
> >   		}
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> >   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> > @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
> >   	return ret;
> >   }
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i;
> >   	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	if (!is_dsc_precompute_needed(state)) {
> >   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >   	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >   	}
> >   	dm_state = *dm_state_ptr;
> >   
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
> >   	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> >   
> >   	for (i = 0; i < local_dc_state->stream_count; i++) {
> >   		struct dc_stream_state *stream = dm_state->context->streams[i];
> > @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   	if (ret != 0)
> >   		goto clean_exit;
> >   
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> > -		ret = -EINVAL;
> >   		goto clean_exit;
> >   	}
> >   
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	kfree(local_dc_state);
> >   
> > -	return (ret == 0);
> > +	return ret;
> >   }
> >   
> >   static unsigned int kbps_from_pbn(unsigned int pbn)
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa..97fd70df531b 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >   	struct amdgpu_dm_connector *aconnector;
> >   };
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> >   
> >   bool needs_dsc_aux_workaround(struct dc_link *link);
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> >   
> >   enum dc_status dm_dp_mst_is_port_support_mode(
> >   	struct amdgpu_dm_connector *aconnector,
> 

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


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

* Re: [v3] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 19:56         ` Lyude Paul
  0 siblings, 0 replies; 43+ messages in thread
From: Lyude Paul @ 2022-11-18 19:56 UTC (permalink / raw)
  To: Limonciello, Mario, amd-gfx
  Cc: Wenjing Liu, open list:DRM DRIVERS, open list, Hamza Mahfooz,
	David Airlie, David Francis, Rodrigo Siqueira, Alex Hung,
	Fangzhi Zuo, Aurabindo Pillai, Harry Wentland, Daniel Vetter,
	Leo Li, hersen wu, Mikita Lipski, Pan, Xinhui, Roman Li, stable,
	Christian König, Thomas Zimmermann, Wayne Lin, Alex Deucher,
	Nicholas Kazlauskas

On Fri, 2022-11-18 at 13:54 -0600, Limonciello, Mario wrote:
> On 11/18/2022 13:25, Lyude Paul wrote:
> > It appears that amdgpu makes the mistake of completely ignoring the return
> > values from the DP MST helpers, and instead just returns a simple
> > true/false. In this case, it seems to have come back to bite us because as
> > a result of simply returning false from
> > compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a
> > deadlock happened from these helpers. This could definitely result in some
> > kernel splats.
> > 
> > V2:
> > * Address Wayne's comments (fix another bunch of spots where we weren't
> >    passing down return codes)
> > V3:
> > * Fix uninitialized var in pre_compute_mst_dsc_configs_for_state()
> 
> FYI v2 was just merged recently, it's in the 6.2 pull request that was 
> sent out and Alex planned to add it to 6.1-fixes next week too.
> 
> Can you send just the delta from v2->v3 as another patch so it can layer 
> in cleanly?

Just did that :), it should be on the list now

> > 
> > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > Cc: Harry Wentland <harry.wentland@amd.com>
> > Cc: <stable@vger.kernel.org> # v5.6+
> > ---
> >   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++--------
> >   .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> >   3 files changed, 147 insertions(+), 118 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > index 0db2a88cd4d7..852a2100c6b3 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   	struct drm_connector_state *new_con_state;
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct dm_connector_state *dm_conn_state;
> > -	int i, j;
> > +	int i, j, ret;
> >   	int vcpi, pbn_div, pbn, slot_num = 0;
> >   
> >   	for_each_new_connector_in_state(state, connector, new_con_state, i) {
> > @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> >   			dm_conn_state->pbn = pbn;
> >   			dm_conn_state->vcpi_slots = slot_num;
> >   
> > -			drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn,
> > -						     false);
> > +			ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
> > +							   dm_conn_state->pbn, false);
> > +			if (ret < 0)
> > +				return ret;
> > +
> >   			continue;
> >   		}
> >   
> > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> >   	if (dc_resource_is_dsc_encoding_supported(dc)) {
> > -		if (!pre_validate_dsc(state, &dm_state, vars)) {
> > -			ret = -EINVAL;
> > +		ret = pre_validate_dsc(state, &dm_state, vars);
> > +		if (ret != 0)
> >   			goto fail;
> > -		}
> >   	}
> >   #endif
> >   
> > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
> >   		}
> >   
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
> > +		ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
> > +		if (ret) {
> >   			DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
> > -			ret = -EINVAL;
> >   			goto fail;
> >   		}
> >   
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > index 6ff96b4bdda5..2f72745660fb 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
> >   	return dsc_config.bits_per_pixel;
> >   }
> >   
> > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > -			     struct drm_dp_mst_topology_state *mst_state,
> > -			     struct dc_link *dc_link,
> > -			     struct dsc_mst_fairness_params *params,
> > -			     struct dsc_mst_fairness_vars *vars,
> > -			     int count,
> > -			     int k)
> > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > +			    struct drm_dp_mst_topology_state *mst_state,
> > +			    struct dc_link *dc_link,
> > +			    struct dsc_mst_fairness_params *params,
> > +			    struct dsc_mst_fairness_vars *vars,
> > +			    int count,
> > +			    int k)
> >   {
> >   	int i;
> >   	bool bpp_increased[MAX_PIPES];
> > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   	int remaining_to_increase = 0;
> >   	int link_timeslots_used;
> >   	int fair_pbn_alloc;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled) {
> > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state,
> >   
> >   		if (initial_slack[next_index] > fair_pbn_alloc) {
> >   			vars[next_index].pbn += fair_pbn_alloc;
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> >   			} else {
> >   				vars[next_index].pbn -= fair_pbn_alloc;
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		} else {
> >   			vars[next_index].pbn += initial_slack[next_index];
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > -			if (!drm_dp_mst_atomic_check(state)) {
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> > +
> > +			ret = drm_dp_mst_atomic_check(state);
> > +			if (ret == 0) {
> >   				vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
> >   			} else {
> >   				vars[next_index].pbn -= initial_slack[next_index];
> > -				if (drm_dp_atomic_find_time_slots(state,
> > -								  params[next_index].port->mgr,
> > -								  params[next_index].port,
> > -								  vars[next_index].pbn) < 0)
> > -					return false;
> > +				ret = drm_dp_atomic_find_time_slots(state,
> > +								    params[next_index].port->mgr,
> > +								    params[next_index].port,
> > +								    vars[next_index].pbn);
> > +				if (ret < 0)
> > +					return ret;
> >   			}
> >   		}
> >   
> >   		bpp_increased[next_index] = true;
> >   		remaining_to_increase--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > -			    struct dc_link *dc_link,
> > -			    struct dsc_mst_fairness_params *params,
> > -			    struct dsc_mst_fairness_vars *vars,
> > -			    int count,
> > -			    int k)
> > +static int try_disable_dsc(struct drm_atomic_state *state,
> > +			   struct dc_link *dc_link,
> > +			   struct dsc_mst_fairness_params *params,
> > +			   struct dsc_mst_fairness_vars *vars,
> > +			   int count,
> > +			   int k)
> >   {
> >   	int i;
> >   	bool tried[MAX_PIPES];
> > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   	int max_kbps_increase;
> >   	int next_index;
> >   	int remaining_to_try = 0;
> > +	int ret;
> >   
> >   	for (i = 0; i < count; i++) {
> >   		if (vars[i + k].dsc_enabled
> > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct drm_atomic_state *state,
> >   			break;
> >   
> >   		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > -		if (drm_dp_atomic_find_time_slots(state,
> > -						  params[next_index].port->mgr,
> > -						  params[next_index].port,
> > -						  vars[next_index].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state,
> > +						    params[next_index].port->mgr,
> > +						    params[next_index].port,
> > +						    vars[next_index].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   
> > -		if (!drm_dp_mst_atomic_check(state)) {
> > +		ret = drm_dp_mst_atomic_check(state);
> > +		if (ret == 0) {
> >   			vars[next_index].dsc_enabled = false;
> >   			vars[next_index].bpp_x16 = 0;
> >   		} else {
> >   			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > -			if (drm_dp_atomic_find_time_slots(state,
> > -							  params[next_index].port->mgr,
> > -							  params[next_index].port,
> > -							  vars[next_index].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state,
> > +							    params[next_index].port->mgr,
> > +							    params[next_index].port,
> > +							    vars[next_index].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   
> >   		tried[next_index] = true;
> >   		remaining_to_try--;
> >   	}
> > -	return true;
> > +	return 0;
> >   }
> >   
> > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > -					     struct dc_state *dc_state,
> > -					     struct dc_link *dc_link,
> > -					     struct dsc_mst_fairness_vars *vars,
> > -					     struct drm_dp_mst_topology_mgr *mgr,
> > -					     int *link_vars_start_index)
> > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > +					    struct dc_state *dc_state,
> > +					    struct dc_link *dc_link,
> > +					    struct dsc_mst_fairness_vars *vars,
> > +					    struct drm_dp_mst_topology_mgr *mgr,
> > +					    int *link_vars_start_index)
> >   {
> >   	struct dc_stream_state *stream;
> >   	struct dsc_mst_fairness_params params[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr);
> >   	int count = 0;
> > -	int i, k;
> > +	int i, k, ret;
> >   	bool debugfs_overwrite = false;
> >   
> >   	memset(params, 0, sizeof(params));
> >   
> >   	if (IS_ERR(mst_state))
> > -		return false;
> > +		return PTR_ERR(mst_state);
> >   
> >   	mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
> >   #if defined(CONFIG_DRM_AMD_DC_DCN)
> > @@ -933,7 +946,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   
> >   	if (count == 0) {
> >   		ASSERT(0);
> > -		return true;
> > +		return 0;
> >   	}
> >   
> >   	/* k is start index of vars for current phy link used by mst hub */
> > @@ -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   		vars[i + k].dsc_enabled = false;
> >   		vars[i + k].bpp_x16 = 0;
> > -		if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > -						  vars[i + k].pbn) < 0)
> > -			return false;
> > +		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
> > +						    vars[i + k].pbn);
> > +		if (ret < 0)
> > +			return ret;
> >   	}
> > -	if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret == 0 && !debugfs_overwrite) {
> >   		set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > -		return true;
> > +		return 0;
> > +	} else if (ret != -ENOSPC) {
> > +		return ret;
> >   	}
> >   
> >   	/* Try max compression */
> > @@ -962,31 +979,36 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> >   			vars[i + k].dsc_enabled = true;
> >   			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		} else {
> >   			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> >   			vars[i + k].dsc_enabled = false;
> >   			vars[i + k].bpp_x16 = 0;
> > -			if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > -							  params[i].port, vars[i + k].pbn) < 0)
> > -				return false;
> > +			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
> > +							    params[i].port, vars[i + k].pbn);
> > +			if (ret < 0)
> > +				return ret;
> >   		}
> >   	}
> > -	if (drm_dp_mst_atomic_check(state))
> > -		return false;
> > +	ret = drm_dp_mst_atomic_check(state);
> > +	if (ret != 0)
> > +		return ret;
> >   
> >   	/* Optimize degree of compression */
> > -	if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> > -	if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > -		return false;
> > +	ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > +	if (ret < 0)
> > +		return ret;
> >   
> >   	set_dsc_configs_from_fairness_vars(params, vars, count, k);
> >   
> > -	return true;
> > +	return 0;
> >   }
> >   
> >   static bool is_dsc_need_re_compute(
> > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> >   	return is_dsc_need_re_compute;
> >   }
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars)
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   			continue;
> >   
> >   		if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -			return false;
> > +			return -EINVAL;
> >   
> >   		if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> >   
> >   		if (stream->timing.flags.DSC == 1)
> >   			if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
> > -				return false;
> > +				return -EINVAL;
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> > -static bool
> > -	pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -					      struct dc_state *dc_state,
> > -					      struct dsc_mst_fairness_vars *vars)
> > +static int pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +						 struct dc_state *dc_state,
> > +						 struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i, j;
> >   	struct dc_stream_state *stream;
> >   	bool computed_streams[MAX_PIPES];
> >   	struct amdgpu_dm_connector *aconnector;
> >   	int link_vars_start_index = 0;
> > +	int ret = 0;
> >   
> >   	for (i = 0; i < dc_state->stream_count; i++)
> >   		computed_streams[i] = false;
> > @@ -1184,11 +1209,12 @@ static bool
> >   			continue;
> >   
> >   		mutex_lock(&aconnector->mst_mgr.lock);
> > -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > -						      &aconnector->mst_mgr,
> > -						      &link_vars_start_index)) {
> > +		ret = compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars,
> > +						       &aconnector->mst_mgr,
> > +						       &link_vars_start_index);
> > +		if (ret != 0) {
> >   			mutex_unlock(&aconnector->mst_mgr.lock);
> > -			return false;
> > +			return ret;
> >   		}
> >   		mutex_unlock(&aconnector->mst_mgr.lock);
> >   
> > @@ -1198,7 +1224,7 @@ static bool
> >   		}
> >   	}
> >   
> > -	return true;
> > +	return ret;
> >   }
> >   
> >   static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
> > @@ -1253,9 +1279,9 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
> >   	return ret;
> >   }
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars)
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars)
> >   {
> >   	int i;
> >   	struct dm_atomic_state *dm_state;
> > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	if (!is_dsc_precompute_needed(state)) {
> >   		DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > -		return true;
> > +		return 0;
> >   	}
> > -	if (dm_atomic_get_state(state, dm_state_ptr)) {
> > +	ret = dm_atomic_get_state(state, dm_state_ptr);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > -		return false;
> > +		return ret;
> >   	}
> >   	dm_state = *dm_state_ptr;
> >   
> > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
> >   	if (!local_dc_state)
> > -		return false;
> > +		return -ENOMEM;
> >   
> >   	for (i = 0; i < local_dc_state->stream_count; i++) {
> >   		struct dc_stream_state *stream = dm_state->context->streams[i];
> > @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   	if (ret != 0)
> >   		goto clean_exit;
> >   
> > -	if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
> > +	ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars);
> > +	if (ret != 0) {
> >   		DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
> > -		ret = -EINVAL;
> >   		goto clean_exit;
> >   	}
> >   
> > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state *state,
> >   
> >   	kfree(local_dc_state);
> >   
> > -	return (ret == 0);
> > +	return ret;
> >   }
> >   
> >   static unsigned int kbps_from_pbn(unsigned int pbn)
> > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > index b92a7c5671aa..97fd70df531b 100644
> > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> >   	struct amdgpu_dm_connector *aconnector;
> >   };
> >   
> > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > -				       struct dc_state *dc_state,
> > -				       struct dsc_mst_fairness_vars *vars);
> > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > +				      struct dc_state *dc_state,
> > +				      struct dsc_mst_fairness_vars *vars);
> >   
> >   bool needs_dsc_aux_workaround(struct dc_link *link);
> >   
> > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > -		      struct dm_atomic_state **dm_state_ptr,
> > -		      struct dsc_mst_fairness_vars *vars);
> > +int pre_validate_dsc(struct drm_atomic_state *state,
> > +		     struct dm_atomic_state **dm_state_ptr,
> > +		     struct dsc_mst_fairness_vars *vars);
> >   
> >   enum dc_status dm_dp_mst_is_port_support_mode(
> >   	struct amdgpu_dm_connector *aconnector,
> 

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


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

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
  2022-11-18 19:53             ` Lyude Paul
  (?)
@ 2022-11-18 20:06               ` Alex Deucher
  -1 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 20:06 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Lin, Wayne, amd-gfx, Liu, Wenjing, open list:DRM DRIVERS,
	open list, Mahfooz, Hamza, David Airlie, Francis, David,
	Siqueira, Rodrigo, Hung, Alex, Zuo, Jerry, Pillai, Aurabindo,
	Wentland, Harry, Daniel Vetter, Li, Sun peng (Leo),
	Wu, Hersen, Mikita Lipski, Pan, Xinhui, Li, Roman, stable,
	Koenig, Christian, Thomas Zimmermann, Deucher, Alexander,
	Kazlauskas, Nicholas

On Fri, Nov 18, 2022 at 2:53 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
> it's in your branch, so I'll omit that and let you add it into the patch

Yeah, I'll add that.  Many thanks!

Alex

>
> On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> > of course, will do in just a moment
> >
> > On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > > I've already picked this up.  Can you send a follow up patch with just
> > > the coverity fix?
> > >
> > > Alex
> > >
> > > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > >
> > > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > > send out a respin real quick to fix it. It's just a missing variable
> > > > assignment (we leave ret unassigned by mistake in
> > > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > >
> > > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > > [Public]
> > > > >
> > > > > All the patch set looks good to me. Feel free to add:
> > > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > >
> > > > > Again, thank you Lyude for helping on this!!!
> > > > >
> > > > > Regards,
> > > > > Wayne
> > > > > > -----Original Message-----
> > > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > > To: amd-gfx@lists.freedesktop.org
> > > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > > deadlocking
> > > > > >
> > > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > > could definitely result in some kernel splats.
> > > > > >
> > > > > > V2:
> > > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > > >   passing down return codes)
> > > > > >
> > > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > > ---
> > > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > > --
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >     struct drm_connector_state *new_con_state;
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct dm_connector_state *dm_conn_state;
> > > > > > -   int i, j;
> > > > > > +   int i, j, ret;
> > > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > >
> > > > > >     for_each_new_connector_in_state(state, connector,
> > > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >                     dm_conn_state->pbn = pbn;
> > > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > >
> > > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > > port, dm_conn_state->pbn,
> > > > > > -                                                false);
> > > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > > aconnector->port,
> > > > > > +                                                      dm_conn_state-
> > > > > > > pbn, false);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > >                     continue;
> > > > > >             }
> > > > > >
> > > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > > -                   ret = -EINVAL;
> > > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > > +           if (ret != 0)
> > > > > >                     goto fail;
> > > > > > -           }
> > > > > >     }
> > > > > >  #endif
> > > > > >
> > > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >             }
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars);
> > > > > > +           if (ret) {
> > > > > >
> > > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -                   ret = -EINVAL;
> > > > > >                     goto fail;
> > > > > >             }
> > > > > >
> > > > > > diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > > dsc_mst_fairness_params param, int pbn)
> > > > > >     return dsc_config.bits_per_pixel;
> > > > > >  }
> > > > > >
> > > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > > -                        struct dc_link *dc_link,
> > > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                        int count,
> > > > > > -                        int k)
> > > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > > +                       struct dc_link *dc_link,
> > > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                       int count,
> > > > > > +                       int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool bpp_increased[MAX_PIPES];
> > > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >     int remaining_to_increase = 0;
> > > > > >     int link_timeslots_used;
> > > > > >     int fair_pbn_alloc;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled) {
> > > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -=
> > > > > > initial_slack[next_index];
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             }
> > > > > >
> > > > > >             bpp_increased[next_index] = true;
> > > > > >             remaining_to_increase--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > > -                       struct dc_link *dc_link,
> > > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > > -                       int count,
> > > > > > -                       int k)
> > > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > > +                      struct dc_link *dc_link,
> > > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > > +                      int count,
> > > > > > +                      int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool tried[MAX_PIPES];
> > > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >     int max_kbps_increase;
> > > > > >     int next_index;
> > > > > >     int remaining_to_try = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled
> > > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     break;
> > > > > >
> > > > > >             vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -                                             params[next_index].port-
> > > > > > > mgr,
> > > > > > -                                             params[next_index].port,
> > > > > > -                                             vars[next_index].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +                                               params[next_index].port-
> > > > > > > mgr,
> > > > > > +                                               params[next_index].port,
> > > > > > +                                               vars[next_index].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >
> > > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > > +           if (ret == 0) {
> > > > > >                     vars[next_index].dsc_enabled = false;
> > > > > >                     vars[next_index].bpp_x16 = 0;
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >
> > > > > >             tried[next_index] = true;
> > > > > >             remaining_to_try--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                        struct dc_state *dc_state,
> > > > > > -                                        struct dc_link *dc_link,
> > > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > -                                        int *link_vars_start_index)
> > > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > +                                       struct dc_state *dc_state,
> > > > > > +                                       struct dc_link *dc_link,
> > > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > +                                       int *link_vars_start_index)
> > > > > >  {
> > > > > >     struct dc_stream_state *stream;
> > > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > > >     int count = 0;
> > > > > > -   int i, k;
> > > > > > +   int i, k, ret;
> > > > > >     bool debugfs_overwrite = false;
> > > > > >
> > > > > >     memset(params, 0, sizeof(params));
> > > > > >
> > > > > >     if (IS_ERR(mst_state))
> > > > > > -           return false;
> > > > > > +           return PTR_ERR(mst_state);
> > > > > >
> > > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >
> > > > > >     if (count == 0) {
> > > > > >             ASSERT(0);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > >
> > > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > > drm_atomic_state *state,
> > > > > >             vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >             vars[i + k].dsc_enabled = false;
> > > > > >             vars[i + k].bpp_x16 = 0;
> > > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > -                                             vars[i + k].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > +                                               vars[i + k].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >     }
> > > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > > +   } else if (ret != -ENOSPC) {
> > > > > > +           return ret;
> > > > > >     }
> > > > > >
> > > > > >     /* Try max compression */
> > > > > > @@ -962,31 +979,36 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > > >                     vars[i + k].dsc_enabled = true;
> > > > > >                     vars[i + k].bpp_x16 =
> > > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             } else {
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >                     vars[i + k].dsc_enabled = false;
> > > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >     }
> > > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > > -           return false;
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret != 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     /* Optimize degree of compression */
> > > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > > k))
> > > > > > -           return false;
> > > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > > count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > > -           return false;
> > > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > >
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > >  static bool is_dsc_need_re_compute(
> > > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > > >     return is_dsc_need_re_compute;
> > > > > >  }
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     continue;
> > > > > >
> > > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > > dc_state, stream) != DC_OK)
> > > > > > -                   return false;
> > > > > > +                   return -EINVAL;
> > > > > >
> > > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (stream->timing.flags.DSC == 1)
> > > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > > dc, dc_state, stream) != DC_OK)
> > > > > > -                           return false;
> > > > > > +                           return -EINVAL;
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > > -static bool
> > > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                         struct dc_state *dc_state,
> > > > > > -                                         struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > > +                                            struct dc_state *dc_state,
> > > > > > +                                            struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > > >             }
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > > >     return ret;
> > > > > >  }
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i;
> > > > > >     struct dm_atomic_state *dm_state;
> > > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > > +   if (ret != 0) {
> > > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > > -           return false;
> > > > > > +           return ret;
> > > > > >     }
> > > > > >     dm_state = *dm_state_ptr;
> > > > > >
> > > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > > dc_state), GFP_KERNEL);
> > > > > >     if (!local_dc_state)
> > > > > > -           return false;
> > > > > > +           return -ENOMEM;
> > > > > >
> > > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >     if (ret != 0)
> > > > > >             goto clean_exit;
> > > > > >
> > > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars)) {
> > > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars);
> > > > > > +   if (ret != 0) {
> > > > > >
> > > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -           ret = -EINVAL;
> > > > > >             goto clean_exit;
> > > > > >     }
> > > > > >
> > > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     kfree(local_dc_state);
> > > > > >
> > > > > > -   return (ret == 0);
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > > --
> > > > > > 2.37.3
> > > > >
> > > >
> > > > --
> > > > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 20:06               ` Alex Deucher
  0 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 20:06 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	Francis, David, Siqueira, Rodrigo, amd-gfx, Li, Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Hung, Alex, Wu, Hersen,
	Mikita Lipski, Pan, Xinhui, open list, stable, Kazlauskas,
	Nicholas, Thomas Zimmermann, Lin, Wayne, Deucher, Alexander,
	Koenig, Christian

On Fri, Nov 18, 2022 at 2:53 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
> it's in your branch, so I'll omit that and let you add it into the patch

Yeah, I'll add that.  Many thanks!

Alex

>
> On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> > of course, will do in just a moment
> >
> > On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > > I've already picked this up.  Can you send a follow up patch with just
> > > the coverity fix?
> > >
> > > Alex
> > >
> > > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > >
> > > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > > send out a respin real quick to fix it. It's just a missing variable
> > > > assignment (we leave ret unassigned by mistake in
> > > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > >
> > > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > > [Public]
> > > > >
> > > > > All the patch set looks good to me. Feel free to add:
> > > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > >
> > > > > Again, thank you Lyude for helping on this!!!
> > > > >
> > > > > Regards,
> > > > > Wayne
> > > > > > -----Original Message-----
> > > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > > To: amd-gfx@lists.freedesktop.org
> > > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > > deadlocking
> > > > > >
> > > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > > could definitely result in some kernel splats.
> > > > > >
> > > > > > V2:
> > > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > > >   passing down return codes)
> > > > > >
> > > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > > ---
> > > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > > --
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >     struct drm_connector_state *new_con_state;
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct dm_connector_state *dm_conn_state;
> > > > > > -   int i, j;
> > > > > > +   int i, j, ret;
> > > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > >
> > > > > >     for_each_new_connector_in_state(state, connector,
> > > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >                     dm_conn_state->pbn = pbn;
> > > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > >
> > > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > > port, dm_conn_state->pbn,
> > > > > > -                                                false);
> > > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > > aconnector->port,
> > > > > > +                                                      dm_conn_state-
> > > > > > > pbn, false);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > >                     continue;
> > > > > >             }
> > > > > >
> > > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > > -                   ret = -EINVAL;
> > > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > > +           if (ret != 0)
> > > > > >                     goto fail;
> > > > > > -           }
> > > > > >     }
> > > > > >  #endif
> > > > > >
> > > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >             }
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars);
> > > > > > +           if (ret) {
> > > > > >
> > > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -                   ret = -EINVAL;
> > > > > >                     goto fail;
> > > > > >             }
> > > > > >
> > > > > > diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > > dsc_mst_fairness_params param, int pbn)
> > > > > >     return dsc_config.bits_per_pixel;
> > > > > >  }
> > > > > >
> > > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > > -                        struct dc_link *dc_link,
> > > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                        int count,
> > > > > > -                        int k)
> > > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > > +                       struct dc_link *dc_link,
> > > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                       int count,
> > > > > > +                       int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool bpp_increased[MAX_PIPES];
> > > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >     int remaining_to_increase = 0;
> > > > > >     int link_timeslots_used;
> > > > > >     int fair_pbn_alloc;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled) {
> > > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -=
> > > > > > initial_slack[next_index];
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             }
> > > > > >
> > > > > >             bpp_increased[next_index] = true;
> > > > > >             remaining_to_increase--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > > -                       struct dc_link *dc_link,
> > > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > > -                       int count,
> > > > > > -                       int k)
> > > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > > +                      struct dc_link *dc_link,
> > > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > > +                      int count,
> > > > > > +                      int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool tried[MAX_PIPES];
> > > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >     int max_kbps_increase;
> > > > > >     int next_index;
> > > > > >     int remaining_to_try = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled
> > > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     break;
> > > > > >
> > > > > >             vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -                                             params[next_index].port-
> > > > > > > mgr,
> > > > > > -                                             params[next_index].port,
> > > > > > -                                             vars[next_index].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +                                               params[next_index].port-
> > > > > > > mgr,
> > > > > > +                                               params[next_index].port,
> > > > > > +                                               vars[next_index].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >
> > > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > > +           if (ret == 0) {
> > > > > >                     vars[next_index].dsc_enabled = false;
> > > > > >                     vars[next_index].bpp_x16 = 0;
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >
> > > > > >             tried[next_index] = true;
> > > > > >             remaining_to_try--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                        struct dc_state *dc_state,
> > > > > > -                                        struct dc_link *dc_link,
> > > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > -                                        int *link_vars_start_index)
> > > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > +                                       struct dc_state *dc_state,
> > > > > > +                                       struct dc_link *dc_link,
> > > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > +                                       int *link_vars_start_index)
> > > > > >  {
> > > > > >     struct dc_stream_state *stream;
> > > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > > >     int count = 0;
> > > > > > -   int i, k;
> > > > > > +   int i, k, ret;
> > > > > >     bool debugfs_overwrite = false;
> > > > > >
> > > > > >     memset(params, 0, sizeof(params));
> > > > > >
> > > > > >     if (IS_ERR(mst_state))
> > > > > > -           return false;
> > > > > > +           return PTR_ERR(mst_state);
> > > > > >
> > > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >
> > > > > >     if (count == 0) {
> > > > > >             ASSERT(0);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > >
> > > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > > drm_atomic_state *state,
> > > > > >             vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >             vars[i + k].dsc_enabled = false;
> > > > > >             vars[i + k].bpp_x16 = 0;
> > > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > -                                             vars[i + k].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > +                                               vars[i + k].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >     }
> > > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > > +   } else if (ret != -ENOSPC) {
> > > > > > +           return ret;
> > > > > >     }
> > > > > >
> > > > > >     /* Try max compression */
> > > > > > @@ -962,31 +979,36 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > > >                     vars[i + k].dsc_enabled = true;
> > > > > >                     vars[i + k].bpp_x16 =
> > > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             } else {
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >                     vars[i + k].dsc_enabled = false;
> > > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >     }
> > > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > > -           return false;
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret != 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     /* Optimize degree of compression */
> > > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > > k))
> > > > > > -           return false;
> > > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > > count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > > -           return false;
> > > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > >
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > >  static bool is_dsc_need_re_compute(
> > > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > > >     return is_dsc_need_re_compute;
> > > > > >  }
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     continue;
> > > > > >
> > > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > > dc_state, stream) != DC_OK)
> > > > > > -                   return false;
> > > > > > +                   return -EINVAL;
> > > > > >
> > > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (stream->timing.flags.DSC == 1)
> > > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > > dc, dc_state, stream) != DC_OK)
> > > > > > -                           return false;
> > > > > > +                           return -EINVAL;
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > > -static bool
> > > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                         struct dc_state *dc_state,
> > > > > > -                                         struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > > +                                            struct dc_state *dc_state,
> > > > > > +                                            struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > > >             }
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > > >     return ret;
> > > > > >  }
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i;
> > > > > >     struct dm_atomic_state *dm_state;
> > > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > > +   if (ret != 0) {
> > > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > > -           return false;
> > > > > > +           return ret;
> > > > > >     }
> > > > > >     dm_state = *dm_state_ptr;
> > > > > >
> > > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > > dc_state), GFP_KERNEL);
> > > > > >     if (!local_dc_state)
> > > > > > -           return false;
> > > > > > +           return -ENOMEM;
> > > > > >
> > > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >     if (ret != 0)
> > > > > >             goto clean_exit;
> > > > > >
> > > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars)) {
> > > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars);
> > > > > > +   if (ret != 0) {
> > > > > >
> > > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -           ret = -EINVAL;
> > > > > >             goto clean_exit;
> > > > > >     }
> > > > > >
> > > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     kfree(local_dc_state);
> > > > > >
> > > > > > -   return (ret == 0);
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > > --
> > > > > > 2.37.3
> > > > >
> > > >
> > > > --
> > > > 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] 43+ messages in thread

* Re: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
@ 2022-11-18 20:06               ` Alex Deucher
  0 siblings, 0 replies; 43+ messages in thread
From: Alex Deucher @ 2022-11-18 20:06 UTC (permalink / raw)
  To: Lyude Paul
  Cc: Liu, Wenjing, open list:DRM DRIVERS, Li, Roman, Mahfooz, Hamza,
	David Airlie, Francis, David, Siqueira, Rodrigo, amd-gfx, Li,
	Sun peng (Leo),
	Zuo, Jerry, Pillai, Aurabindo, Wentland, Harry, Daniel Vetter,
	Hung, Alex, Wu, Hersen, Mikita Lipski, Pan, Xinhui, open list,
	stable, Kazlauskas, Nicholas, Thomas Zimmermann, Lin, Wayne,
	Deucher, Alexander, Koenig, Christian

On Fri, Nov 18, 2022 at 2:53 PM Lyude Paul <lyude@redhat.com> wrote:
>
> JFYI - I'm not sure of the correct commit ID to add for the Fixes: tag since
> it's in your branch, so I'll omit that and let you add it into the patch

Yeah, I'll add that.  Many thanks!

Alex

>
> On Fri, 2022-11-18 at 14:47 -0500, Lyude Paul wrote:
> > of course, will do in just a moment
> >
> > On Fri, 2022-11-18 at 14:46 -0500, Alex Deucher wrote:
> > > I've already picked this up.  Can you send a follow up patch with just
> > > the coverity fix?
> > >
> > > Alex
> > >
> > > On Fri, Nov 18, 2022 at 2:17 PM Lyude Paul <lyude@redhat.com> wrote:
> > > >
> > > > JFYI, Coverity pointed out one more issue with this series so I'm going to
> > > > send out a respin real quick to fix it. It's just a missing variable
> > > > assignment (we leave ret unassigned by mistake in
> > > > pre_compute_mst_dsc_configs()) so I will carry over your r-b on it.
> > > >
> > > > On Wed, 2022-11-16 at 04:39 +0000, Lin, Wayne wrote:
> > > > > [Public]
> > > > >
> > > > > All the patch set looks good to me. Feel free to add:
> > > > > Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
> > > > >
> > > > > Again, thank you Lyude for helping on this!!!
> > > > >
> > > > > Regards,
> > > > > Wayne
> > > > > > -----Original Message-----
> > > > > > From: Lyude Paul <lyude@redhat.com>
> > > > > > Sent: Tuesday, November 15, 2022 6:18 AM
> > > > > > To: amd-gfx@lists.freedesktop.org
> > > > > > Cc: Wentland, Harry <Harry.Wentland@amd.com>; stable@vger.kernel.org;
> > > > > > Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Siqueira, Rodrigo
> > > > > > <Rodrigo.Siqueira@amd.com>; Deucher, Alexander
> > > > > > <Alexander.Deucher@amd.com>; Koenig, Christian
> > > > > > <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>; David
> > > > > > Airlie <airlied@gmail.com>; Daniel Vetter <daniel@ffwll.ch>; Kazlauskas,
> > > > > > Nicholas <Nicholas.Kazlauskas@amd.com>; Pillai, Aurabindo
> > > > > > <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Zuo, Jerry
> > > > > > <Jerry.Zuo@amd.com>; Wu, Hersen <hersenxs.wu@amd.com>; Lin, Wayne
> > > > > > <Wayne.Lin@amd.com>; Thomas Zimmermann <tzimmermann@suse.de>;
> > > > > > Mahfooz, Hamza <Hamza.Mahfooz@amd.com>; Hung, Alex
> > > > > > <Alex.Hung@amd.com>; Mikita Lipski <mikita.lipski@amd.com>; Liu,
> > > > > > Wenjing <Wenjing.Liu@amd.com>; Francis, David
> > > > > > <David.Francis@amd.com>; open list:DRM DRIVERS <dri-
> > > > > > devel@lists.freedesktop.org>; open list <linux-kernel@vger.kernel.org>
> > > > > > Subject: [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and
> > > > > > deadlocking
> > > > > >
> > > > > > It appears that amdgpu makes the mistake of completely ignoring the return
> > > > > > values from the DP MST helpers, and instead just returns a simple true/false.
> > > > > > In this case, it seems to have come back to bite us because as a result of
> > > > > > simply returning false from compute_mst_dsc_configs_for_state(), amdgpu
> > > > > > had no way of telling when a deadlock happened from these helpers. This
> > > > > > could definitely result in some kernel splats.
> > > > > >
> > > > > > V2:
> > > > > > * Address Wayne's comments (fix another bunch of spots where we weren't
> > > > > >   passing down return codes)
> > > > > >
> > > > > > Signed-off-by: Lyude Paul <lyude@redhat.com>
> > > > > > Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share")
> > > > > > Cc: Harry Wentland <harry.wentland@amd.com>
> > > > > > Cc: <stable@vger.kernel.org> # v5.6+
> > > > > > ---
> > > > > >  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  18 +-
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 235 ++++++++++------
> > > > > > --
> > > > > >  .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |  12 +-
> > > > > >  3 files changed, 147 insertions(+), 118 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > index 0db2a88cd4d7b..852a2100c6b38 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > > > @@ -6462,7 +6462,7 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >     struct drm_connector_state *new_con_state;
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct dm_connector_state *dm_conn_state;
> > > > > > -   int i, j;
> > > > > > +   int i, j, ret;
> > > > > >     int vcpi, pbn_div, pbn, slot_num = 0;
> > > > > >
> > > > > >     for_each_new_connector_in_state(state, connector,
> > > > > > new_con_state, i) { @@ -6509,8 +6509,11 @@ static int
> > > > > > dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
> > > > > >                     dm_conn_state->pbn = pbn;
> > > > > >                     dm_conn_state->vcpi_slots = slot_num;
> > > > > >
> > > > > > -                   drm_dp_mst_atomic_enable_dsc(state, aconnector-
> > > > > > > port, dm_conn_state->pbn,
> > > > > > -                                                false);
> > > > > > +                   ret = drm_dp_mst_atomic_enable_dsc(state,
> > > > > > aconnector->port,
> > > > > > +                                                      dm_conn_state-
> > > > > > > pbn, false);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > >                     continue;
> > > > > >             }
> > > > > >
> > > > > > @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > >     if (dc_resource_is_dsc_encoding_supported(dc)) {
> > > > > > -           if (!pre_validate_dsc(state, &dm_state, vars)) {
> > > > > > -                   ret = -EINVAL;
> > > > > > +           ret = pre_validate_dsc(state, &dm_state, vars);
> > > > > > +           if (ret != 0)
> > > > > >                     goto fail;
> > > > > > -           }
> > > > > >     }
> > > > > >  #endif
> > > > > >
> > > > > > @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct
> > > > > > drm_device *dev,
> > > > > >             }
> > > > > >
> > > > > >  #if defined(CONFIG_DRM_AMD_DC_DCN)
> > > > > > -           if (!compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_state(state, dm_state-
> > > > > > > context, vars);
> > > > > > +           if (ret) {
> > > > > >
> > > > > >     DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -                   ret = -EINVAL;
> > > > > >                     goto fail;
> > > > > >             }
> > > > > >
> > > > > > diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > index 6ff96b4bdda5c..bba2e8aaa2c20 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> > > > > > @@ -703,13 +703,13 @@ static int bpp_x16_from_pbn(struct
> > > > > > dsc_mst_fairness_params param, int pbn)
> > > > > >     return dsc_config.bits_per_pixel;
> > > > > >  }
> > > > > >
> > > > > > -static bool increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > -                        struct drm_dp_mst_topology_state *mst_state,
> > > > > > -                        struct dc_link *dc_link,
> > > > > > -                        struct dsc_mst_fairness_params *params,
> > > > > > -                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                        int count,
> > > > > > -                        int k)
> > > > > > +static int increase_dsc_bpp(struct drm_atomic_state *state,
> > > > > > +                       struct drm_dp_mst_topology_state *mst_state,
> > > > > > +                       struct dc_link *dc_link,
> > > > > > +                       struct dsc_mst_fairness_params *params,
> > > > > > +                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                       int count,
> > > > > > +                       int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool bpp_increased[MAX_PIPES];
> > > > > > @@ -719,6 +719,7 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >     int remaining_to_increase = 0;
> > > > > >     int link_timeslots_used;
> > > > > >     int fair_pbn_alloc;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled) {
> > > > > > @@ -757,52 +758,60 @@ static bool increase_dsc_bpp(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (initial_slack[next_index] > fair_pbn_alloc) {
> > > > > >                     vars[next_index].pbn += fair_pbn_alloc;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -= fair_pbn_alloc;
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn += initial_slack[next_index];
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > -                   if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > > +
> > > > > > +                   ret = drm_dp_mst_atomic_check(state);
> > > > > > +                   if (ret == 0) {
> > > > > >                             vars[next_index].bpp_x16 =
> > > > > > params[next_index].bw_range.max_target_bpp_x16;
> > > > > >                     } else {
> > > > > >                             vars[next_index].pbn -=
> > > > > > initial_slack[next_index];
> > > > > > -                           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                                   return false;
> > > > > > +                           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                           if (ret < 0)
> > > > > > +                                   return ret;
> > > > > >                     }
> > > > > >             }
> > > > > >
> > > > > >             bpp_increased[next_index] = true;
> > > > > >             remaining_to_increase--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool try_disable_dsc(struct drm_atomic_state *state,
> > > > > > -                       struct dc_link *dc_link,
> > > > > > -                       struct dsc_mst_fairness_params *params,
> > > > > > -                       struct dsc_mst_fairness_vars *vars,
> > > > > > -                       int count,
> > > > > > -                       int k)
> > > > > > +static int try_disable_dsc(struct drm_atomic_state *state,
> > > > > > +                      struct dc_link *dc_link,
> > > > > > +                      struct dsc_mst_fairness_params *params,
> > > > > > +                      struct dsc_mst_fairness_vars *vars,
> > > > > > +                      int count,
> > > > > > +                      int k)
> > > > > >  {
> > > > > >     int i;
> > > > > >     bool tried[MAX_PIPES];
> > > > > > @@ -810,6 +819,7 @@ static bool try_disable_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >     int max_kbps_increase;
> > > > > >     int next_index;
> > > > > >     int remaining_to_try = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < count; i++) {
> > > > > >             if (vars[i + k].dsc_enabled
> > > > > > @@ -840,49 +850,52 @@ static bool try_disable_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     break;
> > > > > >
> > > > > >             vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
> > > > > > -           if (drm_dp_atomic_find_time_slots(state,
> > > > > > -                                             params[next_index].port-
> > > > > > > mgr,
> > > > > > -                                             params[next_index].port,
> > > > > > -                                             vars[next_index].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +                                               params[next_index].port-
> > > > > > > mgr,
> > > > > > +                                               params[next_index].port,
> > > > > > +                                               vars[next_index].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >
> > > > > > -           if (!drm_dp_mst_atomic_check(state)) {
> > > > > > +           ret = drm_dp_mst_atomic_check(state);
> > > > > > +           if (ret == 0) {
> > > > > >                     vars[next_index].dsc_enabled = false;
> > > > > >                     vars[next_index].bpp_x16 = 0;
> > > > > >             } else {
> > > > > >                     vars[next_index].pbn =
> > > > > > kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > -
> > > > > > params[next_index].port->mgr,
> > > > > > -
> > > > > > params[next_index].port,
> > > > > > -
> > > > > > vars[next_index].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > +
> > > > > > params[next_index].port->mgr,
> > > > > > +
> > > > > > params[next_index].port,
> > > > > > +
> > > > > > vars[next_index].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >
> > > > > >             tried[next_index] = true;
> > > > > >             remaining_to_try--;
> > > > > >     }
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > > -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                        struct dc_state *dc_state,
> > > > > > -                                        struct dc_link *dc_link,
> > > > > > -                                        struct dsc_mst_fairness_vars *vars,
> > > > > > -                                        struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > -                                        int *link_vars_start_index)
> > > > > > +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state
> > > > > > *state,
> > > > > > +                                       struct dc_state *dc_state,
> > > > > > +                                       struct dc_link *dc_link,
> > > > > > +                                       struct dsc_mst_fairness_vars *vars,
> > > > > > +                                       struct drm_dp_mst_topology_mgr
> > > > > > *mgr,
> > > > > > +                                       int *link_vars_start_index)
> > > > > >  {
> > > > > >     struct dc_stream_state *stream;
> > > > > >     struct dsc_mst_fairness_params params[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     struct drm_dp_mst_topology_state *mst_state =
> > > > > > drm_atomic_get_mst_topology_state(state, mgr);
> > > > > >     int count = 0;
> > > > > > -   int i, k;
> > > > > > +   int i, k, ret;
> > > > > >     bool debugfs_overwrite = false;
> > > > > >
> > > > > >     memset(params, 0, sizeof(params));
> > > > > >
> > > > > >     if (IS_ERR(mst_state))
> > > > > > -           return false;
> > > > > > +           return PTR_ERR(mst_state);
> > > > > >
> > > > > >     mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);  #if
> > > > > > defined(CONFIG_DRM_AMD_DC_DCN) @@ -933,7 +946,7 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >
> > > > > >     if (count == 0) {
> > > > > >             ASSERT(0);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > >
> > > > > >     /* k is start index of vars for current phy link used by mst hub */ @@
> > > > > > -947,13 +960,17 @@ static bool compute_mst_dsc_configs_for_link(struct
> > > > > > drm_atomic_state *state,
> > > > > >             vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >             vars[i + k].dsc_enabled = false;
> > > > > >             vars[i + k].bpp_x16 = 0;
> > > > > > -           if (drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > -                                             vars[i + k].pbn) < 0)
> > > > > > -                   return false;
> > > > > > +           ret = drm_dp_atomic_find_time_slots(state, params[i].port-
> > > > > > > mgr, params[i].port,
> > > > > > +                                               vars[i + k].pbn);
> > > > > > +           if (ret < 0)
> > > > > > +                   return ret;
> > > > > >     }
> > > > > > -   if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) {
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret == 0 && !debugfs_overwrite) {
> > > > > >             set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > > +   } else if (ret != -ENOSPC) {
> > > > > > +           return ret;
> > > > > >     }
> > > > > >
> > > > > >     /* Try max compression */
> > > > > > @@ -962,31 +979,36 @@ static bool
> > > > > > compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.min_kbps);
> > > > > >                     vars[i + k].dsc_enabled = true;
> > > > > >                     vars[i + k].bpp_x16 =
> > > > > > params[i].bw_range.min_target_bpp_x16;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             } else {
> > > > > >                     vars[i + k].pbn =
> > > > > > kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
> > > > > >                     vars[i + k].dsc_enabled = false;
> > > > > >                     vars[i + k].bpp_x16 = 0;
> > > > > > -                   if (drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > -                                                     params[i].port, vars[i
> > > > > > + k].pbn) < 0)
> > > > > > -                           return false;
> > > > > > +                   ret = drm_dp_atomic_find_time_slots(state,
> > > > > > params[i].port->mgr,
> > > > > > +                                                       params[i].port,
> > > > > > vars[i + k].pbn);
> > > > > > +                   if (ret < 0)
> > > > > > +                           return ret;
> > > > > >             }
> > > > > >     }
> > > > > > -   if (drm_dp_mst_atomic_check(state))
> > > > > > -           return false;
> > > > > > +   ret = drm_dp_mst_atomic_check(state);
> > > > > > +   if (ret != 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     /* Optimize degree of compression */
> > > > > > -   if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count,
> > > > > > k))
> > > > > > -           return false;
> > > > > > +   ret = increase_dsc_bpp(state, mst_state, dc_link, params, vars,
> > > > > > count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > > -   if (!try_disable_dsc(state, dc_link, params, vars, count, k))
> > > > > > -           return false;
> > > > > > +   ret = try_disable_dsc(state, dc_link, params, vars, count, k);
> > > > > > +   if (ret < 0)
> > > > > > +           return ret;
> > > > > >
> > > > > >     set_dsc_configs_from_fairness_vars(params, vars, count, k);
> > > > > >
> > > > > > -   return true;
> > > > > > +   return 0;
> > > > > >  }
> > > > > >
> > > > > >  static bool is_dsc_need_re_compute(
> > > > > > @@ -1087,15 +1109,16 @@ static bool is_dsc_need_re_compute(
> > > > > >     return is_dsc_need_re_compute;
> > > > > >  }
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars)
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret = 0;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1118,17 +1141,19 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >                     continue;
> > > > > >
> > > > > >             if (dcn20_remove_stream_from_ctx(stream->ctx->dc,
> > > > > > dc_state, stream) != DC_OK)
> > > > > > -                   return false;
> > > > > > +                   return -EINVAL;
> > > > > >
> > > > > >             if (!is_dsc_need_re_compute(state, dc_state, stream->link))
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1143,22 +1168,22 @@ bool compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > >
> > > > > >             if (stream->timing.flags.DSC == 1)
> > > > > >                     if (dc_stream_add_dsc_to_resource(stream->ctx-
> > > > > > > dc, dc_state, stream) != DC_OK)
> > > > > > -                           return false;
> > > > > > +                           return -EINVAL;
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > > -static bool
> > > > > > -   pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state
> > > > > > *state,
> > > > > > -                                         struct dc_state *dc_state,
> > > > > > -                                         struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > > +static int pre_compute_mst_dsc_configs_for_state(struct
> > > > > > drm_atomic_state *state,
> > > > > > +                                            struct dc_state *dc_state,
> > > > > > +                                            struct dsc_mst_fairness_vars
> > > > > > *vars)
> > > > > >  {
> > > > > >     int i, j;
> > > > > >     struct dc_stream_state *stream;
> > > > > >     bool computed_streams[MAX_PIPES];
> > > > > >     struct amdgpu_dm_connector *aconnector;
> > > > > >     int link_vars_start_index = 0;
> > > > > > +   int ret;
> > > > > >
> > > > > >     for (i = 0; i < dc_state->stream_count; i++)
> > > > > >             computed_streams[i] = false;
> > > > > > @@ -1184,11 +1209,12 @@ static bool
> > > > > >                     continue;
> > > > > >
> > > > > >             mutex_lock(&aconnector->mst_mgr.lock);
> > > > > > -           if (!compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > -                                                 &aconnector->mst_mgr,
> > > > > > -                                                 &link_vars_start_index)) {
> > > > > > +           ret = compute_mst_dsc_configs_for_link(state, dc_state,
> > > > > > stream->link, vars,
> > > > > > +                                                  &aconnector->mst_mgr,
> > > > > > +                                                  &link_vars_start_index);
> > > > > > +           if (ret != 0) {
> > > > > >                     mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > > -                   return false;
> > > > > > +                   return ret;
> > > > > >             }
> > > > > >             mutex_unlock(&aconnector->mst_mgr.lock);
> > > > > >
> > > > > > @@ -1198,7 +1224,7 @@ static bool
> > > > > >             }
> > > > > >     }
> > > > > >
> > > > > > -   return true;
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static int find_crtc_index_in_state_by_stream(struct drm_atomic_state
> > > > > > *state, @@ -1253,9 +1279,9 @@ static bool
> > > > > > is_dsc_precompute_needed(struct drm_atomic_state *state)
> > > > > >     return ret;
> > > > > >  }
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars)
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars)
> > > > > >  {
> > > > > >     int i;
> > > > > >     struct dm_atomic_state *dm_state;
> > > > > > @@ -1264,11 +1290,12 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     if (!is_dsc_precompute_needed(state)) {
> > > > > >             DRM_INFO_ONCE("DSC precompute is not needed.\n");
> > > > > > -           return true;
> > > > > > +           return 0;
> > > > > >     }
> > > > > > -   if (dm_atomic_get_state(state, dm_state_ptr)) {
> > > > > > +   ret = dm_atomic_get_state(state, dm_state_ptr);
> > > > > > +   if (ret != 0) {
> > > > > >             DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
> > > > > > -           return false;
> > > > > > +           return ret;
> > > > > >     }
> > > > > >     dm_state = *dm_state_ptr;
> > > > > >
> > > > > > @@ -1280,7 +1307,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     local_dc_state = kmemdup(dm_state->context, sizeof(struct
> > > > > > dc_state), GFP_KERNEL);
> > > > > >     if (!local_dc_state)
> > > > > > -           return false;
> > > > > > +           return -ENOMEM;
> > > > > >
> > > > > >     for (i = 0; i < local_dc_state->stream_count; i++) {
> > > > > >             struct dc_stream_state *stream = dm_state->context-
> > > > > > > streams[i]; @@ -1316,9 +1343,9 @@ bool pre_validate_dsc(struct
> > > > > > drm_atomic_state *state,
> > > > > >     if (ret != 0)
> > > > > >             goto clean_exit;
> > > > > >
> > > > > > -   if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars)) {
> > > > > > +   ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state,
> > > > > > vars);
> > > > > > +   if (ret != 0) {
> > > > > >
> > > > > >     DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state()
> > > > > > failed\n");
> > > > > > -           ret = -EINVAL;
> > > > > >             goto clean_exit;
> > > > > >     }
> > > > > >
> > > > > > @@ -1349,7 +1376,7 @@ bool pre_validate_dsc(struct drm_atomic_state
> > > > > > *state,
> > > > > >
> > > > > >     kfree(local_dc_state);
> > > > > >
> > > > > > -   return (ret == 0);
> > > > > > +   return ret;
> > > > > >  }
> > > > > >
> > > > > >  static unsigned int kbps_from_pbn(unsigned int pbn) diff --git
> > > > > > a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > index b92a7c5671aa2..97fd70df531bf 100644
> > > > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > +++
> > > > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
> > > > > > @@ -53,15 +53,15 @@ struct dsc_mst_fairness_vars {
> > > > > >     struct amdgpu_dm_connector *aconnector;  };
> > > > > >
> > > > > > -bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > -                                  struct dc_state *dc_state,
> > > > > > -                                  struct dsc_mst_fairness_vars *vars);
> > > > > > +int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
> > > > > > +                                 struct dc_state *dc_state,
> > > > > > +                                 struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  bool needs_dsc_aux_workaround(struct dc_link *link);
> > > > > >
> > > > > > -bool pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > -                 struct dm_atomic_state **dm_state_ptr,
> > > > > > -                 struct dsc_mst_fairness_vars *vars);
> > > > > > +int pre_validate_dsc(struct drm_atomic_state *state,
> > > > > > +                struct dm_atomic_state **dm_state_ptr,
> > > > > > +                struct dsc_mst_fairness_vars *vars);
> > > > > >
> > > > > >  enum dc_status dm_dp_mst_is_port_support_mode(
> > > > > >     struct amdgpu_dm_connector *aconnector,
> > > > > > --
> > > > > > 2.37.3
> > > > >
> > > >
> > > > --
> > > > 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] 43+ messages in thread

end of thread, other threads:[~2022-11-18 20:07 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-14 22:17 [PATCH v2 0/4] drm/amdgpu: Regression fixes from MST atomic-only conversion Lyude Paul
2022-11-14 22:17 ` [PATCH v2 1/4] drm/amdgpu/mst: Stop ignoring error codes and deadlocking Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-16  4:39   ` Lin, Wayne
2022-11-16  4:39     ` Lin, Wayne
2022-11-16  4:39     ` Lin, Wayne
2022-11-16 22:43     ` Lyude Paul
2022-11-16 22:43       ` Lyude Paul
2022-11-16 22:43       ` Lyude Paul
2022-11-18 19:17     ` Lyude Paul
2022-11-18 19:17       ` Lyude Paul
2022-11-18 19:17       ` Lyude Paul
2022-11-18 19:46       ` Alex Deucher
2022-11-18 19:46         ` Alex Deucher
2022-11-18 19:46         ` Alex Deucher
2022-11-18 19:47         ` Lyude Paul
2022-11-18 19:47           ` Lyude Paul
2022-11-18 19:47           ` Lyude Paul
2022-11-18 19:53           ` Lyude Paul
2022-11-18 19:53             ` Lyude Paul
2022-11-18 19:53             ` Lyude Paul
2022-11-18 20:06             ` Alex Deucher
2022-11-18 20:06               ` Alex Deucher
2022-11-18 20:06               ` Alex Deucher
2022-11-18 19:25   ` [PATCH v3] " Lyude Paul
2022-11-18 19:25     ` Lyude Paul
2022-11-18 19:25     ` Lyude Paul
2022-11-18 19:54     ` [v3] " Limonciello, Mario
2022-11-18 19:54       ` Limonciello, Mario
2022-11-18 19:54       ` Limonciello, Mario
2022-11-18 19:56       ` Lyude Paul
2022-11-18 19:56         ` Lyude Paul
2022-11-18 19:56         ` Lyude Paul
2022-11-14 22:17 ` [PATCH v2 2/4] drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17 ` [PATCH v2 3/4] drm/amdgpu/dm/mst: Use the correct topology mgr pointer in amdgpu_dm_connector Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17 ` [PATCH v2 4/4] drm/amdgpu/dm/dp_mst: Don't grab mst_mgr->lock when computing DSC state Lyude Paul
2022-11-14 22:17   ` Lyude Paul
2022-11-14 22:17   ` Lyude Paul

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.