diff options
| author | Adrian Salido-Moreno <adrianm@codeaurora.org> | 2012-11-30 18:00:16 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:13:30 -0700 |
| commit | bba940fc54569763b20e9282a62840df030e76ac (patch) | |
| tree | dc5d0357fe2d52ea9e1383f966a57c620f1517f1 | |
| parent | 6bc239c0ca20f0dd9e95a1eb5ee13b32f13486c2 (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>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 44 |
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)) { |
