瀏覽代碼

disp: msm: sde: fix compression info usage in resource alloc

Currently, compression info passed to resource manager is not
valid in atomic check phase. Also in current design allocation
of msm mode info object is from stack which is huge and causing
stack overflow in continuous splash use case. This change fixes
these issues by moving mode info object to heap allocation.

Change-Id: Ifaf39b3ae59c942da5c00b82c73cb97cdaf500d3
Signed-off-by: Prabhanjan Kandula <[email protected]>
Prabhanjan Kandula 5 年之前
父節點
當前提交
62cb53cc59
共有 3 個文件被更改,包括 84 次插入24 次删除
  1. 46 0
      msm/sde/sde_connector.h
  2. 15 11
      msm/sde/sde_encoder.c
  3. 23 13
      msm/sde/sde_rm.c

+ 46 - 0
msm/sde/sde_connector.h

@@ -926,6 +926,52 @@ int sde_connector_helper_reset_custom_properties(
 int sde_connector_state_get_mode_info(struct drm_connector_state *conn_state,
 	struct msm_mode_info *mode_info);
 
+/**
+ * sde_connector_state_get_topology - get topology from given connector state
+ * conn_state: Pointer to the DRM connector state object
+ * topology: Pointer to store topology info of the display
+ */
+static inline int sde_connector_state_get_topology(
+		struct drm_connector_state *conn_state,
+		struct msm_display_topology *topology)
+{
+	struct sde_connector_state *sde_conn_state = NULL;
+
+	if (!conn_state || !topology) {
+		SDE_ERROR("invalid arguments conn_state %d, topology %d\n",
+				!conn_state, !topology);
+		return -EINVAL;
+	}
+
+	sde_conn_state = to_sde_connector_state(conn_state);
+	memcpy(topology, &sde_conn_state->mode_info.topology,
+		sizeof(struct msm_display_topology));
+	return 0;
+}
+
+/**
+ * sde_connector_state_get_compression_info- get compression info of display
+ * from given connector state
+ * conn_state: Pointer to the DRM connector state object
+ * comp_info: Pointer to the compression info structure
+ */
+static inline int sde_connector_state_get_compression_info(
+		struct drm_connector_state *conn_state,
+		struct msm_compression_info *comp_info)
+{
+	struct sde_connector_state *sde_conn_state = NULL;
+
+	if (!conn_state || !comp_info) {
+		SDE_ERROR("invalid arguments\n");
+		return -EINVAL;
+	}
+
+	sde_conn_state = to_sde_connector_state(conn_state);
+	memcpy(comp_info, &sde_conn_state->mode_info.comp_info,
+		sizeof(struct msm_compression_info));
+	return 0;
+}
+
 /**
 * sde_connector_get_mode_info - retrieve mode info for given mode
 * @connector: Pointer to drm connector structure

+ 15 - 11
msm/sde/sde_encoder.c

@@ -510,22 +510,22 @@ void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
 		struct drm_connector_state *conn_state)
 {
 	struct sde_encoder_virt *sde_enc = NULL;
-	struct msm_mode_info mode_info;
-	int i = 0;
+	int ret, i = 0;
 
-	if (!hw_res || !drm_enc || !conn_state) {
-		SDE_ERROR("invalid argument(s), drm_enc %d, res %d, state %d\n",
-				!drm_enc, !hw_res, !conn_state);
+	if (!hw_res || !drm_enc || !conn_state || !hw_res->comp_info) {
+		SDE_ERROR("rc %d, drm_enc %d, res %d, state %d, comp-info %d\n",
+				-EINVAL, !drm_enc, !hw_res, !conn_state,
+				hw_res ? !hw_res->comp_info : 0);
 		return;
 	}
 
 	sde_enc = to_sde_encoder_virt(drm_enc);
 	SDE_DEBUG_ENC(sde_enc, "\n");
 
-	/* Query resources used by phys encs, expected to be without overlap */
-	memset(hw_res, 0, sizeof(*hw_res));
 	hw_res->display_num_of_h_tiles = sde_enc->display_num_of_h_tiles;
+	hw_res->display_type = sde_enc->disp_info.display_type;
 
+	/* Query resources used by phys encs, expected to be without overlap */
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
@@ -538,10 +538,14 @@ void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
 	 * called from atomic_check phase. Use the below API to get mode
 	 * information of the temporary conn_state passed
 	 */
-	sde_connector_state_get_mode_info(conn_state, &mode_info);
-	hw_res->topology = mode_info.topology;
-	hw_res->comp_info = &sde_enc->mode_info.comp_info;
-	hw_res->display_type = sde_enc->disp_info.display_type;
+	ret = sde_connector_state_get_topology(conn_state, &hw_res->topology);
+	if (ret)
+		SDE_ERROR("failed to get topology ret %d\n", ret);
+
+	ret = sde_connector_state_get_compression_info(conn_state,
+			hw_res->comp_info);
+	if (ret)
+		SDE_ERROR("failed to get compression info ret %d\n", ret);
 }
 
 void sde_encoder_destroy(struct drm_encoder *drm_enc)

+ 23 - 13
msm/sde/sde_rm.c

@@ -1273,21 +1273,28 @@ static bool _sde_rm_check_vdc(struct sde_rm *rm,
 static int _sde_rm_reserve_dsc(
 		struct sde_rm *rm,
 		struct sde_rm_rsvp *rsvp,
-		struct msm_display_dsc_info *dsc_info,
-		const struct sde_rm_topology_def *top,
+		struct sde_rm_requirements *reqs,
 		u8 *_dsc_ids)
 {
 	struct sde_rm_hw_iter iter_i, iter_j;
 	struct sde_rm_hw_blk *dsc[MAX_BLOCKS];
 	u32 reserve_mask = 0;
 	int alloc_count = 0;
-	int num_dsc_enc = top->num_comp_enc;
+	int num_dsc_enc;
+	struct msm_display_dsc_info *dsc_info;
 	int i;
 
-	if ((!top->num_comp_enc) || !dsc_info) {
+	if (reqs->hw_res.comp_info->comp_type != MSM_DISPLAY_COMPRESSION_DSC) {
+		SDE_DEBUG("compression blk dsc not required\n");
+		return 0;
+	}
+
+	num_dsc_enc = reqs->topology->num_comp_enc;
+	dsc_info = &reqs->hw_res.comp_info->dsc_info;
+
+	if ((!num_dsc_enc) || !dsc_info) {
 		SDE_DEBUG("invalid topoplogy params: %d, %d\n",
-				top->num_comp_enc,
-				!(dsc_info == NULL));
+				num_dsc_enc, !(dsc_info == NULL));
 		return 0;
 	}
 
@@ -1309,7 +1316,7 @@ static int _sde_rm_reserve_dsc(
 			continue;
 
 		/* if this hw block does not support required feature */
-		if ((dsc_info->config.native_422 ||
+		if (!_dsc_ids && (dsc_info->config.native_422 ||
 			dsc_info->config.native_420) && !has_422_420_support)
 			continue;
 
@@ -1680,9 +1687,7 @@ static int _sde_rm_make_dsc_rsvp(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
 				i, splash_display->dsc_ids[i]);
 	}
 
-	return  _sde_rm_reserve_dsc(rm, rsvp,
-			&reqs->hw_res.comp_info->dsc_info,
-			reqs->topology, hw_ids);
+	return  _sde_rm_reserve_dsc(rm, rsvp, reqs, hw_ids);
 
 }
 
@@ -1907,8 +1912,6 @@ static int _sde_rm_populate_requirements(
 	const struct drm_display_mode *mode = &crtc_state->mode;
 	int i;
 
-	memset(reqs, 0, sizeof(*reqs));
-
 	reqs->top_ctrl = sde_connector_get_property(conn_state,
 			CONNECTOR_PROP_TOPOLOGY_CONTROL);
 	sde_encoder_get_hw_resources(enc, &reqs->hw_res, conn_state);
@@ -2207,9 +2210,10 @@ int sde_rm_reserve(
 		bool test_only)
 {
 	struct sde_rm_rsvp *rsvp_cur, *rsvp_nxt;
-	struct sde_rm_requirements reqs;
+	struct sde_rm_requirements reqs = {0,};
 	struct msm_drm_private *priv;
 	struct sde_kms *sde_kms;
+	struct msm_compression_info *comp_info;
 	int ret;
 
 	if (!rm || !enc || !crtc_state || !conn_state) {
@@ -2233,6 +2237,10 @@ int sde_rm_reserve(
 			!drm_atomic_crtc_needs_modeset(crtc_state))
 		return 0;
 
+	comp_info = kzalloc(sizeof(*comp_info), GFP_KERNEL);
+	if (!comp_info)
+		return -ENOMEM;
+
 	SDE_DEBUG("reserving hw for conn %d enc %d crtc %d test_only %d\n",
 			conn_state->connector->base.id, enc->base.id,
 			crtc_state->crtc->base.id, test_only);
@@ -2265,6 +2273,7 @@ int sde_rm_reserve(
 	if (!test_only && rsvp_nxt)
 		goto commit_rsvp;
 
+	reqs.hw_res.comp_info = comp_info;
 	ret = _sde_rm_populate_requirements(rm, enc, crtc_state,
 			conn_state, &reqs);
 	if (ret) {
@@ -2332,6 +2341,7 @@ commit_rsvp:
 	ret = _sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
 
 end:
+	kfree(comp_info);
 	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_FINAL);
 	mutex_unlock(&rm->rm_lock);