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

Commit 8704b327 authored by Animesh Kishore's avatar Animesh Kishore
Browse files

msm: mdss: Add multi-rectangle validation support



Rectangle number is being passed to kernel from
userspace. Added required validation checks.

CRs-Fixed: 2000464

Change-Id: I179caa1a86beb9a8f5f3f9b9ef489bf1fd12c73e
Signed-off-by: default avatarAnimesh Kishore <animeshk@codeaurora.org>
parent 25ed77f5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -220,6 +220,7 @@ static struct mdp_input_layer *__create_layer_list(

		layer->flags = layer32->flags;
		layer->pipe_ndx = layer32->pipe_ndx;
		layer->rect_num = layer32->rect_num;
		layer->horz_deci = layer32->horz_deci;
		layer->vert_deci = layer32->vert_deci;
		layer->z_order = layer32->z_order;
+2 −1
Original line number Diff line number Diff line
@@ -515,7 +515,8 @@ struct mdp_input_layer32 {
	struct mdp_layer_buffer	buffer;
	compat_caddr_t		pp_info;
	int			error_code;
	uint32_t		reserved[6];
	uint32_t		rect_num;
	uint32_t		reserved[5];
};

struct mdp_output_layer32 {
+128 −85
Original line number Diff line number Diff line
@@ -2151,115 +2151,157 @@ static int __multirect_validate_mode(struct msm_fb_data_type *mfd,
	return 0;
}

static int __update_multirect_info(struct msm_fb_data_type *mfd,
		struct mdss_mdp_validate_info_t *validate_info_list,
		struct mdp_input_layer *layer_list, int ndx, int layer_cnt)
/*
 * linear search for a layer with given source pipe and rectangle number.
 * If rectangle number is invalid, it's dropped from search criteria
 */
static int find_layer(enum mdss_mdp_sspp_index pnum,
			int rect_num,
			struct mdp_input_layer *layer_list,
			size_t layer_cnt, int start_index)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct mdss_mdp_validate_info_t *vinfo[MDSS_MDP_PIPE_MAX_RECTS];
	int i, ptype, max_rects, mode;
	int cnt = 1;

	mode = __multirect_layer_flags_to_mode(layer_list[ndx].flags);
	if (IS_ERR_VALUE(mode))
		return mode;
	int i;

	pr_debug("layer #%d pipe_ndx=%d multirect mode=%d\n",
			ndx, layer_list[ndx].pipe_ndx, mode);
	if (start_index < 0)
		start_index = 0;

	vinfo[0] = &validate_info_list[ndx];
	vinfo[0]->layer = &layer_list[ndx];
	vinfo[0]->multirect.mode = mode;
	vinfo[0]->multirect.num = MDSS_MDP_PIPE_RECT0;
	vinfo[0]->multirect.next = NULL;
	if (start_index >= layer_cnt)
		return -EINVAL;

	/* nothing to be done if multirect is disabled */
	if (mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
		return cnt;
	for (i = start_index; i < layer_cnt; i++) {
		if (get_pipe_num_from_ndx(layer_list[i].pipe_ndx) == pnum &&
			(rect_num < MDSS_MDP_PIPE_RECT0 ||
			rect_num >= MDSS_MDP_PIPE_MAX_RECTS ||
			layer_list[i].rect_num == rect_num))
			return i;
	}

	ptype = get_pipe_type_from_ndx(layer_list[ndx].pipe_ndx);
	if (ptype == MDSS_MDP_PIPE_TYPE_INVALID) {
		pr_err("invalid pipe ndx %d\n", layer_list[ndx].pipe_ndx);
		return -EINVAL;
	return -ENOENT; /* no match found */
}

	max_rects = mdata->rects_per_sspp[ptype] ? : 1;
static int __validate_multirect_param(struct msm_fb_data_type *mfd,
			struct mdss_mdp_validate_info_t *validate_info_list,
			struct mdp_input_layer *layer_list,
			int ndx, size_t layer_count)
{
	int multirect_mode;
	int pnum;
	int rect_num;

	/* populate v_info with default values */
	validate_info_list[ndx].layer = &layer_list[ndx];
	validate_info_list[ndx].multirect.max_rects = MDSS_MDP_PIPE_MAX_RECTS;
	validate_info_list[ndx].multirect.next = NULL;
	validate_info_list[ndx].multirect.num = MDSS_MDP_PIPE_RECT0;
	validate_info_list[ndx].multirect.mode = MDSS_MDP_PIPE_MULTIRECT_NONE;

	multirect_mode = __multirect_layer_flags_to_mode(
					layer_list[ndx].flags);
	if (IS_ERR_VALUE(multirect_mode))
		return multirect_mode;

	for (i = ndx + 1; i < layer_cnt; i++) {
		if (layer_list[ndx].pipe_ndx == layer_list[i].pipe_ndx) {
			if (cnt >= max_rects) {
				pr_err("more than %d layers of type %d with same pipe_ndx=%d indexes=%d %d\n",
					max_rects, ptype,
					layer_list[ndx].pipe_ndx, ndx, i);
	/* nothing to be done if multirect is disabled */
	if (multirect_mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
		return 0;

	validate_info_list[ndx].multirect.mode = multirect_mode;

	pnum = get_pipe_num_from_ndx(layer_list[ndx].pipe_ndx);
	if (get_pipe_type_from_num(pnum) != MDSS_MDP_PIPE_TYPE_DMA) {
		pr_err("Multirect not supported on pipe ndx 0x%x\n",
			layer_list[ndx].pipe_ndx);
		return -EINVAL;
	}

			mode = __multirect_layer_flags_to_mode(
					layer_list[i].flags);
			if (IS_ERR_VALUE(mode))
				return mode;

			if (mode != vinfo[0]->multirect.mode) {
				pr_err("unable to set different multirect modes for pipe_ndx=%d (%d %d)\n",
					layer_list[ndx].pipe_ndx, ndx, i);
	rect_num = layer_list[ndx].rect_num;
	if (rect_num >= MDSS_MDP_PIPE_MAX_RECTS)
		return -EINVAL;
	validate_info_list[ndx].multirect.num = rect_num;

	return 0;
}

			pr_debug("found matching pair for pipe_ndx=%d (%d %d)\n",
					layer_list[i].pipe_ndx, ndx, i);
static int __update_multirect_info(struct msm_fb_data_type *mfd,
			struct mdss_mdp_validate_info_t *validate_info_list,
			struct mdp_input_layer *layer_list,
			int ndx, size_t layer_cnt, int is_rect_num_valid)
{
	int ret;
	int pair_rect_num = -1;
	int pair_index;

			vinfo[cnt] = &validate_info_list[i];
			vinfo[cnt]->multirect.num = cnt;
			vinfo[cnt]->multirect.next = vinfo[0]->layer;
			vinfo[cnt]->multirect.mode = mode;
			vinfo[cnt]->layer = &layer_list[i];
	if (!is_rect_num_valid)
		layer_list[ndx].rect_num = MDSS_MDP_PIPE_RECT0;

			vinfo[cnt - 1]->multirect.next = vinfo[cnt]->layer;
			cnt++;
		}
	}
	ret = __validate_multirect_param(mfd, validate_info_list,
				layer_list, ndx, layer_cnt);
	/* return if we hit error or multirectangle mode is disabled. */
	if (IS_ERR_VALUE(ret) ||
		(!ret && validate_info_list[ndx].multirect.mode ==
		MDSS_MDP_PIPE_MULTIRECT_NONE))
		return ret;

	if (is_rect_num_valid)
		pair_rect_num = (validate_info_list[ndx].multirect.num ==
				MDSS_MDP_PIPE_RECT0) ? MDSS_MDP_PIPE_RECT1 :
				MDSS_MDP_PIPE_RECT0;

	if (cnt == 1) {
		pr_err("multirect mode enabled but unable to find extra rects for pipe_ndx=%x\n",
	pair_index = find_layer(get_pipe_num_from_ndx(
			layer_list[ndx].pipe_ndx), pair_rect_num,
			layer_list, layer_cnt, ndx + 1);
	if (IS_ERR_VALUE(pair_index)) {
		pr_err("Multirect pair not found for pipe ndx 0x%x\n",
			layer_list[ndx].pipe_ndx);
		return -EINVAL;
	}

	return cnt;
	if (!is_rect_num_valid)
		layer_list[pair_index].rect_num = MDSS_MDP_PIPE_RECT1;

	ret = __validate_multirect_param(mfd, validate_info_list,
				layer_list, pair_index, layer_cnt);
	if (IS_ERR_VALUE(ret) ||
		(validate_info_list[ndx].multirect.mode !=
		validate_info_list[pair_index].multirect.mode))
		return -EINVAL;

	validate_info_list[ndx].multirect.next = &layer_list[pair_index];
	validate_info_list[pair_index].multirect.next = &layer_list[ndx];

	return 0;
}

static int __validate_multirect(struct msm_fb_data_type *mfd,
			struct mdss_mdp_validate_info_t *validate_info_list,
	struct mdp_input_layer *layer_list, int ndx, int layer_cnt)
			struct mdp_input_layer *layer_list,
			int ndx, size_t layer_cnt, int is_rect_num_valid)
{
	struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS] = { 0 };
	int i, cnt, rc;

	cnt = __update_multirect_info(mfd, validate_info_list,
			layer_list, ndx, layer_cnt);
	if (IS_ERR_VALUE(cnt))
		return cnt;
	int ret;
	int i;
	struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS];
	struct mdp_input_layer *pair_layer;

	if (cnt <= 1) {
		/* nothing to validate in single rect mode */
		return 0;
	} else if (cnt > 2) {
		pr_err("unsupported multirect configuration, multirect cnt=%d\n",
				cnt);
		return -EINVAL;
	}
	ret = __update_multirect_info(mfd, validate_info_list,
				layer_list, ndx, layer_cnt, is_rect_num_valid);
	/* return if we hit error or multirectangle mode is disabled. */
	if (IS_ERR_VALUE(ret) ||
		(!ret && validate_info_list[ndx].multirect.mode ==
		MDSS_MDP_PIPE_MULTIRECT_NONE))
		return ret;

	layers[0] = validate_info_list[ndx].layer;
	layers[1] = validate_info_list[ndx].multirect.next;
	layers[validate_info_list[ndx].multirect.num] = &layer_list[ndx];
	pair_layer = validate_info_list[ndx].multirect.next;
	layers[pair_layer->rect_num] = pair_layer;

	/* check against smart DMA v1.0 restrictions */
	for (i = 0; i < ARRAY_SIZE(__multirect_validators); i++) {
		if (!__multirect_validators[i](layers, cnt))
		if (!__multirect_validators[i](layers,
			MDSS_MDP_PIPE_MAX_RECTS))
			return -EINVAL;
	}

	rc = __multirect_validate_mode(mfd, layers, cnt);
	if (IS_ERR_VALUE(rc))
		return rc;
	ret = __multirect_validate_mode(mfd, layers, MDSS_MDP_PIPE_MAX_RECTS);
	if (IS_ERR_VALUE(ret))
		return ret;

	return 0;
}
@@ -2407,14 +2449,14 @@ static int __validate_layers(struct msm_fb_data_type *mfd,

		if (!validate_info_list[i].layer) {
			ret = __validate_multirect(mfd, validate_info_list,
						   layer_list, i, layer_count);
				layer_list, i, layer_count,
				!!(commit->flags & MDP_COMMIT_RECT_NUM));
			if (ret) {
				pr_err("error validating multirect config. ret=%d i=%d\n",
					ret, i);
				goto end;
			}
		}

		rect_num = validate_info_list[i].multirect.num;
		BUG_ON(rect_num >= MDSS_MDP_PIPE_MAX_RECTS);

@@ -2772,7 +2814,8 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
	for (i = 0; i < layer_count; i++) {
		if (!validate_info_list[i].layer) {
			ret = __update_multirect_info(mfd, validate_info_list,
						   layer_list, i, layer_count);
				layer_list, i, layer_count,
				!!(commit->flags & MDP_COMMIT_RECT_NUM));
			if (IS_ERR_VALUE(ret)) {
				pr_err("error updating multirect config. ret=%d i=%d\n",
					ret, i);
+13 −1
Original line number Diff line number Diff line
@@ -178,6 +178,12 @@ VALIDATE/COMMIT FLAG CONFIGURATION
 */
#define MDP_COMMIT_CWB_DSPP 0x1000

/*
 * Flag to indicate that rectangle number is being assigned
 * by userspace in multi-rectangle mode
 */
#define MDP_COMMIT_RECT_NUM 0x2000

#define MDP_COMMIT_VERSION_1_0		0x00010000

#define OUT_LAYER_COLOR_SPACE
@@ -425,8 +431,14 @@ struct mdp_input_layer {
	 */
	int			error_code;

	/*
	 * For source pipes supporting multi-rectangle, this field identifies
	 * the rectangle index of the source pipe.
	 */
	uint32_t		rect_num;

	/* 32bits reserved value for future usage. */
	uint32_t		reserved[6];
	uint32_t		reserved[5];
};

struct mdp_output_layer {