浏览代码

Merge "disp: msm: sde: limit encoders attached to crtc during trusted-ui"

qctecmdr 4 年之前
父节点
当前提交
68399fac7e
共有 3 个文件被更改,包括 103 次插入44 次删除
  1. 100 37
      msm/sde/sde_kms.c
  2. 2 0
      msm/sde/sde_vm.h
  3. 1 7
      msm/sde/sde_vm_common.c

+ 100 - 37
msm/sde/sde_kms.c

@@ -1027,8 +1027,13 @@ int sde_kms_vm_primary_prepare_commit(struct sde_kms *sde_kms,
 		sde_kms->hw_intr->ops.clear_all_irqs(sde_kms->hw_intr);
 
 	/* enable the display path IRQ's */
-	drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
+	drm_for_each_encoder_mask(encoder, crtc->dev,
+					crtc->state->encoder_mask) {
+		if (sde_encoder_in_clone_mode(encoder))
+			continue;
+
 		sde_encoder_irq_control(encoder, true);
+	}
 
 	/* Schedule ESD work */
 	list_for_each_entry(connector, &ddev->mode_config.connector_list, head)
@@ -1317,8 +1322,13 @@ int sde_kms_vm_trusted_post_commit(struct sde_kms *sde_kms,
 	/* if vm_req is enabled, once CRTC on the commit is guaranteed */
 	sde_kms_wait_for_frame_transfer_complete(&sde_kms->base, crtc);
 
-	drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
+	drm_for_each_encoder_mask(encoder, crtc->dev,
+					crtc->state->encoder_mask) {
+		if (sde_encoder_in_clone_mode(encoder))
+			continue;
+
 		sde_encoder_irq_control(encoder, false);
+	}
 
 	list_for_each_entry(plane, &ddev->mode_config.plane_list, head)
 		sde_plane_set_sid(plane, 0);
@@ -1359,8 +1369,13 @@ int sde_kms_vm_pre_release(struct sde_kms *sde_kms,
 	}
 
 	/* disable SDE irq's */
-	drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
+	drm_for_each_encoder_mask(encoder, crtc->dev,
+					crtc->state->encoder_mask) {
+		if (sde_encoder_in_clone_mode(encoder))
+			continue;
+
 		sde_encoder_irq_control(encoder, false);
+	}
 
 	/* disable IRQ line */
 	sde_irq_update(&sde_kms->base, false);
@@ -2483,13 +2498,16 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
 	struct sde_kms *sde_kms;
 	struct drm_device *dev;
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *new_cstate, *old_cstate;
+	struct drm_encoder *encoder;
+	struct drm_crtc_state *new_cstate, *old_cstate, *active_cstate;
 	uint32_t i, commit_crtc_cnt = 0, global_crtc_cnt = 0;
+	uint32_t crtc_encoder_cnt = 0;
 	struct drm_crtc *active_crtc = NULL, *global_active_crtc = NULL;
 	enum sde_crtc_vm_req old_vm_req = VM_REQ_NONE, new_vm_req = VM_REQ_NONE;
 	struct sde_vm_ops *vm_ops;
 	bool vm_req_active = false;
 	enum sde_crtc_idle_pc_state idle_pc_state;
+	struct sde_mdss_cfg *catalog;
 	int rc = 0;
 
 	if (!kms || !state)
@@ -2497,11 +2515,18 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
 
 	sde_kms = to_sde_kms(kms);
 	dev = sde_kms->dev;
+	catalog = sde_kms->catalog;
 
 	vm_ops = sde_vm_get_ops(sde_kms);
 	if (!vm_ops)
 		return 0;
 
+	if (!vm_ops->vm_request_valid || !vm_ops->vm_owns_hw ||
+				!vm_ops->vm_acquire)
+		return -EINVAL;
+
+	sde_vm_lock(sde_kms);
+
 	for_each_oldnew_crtc_in_state(state, crtc, old_cstate, new_cstate, i) {
 		struct sde_crtc_state *old_state = NULL, *new_state = NULL;
 
@@ -2516,20 +2541,40 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
 		old_vm_req = sde_crtc_get_property(old_state,
 				CRTC_PROP_VM_REQ_STATE);
 
-		/**
+		/*
 		 * No active request if the transition is from
 		 * VM_REQ_NONE to VM_REQ_NONE
 		 */
-		if (new_vm_req || old_vm_req)
-			vm_req_active = true;
+		if (old_vm_req || new_vm_req) {
+			rc = vm_ops->vm_request_valid(sde_kms,
+					old_vm_req, new_vm_req);
+			if (rc) {
+				SDE_ERROR(
+				"VM transition check failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
+					old_vm_req, new_vm_req,
+					vm_ops->vm_owns_hw(sde_kms), rc);
+				goto end;
+			} else if (old_vm_req == VM_REQ_ACQUIRE &&
+					new_vm_req == VM_REQ_NONE) {
+				SDE_DEBUG(
+				"VM transition valid; ignore further checks\n");
+			} else {
+				vm_req_active = true;
+			}
+		}
 
 		idle_pc_state = sde_crtc_get_property(new_state,
 						CRTC_PROP_IDLE_PC_STATE);
 
 		active_crtc = crtc;
+		active_cstate = new_cstate;
 		commit_crtc_cnt++;
 	}
 
+	/* return early if no active vm request */
+	if (!vm_req_active)
+		goto end;
+
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (!crtc->state->active)
 			continue;
@@ -2538,37 +2583,52 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
 		global_active_crtc = crtc;
 	}
 
-	/* Check for single crtc commits only on valid VM requests */
-	if (vm_req_active && active_crtc && global_active_crtc &&
-		(commit_crtc_cnt > sde_kms->catalog->max_trusted_vm_displays ||
-		 global_crtc_cnt > sde_kms->catalog->max_trusted_vm_displays ||
-		 active_crtc != global_active_crtc)) {
-		SDE_ERROR(
-			   "failed to switch VM due to CRTC concurrencies: MAX_CNT: %d active_cnt: %d global_cnt: %d active_crtc: %d global_crtc: %d\n",
-			   sde_kms->catalog->max_trusted_vm_displays,
-			   commit_crtc_cnt, global_crtc_cnt, active_crtc,
-			   global_active_crtc);
-		return -E2BIG;
+	if (active_crtc) {
+		drm_for_each_encoder_mask(encoder, active_crtc->dev,
+				active_cstate->encoder_mask)
+			crtc_encoder_cnt++;
 	}
 
-	if (!vm_req_active)
-		return 0;
+	/* Check for single crtc commits only on valid VM requests */
+	if (active_crtc && global_active_crtc &&
+		(commit_crtc_cnt > catalog->max_trusted_vm_displays ||
+			global_crtc_cnt > catalog->max_trusted_vm_displays ||
+			active_crtc != global_active_crtc)) {
+		SDE_ERROR(
+		"VM switch failed; MAX:%d a_cnt:%d g_cnt:%d a_crtc:%d g_crtc:%d\n",
+			   catalog->max_trusted_vm_displays,
+			   commit_crtc_cnt, global_crtc_cnt, DRMID(active_crtc),
+			   DRMID(global_active_crtc));
+		rc =  -E2BIG;
+		goto end;
 
-	/* disable idle-pc before releasing the HW */
-	if ((new_vm_req == VM_REQ_RELEASE) &&
-			(idle_pc_state == IDLE_PC_ENABLE)) {
-		SDE_ERROR("failed to switch VM since idle-pc is enabled\n");
-		return -EINVAL;
+	} else if ((new_vm_req == VM_REQ_RELEASE) &&
+	    ((idle_pc_state == IDLE_PC_ENABLE) ||
+		(crtc_encoder_cnt > TRUSTED_VM_MAX_ENCODER_PER_CRTC))) {
+		/*
+		 * disable idle-pc before releasing the HW
+		 * allow only specified number of encoders on a given crtc
+		 */
+		SDE_ERROR(
+			"VM switch failed; idle-pc:%d max:%d encoder_cnt:%d\n",
+				idle_pc_state, TRUSTED_VM_MAX_ENCODER_PER_CRTC,
+				crtc_encoder_cnt);
+		rc = -EINVAL;
+		goto end;
 	}
 
-	sde_vm_lock(sde_kms);
+	if ((new_vm_req == VM_REQ_ACQUIRE) && !vm_ops->vm_owns_hw(sde_kms)) {
+		rc = vm_ops->vm_acquire(sde_kms);
+		if (rc) {
+			SDE_ERROR(
+			"VM acquire failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
+				old_vm_req, new_vm_req,
+				vm_ops->vm_owns_hw(sde_kms), rc);
+			goto end;
+		}
+	}
 
-	if (vm_ops->vm_request_valid)
-		rc = vm_ops->vm_request_valid(sde_kms, old_vm_req, new_vm_req);
-	if (rc)
-		SDE_ERROR(
-		"failed to complete vm transition request. old_state = %d, new_state = %d, hw_ownership: %d\n",
-		old_vm_req, new_vm_req, vm_ops->vm_owns_hw(sde_kms));
+end:
 	sde_vm_unlock(sde_kms);
 
 	return rc;
@@ -2661,18 +2721,21 @@ static void sde_kms_vm_res_release(struct msm_kms *kms,
 		struct drm_atomic_state *state)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
+	struct drm_crtc_state *new_cstate, *old_cstate;
 	struct sde_vm_ops *vm_ops;
 	enum sde_crtc_vm_req vm_req;
 	struct sde_kms *sde_kms = to_sde_kms(kms);
 	int i;
 
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		struct sde_crtc_state *cstate;
+	for_each_oldnew_crtc_in_state(state, crtc, old_cstate, new_cstate, i) {
+		struct sde_crtc_state *new_state;
 
-		cstate = to_sde_crtc_state(state->crtcs[0].new_state);
+		if (!new_cstate->active && !old_cstate->active)
+			continue;
 
-		vm_req = sde_crtc_get_property(cstate, CRTC_PROP_VM_REQ_STATE);
+		new_state = to_sde_crtc_state(new_cstate);
+		vm_req = sde_crtc_get_property(new_state,
+					CRTC_PROP_VM_REQ_STATE);
 		if (vm_req != VM_REQ_ACQUIRE)
 			return;
 	}

+ 2 - 0
msm/sde/sde_vm.h

@@ -8,6 +8,8 @@
 
 #include "msm_drv.h"
 
+#define TRUSTED_VM_MAX_ENCODER_PER_CRTC	1
+
 struct sde_kms;
 
 /**

+ 1 - 7
msm/sde/sde_vm_common.c

@@ -306,14 +306,8 @@ int sde_vm_request_valid(struct sde_kms *sde_kms,
 			rc = -EINVAL;
 		break;
 	case VM_REQ_ACQUIRE:
-		if (old_state != VM_REQ_RELEASE) {
+		if (old_state != VM_REQ_RELEASE)
 			rc = -EINVAL;
-		} else if (!vm_ops->vm_owns_hw(sde_kms)) {
-			if (vm_ops->vm_acquire)
-				rc = vm_ops->vm_acquire(sde_kms);
-			else
-				rc = -EINVAL;
-		}
 		break;
 	default:
 		SDE_ERROR("invalid vm request\n");