summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerence Hampson <thampson@codeaurora.org>2015-09-21 15:21:21 -0400
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:46:06 -0700
commitbc9915b8186cc2276d23af794b61539116b36cef (patch)
tree2ac16ad98a66f09cd19437a8a2cf32798f382a37
parent0a6a08aeac0f5551ccb4976906e4c54cfeeb7177 (diff)
msm: mdss: validate buffer size is enough for intended use
Make sure buffer size is enough for intended use, as soon as we acquire buffer handle. Prior to this change validation was done when mapping the buffer. Failing the validation at this later point was resulting in a layer update drop, with no clean way to handle the validation. By validating earlier, request to commit the frame can fail and client can determine fall back behaviour. Change-Id: Ie14317c5d5125d6bd23fedfdbbaa877897f8786b Signed-off-by: Terence Hampson <thampson@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c19
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_rotator.c19
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c55
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_wb.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_wfd.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_rotator.c4
8 files changed, 108 insertions, 27 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index ab0f371a8783..cbfb687767a5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1228,11 +1228,12 @@ void mdss_mdp_get_v_h_subsample_rate(u8 chroma_samp,
u8 *v_sample, u8 *h_sample);
struct mult_factor *mdss_mdp_get_comp_factor(u32 format,
bool rt_factor);
-int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
- int num_planes, u32 flags, struct device *dev, bool rotator,
- int dir);
int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir);
void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir);
+int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
+ struct msmfb_data *planes, int num_planes, u32 flags,
+ struct device *dev, bool rotator, int dir,
+ struct mdp_layer_buffer *buffer);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 9aa5dc39174d..4a22dad62608 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -856,15 +856,18 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd,
image.memory_id = buffer->planes[0].fd;
image.offset = buffer->planes[0].offset;
- ret = mdss_mdp_data_get(src_data, &image, 1, flags,
- &mfd->pdev->dev, false, DMA_TO_DEVICE);
- if (ret) {
- mdss_mdp_overlay_buf_free(mfd, src_data);
- src_data = ERR_PTR(ret);
- } else {
- src_data->num_planes = 1;
- }
+ ret = mdss_mdp_data_get_and_validate_size(src_data, &image, 1,
+ flags, &mfd->pdev->dev, false, DMA_TO_DEVICE,
+ buffer);
+ if (ret)
+ goto end_buf_free;
+
+ src_data->num_planes = 1;
+ return src_data;
+end_buf_free:
+ mdss_mdp_overlay_buf_free(mfd, src_data);
+ src_data = ERR_PTR(ret);
end:
return src_data;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3ce6334da263..2913527890a1 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2177,6 +2177,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_data *src_data;
+ struct mdp_layer_buffer buffer;
int ret;
u32 flags;
@@ -2212,8 +2213,12 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
pr_err("unable to allocate source buffer\n");
ret = -ENOMEM;
} else {
- ret = mdss_mdp_data_get(src_data, &req->data, 1, flags,
- &mfd->pdev->dev, false, DMA_TO_DEVICE);
+ buffer.width = pipe->img_width;
+ buffer.height = pipe->img_height;
+ buffer.format = pipe->src_fmt->format;
+ ret = mdss_mdp_data_get_and_validate_size(src_data, &req->data,
+ 1, flags, &mfd->pdev->dev, false, DMA_TO_DEVICE,
+ &buffer);
if (IS_ERR_VALUE(ret)) {
mdss_mdp_overlay_buf_free(mfd, src_data);
pr_err("src_data pmem error\n");
diff --git a/drivers/video/fbdev/msm/mdss_mdp_rotator.c b/drivers/video/fbdev/msm/mdss_mdp_rotator.c
index 7b88c664f4ba..d7a9f73966ea 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_rotator.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_rotator.c
@@ -1005,6 +1005,7 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
struct mdss_mdp_rotator_session *rot;
+ struct mdp_layer_buffer buffer;
int ret;
u32 flgs;
struct mdss_mdp_data src_buf;
@@ -1024,8 +1025,12 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
mdss_iommu_ctrl(1);
mutex_lock(&rot->lock);
- ret = mdss_mdp_data_get(&src_buf, &req->data, 1, flgs,
- &mfd->pdev->dev, true, DMA_TO_DEVICE);
+ buffer.width = rot->src_rect.w;
+ buffer.height = rot->src_rect.h;
+ buffer.format = rot->format;
+ ret = mdss_mdp_data_get_and_validate_size(&src_buf,
+ &req->data, 1, flgs, &mfd->pdev->dev, true,
+ DMA_TO_DEVICE, &buffer);
if (ret) {
pr_err("src_data pmem error\n");
goto dst_buf_fail;
@@ -1041,8 +1046,14 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
memcpy(&rot->src_buf, &src_buf, sizeof(struct mdss_mdp_data));
mdss_mdp_data_free(&rot->dst_buf, true, DMA_FROM_DEVICE);
- ret = mdss_mdp_data_get(&rot->dst_buf, &req->dst_data, 1, flgs,
- &mfd->pdev->dev, true, DMA_FROM_DEVICE);
+ buffer.width = rot->dst.w;
+ buffer.height = rot->dst.h;
+ buffer.format = mdss_mdp_get_rotator_dst_format(rot->format,
+ rot->flags & MDP_ROT_90, rot->bwc_mode);
+
+ ret = mdss_mdp_data_get_and_validate_size(&rot->dst_buf,
+ &req->dst_data, 1, flgs, &mfd->pdev->dev, true,
+ DMA_FROM_DEVICE, &buffer);
if (ret) {
pr_err("dst_data pmem error\n");
mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c
index 5faacaa65a26..bad0074fec27 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_util.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_util.c
@@ -1238,9 +1238,9 @@ err_unmap:
return ret;
}
-int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
- int num_planes, u32 flags, struct device *dev, bool rotator,
- int dir)
+static int mdss_mdp_data_get(struct mdss_mdp_data *data,
+ struct msmfb_data *planes, int num_planes, u32 flags,
+ struct device *dev, bool rotator, int dir)
{
int i, rc = 0;
@@ -1300,6 +1300,55 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir)
data->num_planes = 0;
}
+int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
+ struct msmfb_data *planes, int num_planes, u32 flags,
+ struct device *dev, bool rotator, int dir,
+ struct mdp_layer_buffer *buffer)
+{
+ struct mdss_mdp_format_params *fmt;
+ struct mdss_mdp_plane_sizes ps;
+ int ret, i;
+ unsigned long total_buf_len = 0;
+
+ fmt = mdss_mdp_get_format_params(buffer->format);
+ if (!fmt) {
+ pr_err("Format %d not supported\n", buffer->format);
+ return -EINVAL;
+ }
+
+ ret = mdss_mdp_data_get(data, planes, num_planes,
+ flags, dev, rotator, dir);
+ if (ret)
+ return ret;
+
+ mdss_mdp_get_plane_sizes(fmt, buffer->width, buffer->height, &ps, 0, 0);
+
+ for (i = 0; i < num_planes ; i++) {
+ unsigned long plane_len = (data->p[i].srcp_dma_buf) ?
+ data->p[i].srcp_dma_buf->size : data->p[i].len;
+
+ if (plane_len < planes[i].offset) {
+ pr_err("Offset=%d larger than buffer size=%lu\n",
+ planes[i].offset, plane_len);
+ ret = -EINVAL;
+ goto buf_too_small;
+ }
+ total_buf_len += plane_len - planes[i].offset;
+ }
+
+ if (total_buf_len < ps.total_size) {
+ pr_err("Buffer size=%lu, expected size=%d\n", total_buf_len,
+ ps.total_size);
+ ret = -EINVAL;
+ goto buf_too_small;
+ }
+ return 0;
+
+buf_too_small:
+ mdss_mdp_data_free(data, rotator, dir);
+ return ret;
+}
+
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
diff --git a/drivers/video/fbdev/msm/mdss_mdp_wb.c b/drivers/video/fbdev/msm/mdss_mdp_wb.c
index 0733d550358e..c9b69452d4a7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_wb.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_wb.c
@@ -409,10 +409,12 @@ static struct mdss_mdp_wb_data *get_local_node(struct mdss_mdp_wb *wb,
static struct mdss_mdp_wb_data *get_user_node(struct msm_fb_data_type *mfd,
struct msmfb_data *data)
{
-
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ struct mdp_layer_buffer buffer;
struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node;
struct mdss_mdp_img_data *buf;
+ struct mdss_mdp_mixer *mixer;
u32 flags = 0;
int ret;
@@ -453,8 +455,17 @@ static struct mdss_mdp_wb_data *get_user_node(struct msm_fb_data_type *mfd,
if (wb->is_secure)
flags |= MDP_SECURE_OVERLAY_SESSION;
- ret = mdss_mdp_data_get(&node->buf_data, data, 1, flags,
- &mfd->pdev->dev, true, DMA_FROM_DEVICE);
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
+ if (!mixer) {
+ pr_err("Null mixer\n");
+ goto register_fail;
+ }
+ buffer.width = mixer->width;
+ buffer.height = mixer->height;
+ buffer.format = ctl->dst_format;
+ ret = mdss_mdp_data_get_and_validate_size(&node->buf_data,
+ data, 1, flags, &mfd->pdev->dev, true, DMA_FROM_DEVICE,
+ &buffer);
if (IS_ERR_VALUE(ret)) {
pr_err("error getting buffer info\n");
goto register_fail;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_wfd.c b/drivers/video/fbdev/msm/mdss_mdp_wfd.c
index aefec0f2f47c..6795ac17492d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_wfd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_wfd.c
@@ -239,8 +239,9 @@ static int mdss_mdp_wfd_import_data(struct device *device,
planes[i].offset = buffer->planes[i].offset;
}
- ret = mdss_mdp_data_get(data, planes, buffer->plane_count, flags,
- device, false, DMA_FROM_DEVICE);
+ ret = mdss_mdp_data_get_and_validate_size(data, planes,
+ buffer->plane_count, flags, device,
+ false, DMA_FROM_DEVICE, buffer);
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c
index fb4acfc7def0..a5afb18178b4 100644
--- a/drivers/video/fbdev/msm/mdss_rotator.c
+++ b/drivers/video/fbdev/msm/mdss_rotator.c
@@ -504,8 +504,8 @@ static int mdss_rotator_import_buffer(struct mdp_layer_buffer *buffer,
planes[i].offset = buffer->planes[i].offset;
}
- ret = mdss_mdp_data_get(data, planes, buffer->plane_count,
- flags, dev, true, dir);
+ ret = mdss_mdp_data_get_and_validate_size(data, planes,
+ buffer->plane_count, flags, dev, true, dir, buffer);
return ret;
}