Преглед изворни кода

disp: msm: sde: handle all error cases during sui transitions

During secure-ui, the SMMU, MISR and VBIF states
are altered based on the enable/disable of secure-ui
which is followed by the scm_call. Failure in any of
the steps would lead the system to an unstable state.
Address all the failures and revert back all steps
to get the system back in original state to avoid
any issues.

Change-Id: I736c6cf018c5992ec33806c00e58bf56b818b8a7
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Signed-off-by: Samantha Tran <[email protected]>
Veera Sundaram Sankaran пре 5 година
родитељ
комит
e4a7d473f9
3 измењених фајлова са 91 додато и 44 уклоњено
  1. 1 0
      msm/sde/sde_crtc.c
  2. 88 44
      msm/sde/sde_kms.c
  3. 2 0
      msm/sde/sde_kms.h

+ 1 - 0
msm/sde/sde_crtc.c

@@ -1783,6 +1783,7 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
 
 	smmu_state = &sde_kms->smmu_state;
 	smmu_state->prev_state = smmu_state->state;
+	smmu_state->prev_secure_level = smmu_state->secure_level;
 
 	sde_crtc = to_sde_crtc(crtc);
 	secure_level = sde_crtc_get_secure_level(crtc, crtc->state);

+ 88 - 44
msm/sde/sde_kms.c

@@ -334,88 +334,118 @@ static int _sde_kms_scm_call(struct sde_kms *sde_kms, int vmid)
 
 static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms, u32 vmid)
 {
-	u32 ret = 0;
+	u32 ret;
 
 	if (atomic_inc_return(&sde_kms->detach_all_cb) > 1)
-		goto end;
+		return 0;
 
 	/* detach_all_contexts */
 	ret = sde_kms_mmu_detach(sde_kms, false);
 	if (ret) {
 		SDE_ERROR("failed to detach all cb ret:%d\n", ret);
-		goto end;
+		goto mmu_error;
 	}
 
 	ret = _sde_kms_scm_call(sde_kms, vmid);
-	if (ret)
-		goto end;
+	if (ret) {
+		SDE_ERROR("scm call failed for vmid:%d\n", vmid);
+		goto scm_error;
+	}
 
-end:
+	return 0;
+
+scm_error:
+	sde_kms_mmu_attach(sde_kms, false);
+mmu_error:
+	atomic_dec(&sde_kms->detach_all_cb);
 	return ret;
 }
 
-static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms, int vmid)
+static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms, u32 vmid,
+		u32 old_vmid)
 {
-	u32 ret = 0;
+	u32 ret;
 
 	if (atomic_dec_return(&sde_kms->detach_all_cb) != 0)
-		goto end;
+		return 0;
 
 	ret = _sde_kms_scm_call(sde_kms, vmid);
-	if (ret)
-		goto end;
+	if (ret) {
+		SDE_ERROR("scm call failed for vmid:%d\n", vmid);
+		goto scm_error;
+	}
 
 	/* attach_all_contexts */
 	ret = sde_kms_mmu_attach(sde_kms, false);
 	if (ret) {
 		SDE_ERROR("failed to attach all cb ret:%d\n", ret);
-		goto end;
+		goto mmu_error;
 	}
 
-end:
+	return 0;
+
+mmu_error:
+	_sde_kms_scm_call(sde_kms, old_vmid);
+scm_error:
+	atomic_inc(&sde_kms->detach_all_cb);
 	return ret;
 }
 
 static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms, int vmid)
 {
-	u32 ret = 0;
+	u32 ret;
 
 	if (atomic_inc_return(&sde_kms->detach_sec_cb) > 1)
-		goto end;
+		return 0;
 
 	/* detach secure_context */
 	ret = sde_kms_mmu_detach(sde_kms, true);
 	if (ret) {
 		SDE_ERROR("failed to detach sec cb ret:%d\n", ret);
-		goto end;
+		goto mmu_error;
 	}
 
 	ret = _sde_kms_scm_call(sde_kms, vmid);
-	if (ret)
-		goto end;
+	if (ret) {
+		SDE_ERROR("scm call failed for vmid:%d\n", vmid);
+		goto scm_error;
+	}
 
-end:
+	return 0;
+
+scm_error:
+	sde_kms_mmu_attach(sde_kms, true);
+mmu_error:
+	atomic_dec(&sde_kms->detach_sec_cb);
 	return ret;
 }
 
-static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms, int vmid)
+static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms, u32 vmid,
+		u32 old_vmid)
 {
-	u32 ret = 0;
+	u32 ret;
 
 	if (atomic_dec_return(&sde_kms->detach_sec_cb) != 0)
-		goto end;
+		return 0;
 
 	ret = _sde_kms_scm_call(sde_kms, vmid);
-	if (ret)
-		goto end;
+	if (ret) {
+		goto scm_error;
+		SDE_ERROR("scm call failed for vmid:%d\n", vmid);
+	}
 
 	ret = sde_kms_mmu_attach(sde_kms, true);
 	if (ret) {
 		SDE_ERROR("failed to attach sec cb ret:%d\n", ret);
-		goto end;
+		goto mmu_error;
 	}
 
-end:
+	return 0;
+
+mmu_error:
+	_sde_kms_scm_call(sde_kms, old_vmid);
+scm_error:
+	atomic_inc(&sde_kms->detach_sec_cb);
 	return ret;
 }
 
@@ -435,6 +465,7 @@ static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
 
 		ret = _sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, true);
 		if (ret) {
+			sde_crtc_misr_setup(crtc, false, 0);
 			pm_runtime_put_sync(sde_kms->dev->dev);
 			return ret;
 		}
@@ -473,8 +504,10 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
 	/* enable sui misr if requested, before the transition */
 	if (smmu_state->sui_misr_state == SUI_MISR_ENABLE_REQ) {
 		ret = _sde_kms_sui_misr_ctrl(sde_kms, crtc, true);
-		if (ret)
+		if (ret) {
+			smmu_state->sui_misr_state == NONE;
 			goto end;
+		}
 	}
 
 	mutex_lock(&sde_kms->secure_transition_lock);
@@ -486,7 +519,8 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
 		break;
 
 	case ATTACH_ALL_REQ:
-		ret = _sde_kms_attach_all_cb(sde_kms, VMID_CP_PIXEL);
+		ret = _sde_kms_attach_all_cb(sde_kms, VMID_CP_PIXEL,
+				VMID_CP_SEC_DISPLAY);
 		if (!ret) {
 			smmu_state->state = ATTACHED;
 			smmu_state->secure_level = SDE_DRM_SEC_NON_SEC;
@@ -503,7 +537,9 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
 		break;
 
 	case ATTACH_SEC_REQ:
-		ret = _sde_kms_attach_sec_cb(sde_kms, VMID_CP_PIXEL);
+		vmid = (smmu_state->secure_level == SDE_DRM_SEC_ONLY) ?
+				VMID_CP_SEC_DISPLAY : VMID_CP_CAMERA_PREVIEW;
+		ret = _sde_kms_attach_sec_cb(sde_kms, VMID_CP_PIXEL, vmid);
 		if (!ret) {
 			smmu_state->state = ATTACHED;
 			smmu_state->secure_level = SDE_DRM_SEC_NON_SEC;
@@ -527,29 +563,34 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
 	}
 
 end:
-	smmu_state->sui_misr_state = NONE;
-	smmu_state->transition_type = NONE;
 	smmu_state->transition_error = false;
 
-	/*
-	 * If switch failed, toggling secure_level is enough since
-	 * there are only two secure levels - secure/non-secure
-	 */
 	if (ret) {
 		smmu_state->transition_error = true;
+		SDE_ERROR(
+		  "crtc%d: req_state %d, new_state %d, sec_lvl %d, ret %d\n",
+			DRMID(crtc), old_smmu_state, smmu_state->state,
+			smmu_state->secure_level, ret);
+
 		smmu_state->state = smmu_state->prev_state;
-		smmu_state->secure_level = !smmu_state->secure_level;
+		smmu_state->secure_level = smmu_state->prev_secure_level;
+
+		if (smmu_state->sui_misr_state == SUI_MISR_ENABLE_REQ)
+			_sde_kms_sui_misr_ctrl(sde_kms, crtc, false);
 	}
 
-	SDE_DEBUG(
-		"crtc %d: old_state %d, req_state %d, new_state %d, sec_lvl %d, ret %d\n",
-			DRMID(crtc), smmu_state->prev_state, old_smmu_state,
-			smmu_state->state, smmu_state->secure_level, ret);
-	SDE_EVT32(DRMID(crtc), smmu_state->prev_state,
-			smmu_state->state, smmu_state->transition_type,
-			smmu_state->transition_error, smmu_state->secure_level,
+	SDE_DEBUG("crtc %d: req_state %d, new_state %d, sec_lvl %d, ret %d\n",
+			DRMID(crtc), old_smmu_state, smmu_state->state,
+			smmu_state->secure_level, ret);
+	SDE_EVT32(DRMID(crtc), smmu_state->state, smmu_state->prev_state,
+			smmu_state->transition_type,
+			smmu_state->transition_error,
+			smmu_state->secure_level, smmu_state->prev_secure_level,
 			smmu_state->sui_misr_state, ret, SDE_EVTLOG_FUNC_EXIT);
 
+	smmu_state->sui_misr_state = NONE;
+	smmu_state->transition_type = NONE;
+
 	return ret;
 }
 
@@ -565,6 +606,7 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms,
 	struct drm_device *dev = sde_kms->dev;
 	int i, ops = 0, ret = 0;
 	bool old_valid_fb = false;
+	struct sde_kms_smmu_state_data *smmu_state = &sde_kms->smmu_state;
 
 	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
 		if (!crtc->state || !crtc->state->active)
@@ -601,8 +643,10 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms,
 			return ops;
 		}
 
-		if (!ops)
+		if (!ops) {
+			smmu_state->transition_error = false;
 			goto no_ops;
+		}
 
 		SDE_DEBUG("%d:secure operations(%x) started on state:%pK\n",
 				crtc->base.id, ops, crtc->state);

+ 2 - 0
msm/sde/sde_kms.h

@@ -189,6 +189,7 @@ enum frame_trigger_mode_type {
  * @state: current state of smmu context banks
  * @prev_state: previous state of smmu context banks
  * @secure_level: secure level cached from crtc
+ * @prev_secure_level: previous secure level
  * @transition_type: transition request type
  * @transition_error: whether there is error while transitioning the state
  */
@@ -196,6 +197,7 @@ struct sde_kms_smmu_state_data {
 	uint32_t state;
 	uint32_t prev_state;
 	uint32_t secure_level;
+	uint32_t prev_secure_level;
 	uint32_t transition_type;
 	uint32_t transition_error;
 	uint32_t sui_misr_state;