summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnimesh Kishore <animeshk@codeaurora.org>2017-04-11 19:40:24 +0530
committerAnimesh Kishore <animeshk@codeaurora.org>2017-04-24 13:59:22 +0530
commit8704b3275410c265ee04ed6f0c81c9b975b42227 (patch)
treeee7d07ec6b1e3e468c6e111e131fa2f16781409e
parent25ed77f5bb9a1af7e4635c5aa91505fae041ea27 (diff)
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: Animesh Kishore <animeshk@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c213
-rw-r--r--include/uapi/linux/msm_mdp_ext.h14
4 files changed, 144 insertions, 87 deletions
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index 17644e3556b6..5ce9dbaf73fe 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -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;
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h
index 4f44cd1c9471..b7fa401f52d2 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.h
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.h
@@ -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 {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index fce667a2126d..914f73d067a9 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -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;
+ int i;
- mode = __multirect_layer_flags_to_mode(layer_list[ndx].flags);
- if (IS_ERR_VALUE(mode))
- return mode;
+ if (start_index < 0)
+ start_index = 0;
- pr_debug("layer #%d pipe_ndx=%d multirect mode=%d\n",
- ndx, layer_list[ndx].pipe_ndx, mode);
+ if (start_index >= layer_cnt)
+ return -EINVAL;
- 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;
+ 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;
+ }
- /* nothing to be done if multirect is disabled */
- if (mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
- return cnt;
+ return -ENOENT; /* no match found */
+}
- 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;
- }
+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;
- max_rects = mdata->rects_per_sspp[ptype] ? : 1;
+ /* nothing to be done if multirect is disabled */
+ if (multirect_mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
+ return 0;
- 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);
- return -EINVAL;
- }
+ validate_info_list[ndx].multirect.mode = multirect_mode;
- mode = __multirect_layer_flags_to_mode(
- layer_list[i].flags);
- if (IS_ERR_VALUE(mode))
- return 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;
+ }
- 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);
- return -EINVAL;
- }
+ 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;
- pr_debug("found matching pair for pipe_ndx=%d (%d %d)\n",
- layer_list[i].pipe_ndx, ndx, i);
+ return 0;
+}
- 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];
+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;
+
+ if (!is_rect_num_valid)
+ layer_list[ndx].rect_num = MDSS_MDP_PIPE_RECT0;
+
+ 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;
- vinfo[cnt - 1]->multirect.next = vinfo[cnt]->layer;
- cnt++;
- }
- }
+ 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 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)
{
- 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;
-
- 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;
- }
+ int ret;
+ int i;
+ struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS];
+ struct mdp_input_layer *pair_layer;
+
+ 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);
diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 35029f227f8b..da9ee3bcc525 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -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 {