Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit addca914 authored by Veera Sundaram Sankaran's avatar Veera Sundaram Sankaran
Browse files

drm/msm/sde: avoid detaching non-sec context bank during secure-ui



After the hardware enhancement for secure-display which allows
only secure data to be transferred during secure-display, the
non-secure context banks can co-exist during the session and
may be used for non-data related purpose. With this in effect,
there is no necessity for unmapping the non-sec buffers before
entering the secure session. Support backward compatibility, so
targets without this feature can still work the old way.

Change-Id: I54e0f67320e7680525f429934c30ca4179ac1000
Signed-off-by: default avatarVeera Sundaram Sankaran <veeras@codeaurora.org>
parent 8408f038
Loading
Loading
Loading
Loading
+83 −57
Original line number Diff line number Diff line
@@ -1805,15 +1805,9 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
	secure_level = sde_crtc_get_secure_level(crtc, crtc->state);
	catalog = sde_kms->catalog;

	SDE_DEBUG("crtc%d, secure_level%d old_valid_fb%d\n",
			crtc->base.id, secure_level, old_valid_fb);

	SDE_EVT32_VERBOSE(DRMID(crtc), secure_level, smmu_state->state,
			old_valid_fb, SDE_EVTLOG_FUNC_ENTRY);
	/**
	 * SMMU operations need to be delayed in case of
	 * video mode panels when switching back to non_secure
	 * mode
	/*
	 * SMMU operations need to be delayed in case of video mode panels
	 * when switching back to non_secure mode
	 */
	drm_for_each_encoder(encoder, crtc->dev) {
		if (encoder->crtc != crtc)
@@ -1823,6 +1817,11 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
						MSM_DISPLAY_CAP_VID_MODE);
	}

	SDE_DEBUG("crtc%d: secure_level %d old_valid_fb %d post_commit %d\n",
			DRMID(crtc), secure_level, old_valid_fb, post_commit);
	SDE_EVT32_VERBOSE(DRMID(crtc), secure_level, smmu_state->state,
			old_valid_fb, post_commit, SDE_EVTLOG_FUNC_ENTRY);

	drm_atomic_crtc_for_each_plane(plane, crtc) {
		if (!plane->state)
			continue;
@@ -1831,15 +1830,12 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
				to_sde_plane_state(plane->state),
				PLANE_PROP_FB_TRANSLATION_MODE);
		if (translation_mode > SDE_DRM_FB_SEC_DIR_TRANS) {
			SDE_ERROR("crtc%d, invalid translation_mode%d\n",
					crtc->base.id, translation_mode);
			SDE_ERROR("crtc%d: invalid translation_mode %d\n",
					DRMID(crtc), translation_mode);
			return -EINVAL;
		}

		/**
		 * we can break if we find sec_fir or non_sec_dir
		 * plane
		 */
		/* we can break if we find sec_dir plane */
		if (translation_mode == SDE_DRM_FB_SEC_DIR_TRANS)
			break;
	}
@@ -1849,21 +1845,23 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
	switch (translation_mode) {
	case SDE_DRM_FB_SEC_DIR_TRANS:
		/* secure display usecase */
		if ((smmu_state->state == ATTACHED) &&
				(secure_level == SDE_DRM_SEC_ONLY)) {
			smmu_state->state = DETACH_ALL_REQ;
		if ((smmu_state->state == ATTACHED)
				&& (secure_level == SDE_DRM_SEC_ONLY)) {
			smmu_state->state = catalog->sui_ns_allowed ?
						DETACH_SEC_REQ : DETACH_ALL_REQ;
			smmu_state->secure_level = secure_level;
			smmu_state->transition_type = PRE_COMMIT;
			ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE;
			if (old_valid_fb) {
			if (old_valid_fb)
				ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE  |
						SDE_KMS_OPS_CLEANUP_PLANE_FB);
			}
			if (catalog->sui_misr_supported)
				smmu_state->sui_misr_state =
						SUI_MISR_ENABLE_REQ;
		/* secure camera usecase */
		} else if (smmu_state->state == ATTACHED) {
			smmu_state->state = DETACH_SEC_REQ;
			smmu_state->secure_level = secure_level;
			smmu_state->transition_type = PRE_COMMIT;
			ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE;
		}
@@ -1871,17 +1869,14 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,

	case SDE_DRM_FB_SEC:
	case SDE_DRM_FB_NON_SEC:
		if ((smmu_state->state == DETACHED_SEC) ||
			(smmu_state->state == DETACH_SEC_REQ)) {
			smmu_state->state = ATTACH_SEC_REQ;
			smmu_state->transition_type = post_commit ?
				POST_COMMIT : PRE_COMMIT;
			ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE;
			if (old_valid_fb)
				ops |= SDE_KMS_OPS_WAIT_FOR_TX_DONE;
		} else if ((smmu_state->state == DETACHED) ||
				(smmu_state->state == DETACH_ALL_REQ)) {
			smmu_state->state = ATTACH_ALL_REQ;
		if (((smmu_state->state == DETACHED)
				|| (smmu_state->state == DETACH_ALL_REQ))
			|| ((smmu_state->secure_level == SDE_DRM_SEC_ONLY)
				&& ((smmu_state->state == DETACHED_SEC)
				  || (smmu_state->state == DETACH_SEC_REQ)))) {
			smmu_state->state = catalog->sui_ns_allowed ?
						ATTACH_SEC_REQ : ATTACH_ALL_REQ;
			smmu_state->secure_level = secure_level;
			smmu_state->transition_type = post_commit ?
						POST_COMMIT : PRE_COMMIT;
			ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE;
@@ -1891,21 +1886,35 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc,
			if (catalog->sui_misr_supported)
				smmu_state->sui_misr_state =
						SUI_MISR_DISABLE_REQ;
		} else if ((smmu_state->state == DETACHED_SEC)
				|| (smmu_state->state == DETACH_SEC_REQ)) {
			smmu_state->state = ATTACH_SEC_REQ;
			smmu_state->secure_level = secure_level;
			smmu_state->transition_type = post_commit ?
						POST_COMMIT : PRE_COMMIT;
			ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE;
			if (old_valid_fb)
				ops |= SDE_KMS_OPS_WAIT_FOR_TX_DONE;
		}
		break;

	default:
		SDE_ERROR("invalid plane fb_mode:%d\n", translation_mode);
		SDE_ERROR("crtc%d: invalid plane fb_mode %d\n",
				DRMID(crtc), translation_mode);
		ops = -EINVAL;
	}

	SDE_DEBUG("SMMU State:%d, type:%d ops:%x\n", smmu_state->state,
			smmu_state->transition_type, ops);
	/* log only during actual transition times */
	if (ops)
	if (ops) {
		SDE_DEBUG("crtc%d: state %d, secure_level %d, type %d ops %x\n",
			DRMID(crtc), smmu_state->state,
			smmu_state->secure_level,
			smmu_state->transition_type, ops);
		SDE_EVT32(DRMID(crtc), secure_level, translation_mode,
				smmu_state->state, smmu_state->transition_type,
				ops, old_valid_fb, SDE_EVTLOG_FUNC_EXIT);
				smmu_state->secure_level, old_valid_fb,
				post_commit, ops, SDE_EVTLOG_FUNC_EXIT);
	}

	mutex_unlock(&sde_kms->secure_transition_lock);

@@ -3106,7 +3115,7 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
	 * apply color processing properties only if
	 * smmu state is attached,
	 */
	if (!sde_kms_is_secure_session_inprogress(sde_kms))
	if (sde_kms_is_cp_operation_allowed(sde_kms))
		sde_cp_crtc_apply_properties(crtc);

	/*
@@ -4455,7 +4464,7 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
		if (fb_ns || fb_sec) {
			SDE_ERROR(
			 "crtc%d: invalid fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n",
				crtc->base.id, fb_sec, fb_ns, fb_sec_dir);
				DRMID(crtc), fb_sec, fb_ns, fb_sec_dir);
			return -EINVAL;
		}

@@ -4467,25 +4476,37 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
			if (!pstates[i].drm_pstate
					|| !pstates[i].drm_pstate->plane) {
				SDE_ERROR("crtc%d: invalid pstate at i:%d\n",
						crtc->base.id, i);
						DRMID(crtc), i);
				return -EINVAL;
			}
			plane = pstates[i].drm_pstate->plane;

			if (!sde_plane_is_sec_ui_allowed(plane)) {
				SDE_ERROR("crtc%d: sec-ui not allowed in p%d\n",
						crtc->base.id, plane->base.id);
						DRMID(crtc), plane->base.id);
				return -EINVAL;
			}

			if (pstates[i].stage != pstates[i-1].stage) {
			} else if (pstates[i].stage != pstates[i-1].stage) {
				SDE_ERROR(
				  "crtc%d: invalid blend stages %d:%d, %d:%d\n",
				  crtc->base.id, i, pstates[i].stage,
				  DRMID(crtc), i, pstates[i].stage,
				  i-1, pstates[i-1].stage);
				return -EINVAL;
			}
		}

		/* check if all the dim_layers are in the same stage */
		for (i = 1; i < cstate->num_dim_layers; i++) {
			if (cstate->dim_layer[i].stage !=
					cstate->dim_layer[i-1].stage) {
				SDE_ERROR(
				"crtc%d: invalid dimlayer stage %d:%d, %d:%d\n",
					DRMID(crtc),
					i, cstate->dim_layer[i].stage,
					i-1, cstate->dim_layer[i-1].stage);
				return -EINVAL;
			}
		}
	}

	/*
@@ -4499,7 +4520,7 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,

		if (encoder_cnt > MAX_ALLOWED_ENCODER_CNT_PER_SECURE_CRTC) {
			SDE_ERROR("crtc%d, invalid virtual encoder crtc%d\n",
				crtc->base.id, encoder_cnt);
				DRMID(crtc), encoder_cnt);
			return -EINVAL;

		}
@@ -4524,18 +4545,23 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
		((fb_sec_dir && ((smmu_state->state == ATTACHED) &&
			(secure == SDE_DRM_SEC_ONLY))) ||
		    (fb_ns && ((smmu_state->state == DETACHED) ||
				(smmu_state->state == DETACH_ALL_REQ))))) {

		SDE_EVT32(DRMID(&sde_crtc->base), fb_ns, fb_sec_dir,
		  smmu_state->state, crtc->state->plane_mask,
			crtc->state->plane_mask);
		SDE_DEBUG("crtc %d, Invalid secure transition %x\n",
				crtc->base.id, smmu_state->state);
			(smmu_state->state == DETACH_ALL_REQ))) ||
		    (fb_ns && ((smmu_state->state == DETACHED_SEC) ||
			(smmu_state->state == DETACH_SEC_REQ)) &&
			(smmu_state->secure_level == SDE_DRM_SEC_ONLY)))) {

		SDE_EVT32(DRMID(crtc), fb_ns, fb_sec_dir,
			smmu_state->state, smmu_state->secure_level,
			secure, crtc->state->plane_mask, state->plane_mask);
		SDE_ERROR(
		 "crtc%d Invalid transition;sec%d state%d slvl%d ns%d sdir%d\n",
			DRMID(crtc), secure, smmu_state->state,
			smmu_state->secure_level, fb_ns, fb_sec_dir);
		return -EINVAL;

	}

	SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id);
	SDE_DEBUG("crtc:%d Secure validation successful\n", DRMID(crtc));

	return 0;
}
+3 −0
Original line number Diff line number Diff line
@@ -1043,6 +1043,8 @@ struct sde_perf_cfg {
 * @sec_sid_mask_count  number of SID masks
 * @sec_sid_mask        SID masks used during the scm_call for transition
 *                         between secure/non-secure sessions
 * @sui_ns_allowed      flag to indicate non-secure context banks are allowed
 *                         during secure-ui session
 */
struct sde_mdss_cfg {
	u32 hwversion;
@@ -1083,6 +1085,7 @@ struct sde_mdss_cfg {

	u32 sec_sid_mask_count;
	u32 sec_sid_mask[MAX_BLOCKS];
	u32 sui_ns_allowed;

	bool has_hdr;
	u32 mdss_count;
+21 −21
Original line number Diff line number Diff line
@@ -491,7 +491,7 @@ static int _sde_kms_scm_call(struct sde_kms *sde_kms, int vmid)
	return ret;
}

static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms)
static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms, u32 vmid)
{
	u32 ret = 0;

@@ -505,7 +505,7 @@ static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms)
		goto end;
	}

	ret = _sde_kms_scm_call(sde_kms, VMID_CP_SEC_DISPLAY);
	ret = _sde_kms_scm_call(sde_kms, vmid);
	if (ret)
		goto end;

@@ -513,14 +513,14 @@ static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms)
	return ret;
}

static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms)
static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms, int vmid)
{
	u32 ret = 0;

	if (atomic_dec_return(&sde_kms->detach_all_cb) != 0)
		goto end;

	ret = _sde_kms_scm_call(sde_kms, VMID_CP_PIXEL);
	ret = _sde_kms_scm_call(sde_kms, vmid);
	if (ret)
		goto end;

@@ -535,7 +535,7 @@ static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms)
	return ret;
}

static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms)
static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms, int vmid)
{
	u32 ret = 0;

@@ -549,7 +549,7 @@ static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms)
		goto end;
	}

	ret = _sde_kms_scm_call(sde_kms, VMID_CP_CAMERA_PREVIEW);
	ret = _sde_kms_scm_call(sde_kms, vmid);
	if (ret)
		goto end;

@@ -557,14 +557,14 @@ static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms)
	return ret;
}

static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms)
static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms, int vmid)
{
	u32 ret = 0;

	if (atomic_dec_return(&sde_kms->detach_sec_cb) != 0)
		goto end;

	ret = _sde_kms_scm_call(sde_kms, VMID_CP_PIXEL);
	ret = _sde_kms_scm_call(sde_kms, vmid);
	if (ret)
		goto end;

@@ -618,6 +618,7 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
	struct sde_kms_smmu_state_data *smmu_state = &sde_kms->smmu_state;
	int old_smmu_state = smmu_state->state;
	int ret = 0;
	u32 vmid;

	if (!sde_kms || !crtc) {
		SDE_ERROR("invalid argument(s)\n");
@@ -626,7 +627,7 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,

	SDE_EVT32(DRMID(crtc), smmu_state->state, smmu_state->transition_type,
			post_commit, smmu_state->sui_misr_state,
			SDE_EVTLOG_FUNC_ENTRY);
			smmu_state->secure_level, SDE_EVTLOG_FUNC_ENTRY);

	if ((!smmu_state->transition_type) ||
	    ((smmu_state->transition_type == POST_COMMIT) && !post_commit))
@@ -642,36 +643,35 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,

	mutex_lock(&sde_kms->secure_transition_lock);
	switch (smmu_state->state) {
	/* Secure UI use case enable */
	case DETACH_ALL_REQ:
		ret = _sde_kms_detach_all_cb(sde_kms);
		ret = _sde_kms_detach_all_cb(sde_kms, VMID_CP_SEC_DISPLAY);
		if (!ret)
			smmu_state->state = DETACHED;
		break;

	/* Secure UI use case disable */
	case ATTACH_ALL_REQ:
		ret = _sde_kms_attach_all_cb(sde_kms);
		ret = _sde_kms_attach_all_cb(sde_kms, VMID_CP_PIXEL);
		if (!ret)
			smmu_state->state = ATTACHED;
		break;

	/* Secure preview enable */
	case DETACH_SEC_REQ:
		ret = _sde_kms_detach_sec_cb(sde_kms);
		vmid = (smmu_state->secure_level == SDE_DRM_SEC_ONLY) ?
				VMID_CP_SEC_DISPLAY : VMID_CP_CAMERA_PREVIEW;

		ret = _sde_kms_detach_sec_cb(sde_kms, vmid);
		if (!ret)
			smmu_state->state = DETACHED_SEC;
		break;

	/* Secure preview disable */
	case ATTACH_SEC_REQ:
		ret = _sde_kms_attach_sec_cb(sde_kms);
		ret = _sde_kms_attach_sec_cb(sde_kms, VMID_CP_PIXEL);
		if (!ret)
			smmu_state->state = ATTACHED;
		break;

	default:
		SDE_ERROR("crtc:%d invalid smmu state:%d transition type:%d\n",
		SDE_ERROR("crtc%d: invalid smmu state %d transition type %d\n",
			DRMID(crtc), smmu_state->state,
			smmu_state->transition_type);
		ret = -EINVAL;
@@ -691,11 +691,11 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
	smmu_state->transition_type = NONE;
	smmu_state->transition_error = ret ? true : false;

	SDE_DEBUG("crtc:%d, old_state %d new_state %d, ret %d\n",
	SDE_DEBUG("crtc %d: old_state %d, new_state %d, ret %d\n",
			DRMID(crtc), old_smmu_state, smmu_state->state, ret);
	SDE_EVT32(DRMID(crtc), smmu_state->state, smmu_state->transition_type,
			smmu_state->transition_error, ret,
			SDE_EVTLOG_FUNC_EXIT);
			smmu_state->transition_error, smmu_state->secure_level,
			smmu_state->sui_misr_state, ret, SDE_EVTLOG_FUNC_EXIT);

	return ret;
}
+24 −1
Original line number Diff line number Diff line
@@ -160,11 +160,13 @@ enum sde_kms_sui_misr_state {
/**
 * struct sde_kms_smmu_state_data: stores the smmu state and transition type
 * @state: current state of smmu context banks
 * @secure_level: secure level cached from crtc
 * @transition_type: transition request type
 * @transition_error: whether there is error while transitioning the state
 */
struct sde_kms_smmu_state_data {
	uint32_t state;
	uint32_t secure_level;
	uint32_t transition_type;
	uint32_t transition_error;
	uint32_t sui_misr_state;
@@ -333,7 +335,11 @@ static inline bool sde_kms_is_secure_session_inprogress(struct sde_kms *sde_kms)
		return false;

	mutex_lock(&sde_kms->secure_transition_lock);
	if (sde_kms->smmu_state.state == DETACHED)
	if (((sde_kms->smmu_state.secure_level == SDE_DRM_SEC_ONLY) &&
			((sde_kms->smmu_state.state == DETACHED_SEC) ||
				(sde_kms->smmu_state.state == DETACH_SEC_REQ)))
		|| (((sde_kms->smmu_state.state == DETACHED) ||
			(sde_kms->smmu_state.state == DETACH_ALL_REQ))))
		ret = true;
	mutex_unlock(&sde_kms->secure_transition_lock);

@@ -359,6 +365,23 @@ static inline bool sde_kms_is_vbif_operation_allowed(struct sde_kms *sde_kms)
	return !sde_kms_is_secure_session_inprogress(sde_kms);
}

/**
 * sde_kms_is_cp_operation_allowed - resticts the CP programming
 * during secure-ui, if the non-secure context banks are detached
 *
 * @sde_kms: Pointer to sde_kms
 */
static inline bool sde_kms_is_cp_operation_allowed(struct sde_kms *sde_kms)
{
	if (!sde_kms || !sde_kms->catalog)
		return false;

	if (sde_kms->catalog->sui_ns_allowed)
		return true;

	return !sde_kms_is_secure_session_inprogress(sde_kms);
}

/**
 * Debugfs functions - extra helper functions for debugfs support
 *