summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAdrian Salido-Moreno <adrianm@codeaurora.org>2012-11-30 18:00:16 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:13:30 -0700
commitbba940fc54569763b20e9282a62840df030e76ac (patch)
treedc5d0357fe2d52ea9e1383f966a57c620f1517f1 /drivers
parent6bc239c0ca20f0dd9e95a1eb5ee13b32f13486c2 (diff)
msm: mdss: fix iommu fault due to incorrect buffer unmap
Any buffer that is being fetched by MDP to display on panel should not be unmapped until there is a new buffer to replace it. Ensure multiple buffer updates without a commit to display won't cause displayed buffer to be unmapped. CRs-Fixed: 420561 Change-Id: Ibe720976024d7739c36bd4f05f9f70a061ed1eb9 Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c44
2 files changed, 24 insertions, 24 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 0a7c70158c8a..d93978fb8266 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -243,7 +243,9 @@ struct mdss_mdp_pipe {
unsigned long smp[MAX_PLANES];
- struct mdss_mdp_data buffers[2];
+ struct mdss_mdp_data back_buf;
+ struct mdss_mdp_data front_buf;
+
struct list_head used_list;
struct list_head cleanup_list;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 61c1e9f287cc..5b6d00972970 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -430,35 +430,24 @@ static int mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
{
struct mdss_mdp_pipe *pipe, *tmp;
LIST_HEAD(destroy_pipes);
- int i;
- mutex_lock(&mfd->ov_lock);
mutex_lock(&mfd->lock);
list_for_each_entry_safe(pipe, tmp, &mfd->pipes_cleanup, cleanup_list) {
list_move(&pipe->cleanup_list, &destroy_pipes);
- for (i = 0; i < ARRAY_SIZE(pipe->buffers); i++)
- mdss_mdp_overlay_free_buf(&pipe->buffers[i]);
+ mdss_mdp_overlay_free_buf(&pipe->back_buf);
+ mdss_mdp_overlay_free_buf(&pipe->front_buf);
}
- if (!list_empty(&mfd->pipes_used)) {
- struct mdss_mdp_data *data;
- int buf_ndx;
-
- list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
- buf_ndx = (pipe->play_cnt - 1) & 1; /* prev buffer */
- data = &pipe->buffers[buf_ndx];
-
- if (data->num_planes) {
- pr_debug("free buffer ndx=%d pnum=%d\n",
- buf_ndx, pipe->num);
- mdss_mdp_overlay_free_buf(data);
- }
+ list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ if (pipe->back_buf.num_planes) {
+ /* make back buffer active */
+ mdss_mdp_overlay_free_buf(&pipe->front_buf);
+ swap(pipe->back_buf, pipe->front_buf);
}
}
mutex_unlock(&mfd->lock);
list_for_each_entry_safe(pipe, tmp, &destroy_pipes, cleanup_list)
mdss_mdp_pipe_destroy(pipe);
- mutex_unlock(&mfd->ov_lock);
return 0;
}
@@ -468,12 +457,16 @@ static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
struct msm_fb_data_type *mfd = ctl->mfd;
int ret;
+ mutex_lock(&mfd->ov_lock);
+
if (mfd->kickoff_fnc)
ret = mfd->kickoff_fnc(ctl);
else
ret = mdss_mdp_display_commit(ctl, NULL);
- if (IS_ERR_VALUE(ret))
+ if (IS_ERR_VALUE(ret)) {
+ mutex_unlock(&mfd->ov_lock);
return ret;
+ }
complete(&mfd->update.comp);
mutex_lock(&mfd->no_update.lock);
@@ -486,6 +479,8 @@ static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
ret = mdss_mdp_overlay_cleanup(mfd);
+ mutex_unlock(&mfd->ov_lock);
+
return ret;
}
@@ -630,7 +625,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct mdss_mdp_ctl *ctl;
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_data *src_data;
- int ret, buf_ndx;
+ int ret;
u32 flags;
pipe = mdss_mdp_pipe_get_locked(req->id);
@@ -643,9 +638,12 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
- buf_ndx = (pipe->play_cnt + 1) & 1; /* next buffer */
- src_data = &pipe->buffers[buf_ndx];
- mdss_mdp_overlay_free_buf(src_data);
+ src_data = &pipe->back_buf;
+ if (src_data->num_planes) {
+ pr_warn("dropped buffer pnum=%d play=%d addr=0x%x\n",
+ pipe->num, pipe->play_cnt, src_data->p[0].addr);
+ mdss_mdp_overlay_free_buf(src_data);
+ }
ret = mdss_mdp_overlay_get_buf(mfd, src_data, &req->data, 1, flags);
if (IS_ERR_VALUE(ret)) {