Browse Source

disp: msm: dp: fix dsc resource bookkeeping for mst

DP driver maintains the number of allocated DSCs per stream for managing
the availability of DSC blocks for each stream. In the current driver,
if there are errors in the disable path, it is possible for the refcount
to go negative thereby affecting the availability of DSC blocks in
subsequent enables.

This change fixes the refcount logic by making sure the DSC count in the
context correctly reflects the usage.

Change-Id: Id595ec87c186ddb3ed300e1390384f367ef79148
Signed-off-by: Sandeep Gangadharaiah <[email protected]>
Sandeep Gangadharaiah 4 năm trước cách đây
mục cha
commit
ed103ed1ef
2 tập tin đã thay đổi với 37 bổ sung34 xóa
  1. 35 32
      msm/dp/dp_display.c
  2. 2 2
      msm/dp/dp_panel.h

+ 35 - 32
msm/dp/dp_display.c

@@ -1378,6 +1378,31 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
 	return 0;
 }
 
+static void dp_display_update_dsc_resources(struct dp_display_private *dp,
+		struct dp_panel *panel, bool enable)
+{
+	int rc;
+	u32 dsc_blk_cnt = 0;
+	struct msm_drm_private *priv = dp->priv;
+
+	if (enable) {
+		if (panel->pinfo.comp_info.comp_type == MSM_DISPLAY_COMPRESSION_DSC &&
+				(panel->pinfo.comp_info.comp_ratio > 1)) {
+			rc = msm_get_dsc_count(priv, panel->pinfo.h_active,
+					&dsc_blk_cnt);
+			if (rc) {
+				DP_ERR("error getting dsc count. rc:%d\n", rc);
+				return;
+			}
+		}
+		dp->tot_dsc_blks_in_use += dsc_blk_cnt;
+		panel->dsc_blks_in_use += dsc_blk_cnt;
+	} else {
+		dp->tot_dsc_blks_in_use -= panel->dsc_blks_in_use;
+		panel->dsc_blks_in_use = 0;
+	}
+}
+
 static int dp_display_stream_pre_disable(struct dp_display_private *dp,
 			struct dp_panel *dp_panel)
 {
@@ -1407,8 +1432,11 @@ static void dp_display_stream_disable(struct dp_display_private *dp,
 		return;
 	}
 
-	DP_DEBUG("stream_id=%d, active_stream_cnt=%d\n",
-			dp_panel->stream_id, dp->active_stream_cnt);
+	dp_display_update_dsc_resources(dp, dp_panel, false);
+
+	DP_DEBUG("stream_id=%d, active_stream_cnt=%d, tot_dsc_blks_in_use=%d\n",
+			dp_panel->stream_id, dp->active_stream_cnt,
+			dp->tot_dsc_blks_in_use);
 
 	dp->ctrl->stream_off(dp->ctrl, dp_panel);
 	dp->active_panels[dp_panel->stream_id] = NULL;
@@ -1577,7 +1605,10 @@ static int dp_display_stream_enable(struct dp_display_private *dp,
 		dp->active_stream_cnt++;
 	}
 
-	DP_DEBUG("dp active_stream_cnt:%d\n", dp->active_stream_cnt);
+	dp_display_update_dsc_resources(dp, dp_panel, true);
+
+	DP_DEBUG("dp active_stream_cnt:%d, tot_dsc_blks_in_use=%d\n",
+			dp->active_stream_cnt, dp->tot_dsc_blks_in_use);
 
 	return rc;
 }
@@ -2286,32 +2317,6 @@ static int dp_display_set_stream_info(struct dp_display *dp_display,
 	return rc;
 }
 
-static void dp_display_update_dsc_resources(struct dp_display_private *dp,
-		struct dp_panel *panel, bool enable)
-{
-	int rc;
-	u32 dsc_blk_cnt = 0;
-	struct msm_drm_private *priv = dp->priv;
-
-	if (panel->pinfo.comp_info.comp_type == MSM_DISPLAY_COMPRESSION_DSC &&
-			(panel->pinfo.comp_info.comp_ratio > 1)) {
-		rc = msm_get_dsc_count(priv, panel->pinfo.h_active,
-				&dsc_blk_cnt);
-		if (rc) {
-			DP_ERR("error getting dsc count. rc:%d\n", rc);
-			return;
-		}
-	}
-
-	if (enable) {
-		dp->tot_dsc_blks_in_use += dsc_blk_cnt;
-		panel->tot_dsc_blks_in_use += dsc_blk_cnt;
-	} else {
-		dp->tot_dsc_blks_in_use -= dsc_blk_cnt;
-		panel->tot_dsc_blks_in_use -= dsc_blk_cnt;
-	}
-}
-
 static int dp_display_enable(struct dp_display *dp_display, void *panel)
 {
 	int rc = 0;
@@ -2351,7 +2356,6 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel)
 	if (rc)
 		goto end;
 
-	dp_display_update_dsc_resources(dp, panel, true);
 	dp_display_state_add(DP_STATE_ENABLED);
 end:
 	mutex_unlock(&dp->session_lock);
@@ -2537,7 +2541,6 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel)
 	}
 
 	dp_display_stream_disable(dp, dp_panel);
-	dp_display_update_dsc_resources(dp, dp_panel, false);
 
 	dp_display_state_remove(DP_STATE_HDCP_ABORTED);
 	for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
@@ -3002,7 +3005,7 @@ static void dp_display_convert_to_dp_mode(struct dp_display *dp_display,
 
 	free_dsc_blks = dp_display->max_dsc_count -
 				dp->tot_dsc_blks_in_use +
-				dp_panel->tot_dsc_blks_in_use;
+				dp_panel->dsc_blks_in_use;
 
 	rc = msm_get_dsc_count(dp->priv, drm_mode->hdisplay,
 			&required_dsc_blks);

+ 2 - 2
msm/dp/dp_panel.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DP_PANEL_H_
@@ -135,7 +135,7 @@ struct dp_panel {
 	u32 channel_total_slots;
 	u32 pbn;
 
-	u32 tot_dsc_blks_in_use;
+	u32 dsc_blks_in_use;
 	/* DRM connector assosiated with this panel */
 	struct drm_connector *connector;