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

Commit 8da18b4f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: avoid multi-display update during secure-session"

parents bc710458 f9fca5f3
Loading
Loading
Loading
Loading
+38 −30
Original line number Original line Diff line number Diff line
@@ -4329,13 +4329,14 @@ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state,
}
}


static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
		struct drm_crtc_state *state, struct plane_state pstates[],
		int cnt)
{
{
	struct drm_encoder *encoder;
	struct drm_encoder *encoder;
	struct sde_crtc_state *cstate;
	struct sde_crtc_state *cstate;
	uint32_t secure;
	uint32_t secure;
	uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0;
	uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0;
	int encoder_cnt = 0;
	int encoder_cnt = 0, i;
	int rc;
	int rc;


	if (!crtc || !state) {
	if (!crtc || !state) {
@@ -4345,31 +4346,40 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,


	cstate = to_sde_crtc_state(state);
	cstate = to_sde_crtc_state(state);


	secure = sde_crtc_get_property(cstate,
	secure = sde_crtc_get_property(cstate, CRTC_PROP_SECURITY_LEVEL);
			CRTC_PROP_SECURITY_LEVEL);


	rc = _sde_crtc_find_plane_fb_modes(state,
	rc = _sde_crtc_find_plane_fb_modes(state, &fb_ns, &fb_sec, &fb_sec_dir);
			&fb_ns,
			&fb_sec,
			&fb_sec_dir);
	if (rc)
	if (rc)
		return rc;
		return rc;


	/**
	if (secure == SDE_DRM_SEC_ONLY) {
	 * validate planes
		/*
	 * fb_sec_dir is for secure camera preview and secure display  use case,
		 * validate planes - only fb_sec_dir is allowed during sec_crtc
	 * fb_sec is for secure video playback,
		 * - fb_sec_dir is for secure camera preview and
	 * fb_ns is for normal non secure use cases.
		 * secure display use case
		 * - fb_sec is for secure video playback
		 * - fb_ns is for normal non secure use cases
		 */
		 */
	if ((secure == SDE_DRM_SEC_ONLY) &&
		if (fb_ns || fb_sec) {
			(fb_ns || fb_sec || (fb_sec && fb_sec_dir))) {
			SDE_ERROR(
			SDE_ERROR(
		"crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n",
			 "crtc%d: invalid fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n",
				crtc->base.id, fb_sec, fb_ns, fb_sec_dir);
				crtc->base.id, fb_sec, fb_ns, fb_sec_dir);
			return -EINVAL;
			return -EINVAL;
		}
		}


	/**
		/* only one blending stage is allowed in sec_crtc */
		for (i = 1; i < cnt; i++) {
			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,
				  i-1, pstates[i-1].stage);
				return -EINVAL;
			}
		}
	}

	/*
	 * secure_crtc is not allowed in a shared toppolgy
	 * secure_crtc is not allowed in a shared toppolgy
	 * across different encoders.
	 * across different encoders.
	 */
	 */
@@ -4378,17 +4388,15 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc,
			if (encoder->crtc ==  crtc)
			if (encoder->crtc ==  crtc)
				encoder_cnt++;
				encoder_cnt++;


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


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

	return 0;
	return 0;
}
}


@@ -4445,10 +4453,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	_sde_crtc_setup_is_ppsplit(state);
	_sde_crtc_setup_is_ppsplit(state);
	_sde_crtc_setup_lm_bounds(crtc, state);
	_sde_crtc_setup_lm_bounds(crtc, state);


	rc = _sde_crtc_check_secure_state(crtc, state);
	if (rc)
		return rc;

	 /* get plane state for all drm planes associated with crtc state */
	 /* get plane state for all drm planes associated with crtc state */
	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
		if (IS_ERR_OR_NULL(pstate)) {
		if (IS_ERR_OR_NULL(pstate)) {
@@ -4522,6 +4526,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	/* assign mixer stages based on sorted zpos property */
	/* assign mixer stages based on sorted zpos property */
	sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
	sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);


	rc = _sde_crtc_check_secure_state(crtc, state, pstates, cnt);
	if (rc)
		goto end;

	rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt);
	rc = _sde_crtc_excl_dim_layer_check(state, pstates, cnt);
	if (rc)
	if (rc)
		goto end;
		goto end;
+44 −36
Original line number Original line Diff line number Diff line
@@ -1910,10 +1910,10 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms,
	struct sde_kms *sde_kms;
	struct sde_kms *sde_kms;
	struct drm_device *dev;
	struct drm_device *dev;
	struct drm_crtc *crtc;
	struct drm_crtc *crtc;
	struct drm_crtc *sec_crtc = NULL, *temp_crtc = NULL;
	struct drm_crtc *cur_crtc = NULL, *global_crtc = NULL;
	struct drm_crtc_state *crtc_state;
	struct drm_crtc_state *crtc_state;
	int secure_crtc_cnt = 0, active_crtc_cnt = 0;
	int active_crtc_cnt = 0, global_active_crtc_cnt = 0;
	int secure_global_crtc_cnt = 0, active_mode_crtc_cnt = 0;
	bool sec_session = false, global_sec_session = false;
	int i;
	int i;


	if (!kms || !state) {
	if (!kms || !state) {
@@ -1921,56 +1921,64 @@ static int sde_kms_check_secure_transition(struct msm_kms *kms,
		SDE_ERROR("invalid arguments\n");
		SDE_ERROR("invalid arguments\n");
	}
	}


	/* iterate state object for active and secure crtc */
	sde_kms = to_sde_kms(kms);
	dev = sde_kms->dev;

	/* iterate state object for active secure/non-secure crtc */
	for_each_crtc_in_state(state, crtc, crtc_state, i) {
	for_each_crtc_in_state(state, crtc, crtc_state, i) {
		if (!crtc_state->active)
		if (!crtc_state->active)
			continue;
			continue;

		active_crtc_cnt++;
		active_crtc_cnt++;
		if (sde_crtc_get_secure_level(crtc, crtc_state) ==
		if (sde_crtc_get_secure_level(crtc, crtc_state) ==
				SDE_DRM_SEC_ONLY) {
				SDE_DRM_SEC_ONLY)
			sec_crtc = crtc;
			sec_session = true;
			secure_crtc_cnt++;
		}
	}

	/* bail out from further validation if no secure ctrc */
	if (!secure_crtc_cnt)
		return 0;


	if ((secure_crtc_cnt > MAX_ALLOWED_SECURE_CLIENT_CNT) ||
		cur_crtc = crtc;
		(secure_crtc_cnt &&
		 (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE))) {
		SDE_ERROR("Secure check failed active:%d, secure:%d\n",
				active_crtc_cnt, secure_crtc_cnt);
		return -EPERM;
	}
	}


	sde_kms = to_sde_kms(kms);
	dev = sde_kms->dev;
	/* iterate global list for active and secure crtc */
	/* iterate global list for active and secure crtc */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {

		if (!crtc->state->active)
		if (!crtc->state->active)
			continue;
			continue;


		active_mode_crtc_cnt++;
		global_active_crtc_cnt++;

		if (sde_crtc_get_secure_level(crtc, crtc->state) ==
		if (sde_crtc_get_secure_level(crtc, crtc->state) ==
				SDE_DRM_SEC_ONLY) {
				SDE_DRM_SEC_ONLY)
			secure_global_crtc_cnt++;
			global_sec_session = true;
			temp_crtc = crtc;

		}
		global_crtc = crtc;
	}
	}


	/**
	/*
	 * if more than one crtc is active fail
	 * - fail secure crtc commit, if any other crtc session is already
	 * check if the previous and current commit secure
	 *   in progress
	 * are same
	 * - fail non-secure crtc commit, if any secure crtc session is already
	 *   in progress
	 */
	 */
	if (secure_crtc_cnt && ((active_mode_crtc_cnt > 1) ||
	if (global_sec_session || sec_session) {
			(secure_global_crtc_cnt && (temp_crtc != sec_crtc))))
		if ((global_active_crtc_cnt >
		SDE_ERROR("Secure check failed active:%d crtc_id:%d\n",
					MAX_ALLOWED_CRTC_CNT_DURING_SECURE) ||
				active_mode_crtc_cnt, temp_crtc->base.id);
		    (active_crtc_cnt > MAX_ALLOWED_CRTC_CNT_DURING_SECURE)) {
			SDE_ERROR(
			"Secure check failed global_active:%d active:%d\n",
				global_active_crtc_cnt, active_crtc_cnt);
			return -EPERM;

		/*
		 * As only one crtc is allowed during secure session, the crtc
		 * in this commit should match with the global crtc, if it
		 * exists
		 */
		} else if (global_crtc && (global_crtc != cur_crtc)) {
			SDE_ERROR(
			    "crtc%d-sec%d not allowed during crtc%d-sec%d\n",
				cur_crtc->base.id, sec_session,
				global_crtc->base.id, global_sec_session);
			return -EPERM;
		}

	}


	return 0;
	return 0;
}
}