diff options
| author | Dhaval Patel <pdhaval@codeaurora.org> | 2015-07-15 21:27:24 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:44:07 -0700 |
| commit | 9a87e1dcc6031396cb248b6402119db7d22e342d (patch) | |
| tree | bf0254e534781ca9a4490974ec6c793e68c5525a /drivers/video/fbdev | |
| parent | 1084c53ce60fa9694a2e812fd123d9fef1996e61 (diff) | |
msm: mdss: wait for pipe free before returning busy error
Client waits for retire fence and reuse the pipe
on another display interface. This pipe is not
stagged on MDP hardware but software structures
are not updated because retire fence is signaled
first. Due scheduling priorities between two threads,
validate call from another interface may come first
and try to reuse the same pipe. MDSS driver fails
this call because software structures are not
updated with pipe status.
Ideally, driver should wait for timeout duration
to allow other interface (or software structure) to
release the pipe. This allow clients to reuse the
same pipe on multiple displays without switching
composition method.
Change-Id: I999874f38a829162de7708cf2e5b3b425c9d5f2a
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
[cip@codeaurora.org: Resolved merge conflicts]
Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_layer.c | 5 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_pipe.c | 45 |
4 files changed, 41 insertions, 14 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 8bf9153af2e8..0935edcf6e2a 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -572,6 +572,7 @@ struct mdss_mdp_pipe { u8 chroma_sample_h; u8 chroma_sample_v; + wait_queue_head_t free_waitq; u32 frame_rate; u8 csc_coeff_set; }; diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index d696d3d3463e..c70a123bdd2d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -936,7 +936,6 @@ static struct mdss_mdp_pipe *__assign_pipe_for_layer( struct mdss_mdp_pipe *pipe; struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_data_type *mdata = mfd_to_mdata(mfd); - u32 pipe_list = 0; pipe = __find_used_pipe(mfd, pipe_ndx); *new_pipe = pipe ? false : true; @@ -962,8 +961,8 @@ static struct mdss_mdp_pipe *__assign_pipe_for_layer( pipe = mdss_mdp_pipe_assign(mdata, mixer, pipe_ndx); if (IS_ERR_OR_NULL(pipe)) { - pr_err("error reserving pipe. pipe_ndx=0x%x pipe_list=0x%x\n", - pipe_ndx, pipe_list); + pr_err("error reserving pipe. pipe_ndx=0x%x mfd ndx=%d\n", + pipe_ndx, mfd->index); goto end; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 74e63c449f94..2221258a0aa0 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -2345,8 +2345,8 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd) if (!mdp5_data || !mdp5_data->ctl) return; - if (fbi->fix.smem_len == 0 || - mdp5_data->borderfill_enable) { + if (IS_ERR_OR_NULL(mfd->fbmem_buf) || fbi->fix.smem_len == 0 || + mdp5_data->borderfill_enable) { mfd->mdp.kickoff_fnc(mfd, NULL); return; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 18e946c1e8ed..de2a2af559db 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -27,6 +27,8 @@ #define SMP_MB_ENTRY_SIZE 16 #define MAX_BPP 4 +#define PIPE_CLEANUP_TIMEOUT_US 100000 + /* following offsets are relative to ctrl register bit offset */ #define CLK_FORCE_ON_OFFSET 0x0 #define CLK_FORCE_OFF_OFFSET 0x1 @@ -959,6 +961,13 @@ static void mdss_mdp_fixed_qos_arbiter_setup(struct mdss_data_type *mdata, mutex_unlock(&mdata->reg_lock); } +static void mdss_mdp_init_pipe_params(struct mdss_mdp_pipe *pipe) +{ + kref_init(&pipe->kref); + init_waitqueue_head(&pipe->free_waitq); + INIT_LIST_HEAD(&pipe->buf_queue); +} + static int mdss_mdp_pipe_init_config(struct mdss_mdp_pipe *pipe, struct mdss_mdp_mixer *mixer, bool pipe_share) { @@ -978,8 +987,7 @@ static int mdss_mdp_pipe_init_config(struct mdss_mdp_pipe *pipe, if (pipe) { pr_debug("type=%x pnum=%d\n", pipe->type, pipe->num); - kref_init(&pipe->kref); - INIT_LIST_HEAD(&pipe->buf_queue); + mdss_mdp_init_pipe_params(pipe); } else if (pipe_share) { /* @@ -1067,8 +1075,7 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer, } if (pipe && type == MDSS_MDP_PIPE_TYPE_CURSOR) { - kref_init(&pipe->kref); - INIT_LIST_HEAD(&pipe->buf_queue); + mdss_mdp_init_pipe_params(pipe); pr_debug("cursor: type=%x pnum=%d\n", pipe->type, pipe->num); goto cursor_done; @@ -1146,6 +1153,7 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, { struct mdss_mdp_pipe *pipe = NULL; int rc; + int retry_count = 0; if (!ndx) return ERR_PTR(-EINVAL); @@ -1159,9 +1167,27 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, } if (atomic_read(&pipe->kref.refcount) != 0) { - pr_err("pipe is in use\n"); - pipe = ERR_PTR(-EBUSY); - goto error; + mutex_unlock(&mdss_mdp_sspp_lock); + do { + rc = wait_event_interruptible_timeout(pipe->free_waitq, + !atomic_read(&pipe->kref.refcount), + usecs_to_jiffies(PIPE_CLEANUP_TIMEOUT_US)); + if (rc == 0 || retry_count == 5) { + pr_err("pipe ndx:%d free wait failed, mfd ndx:%d rc=%d\n", + pipe->ndx, + pipe->mfd ? pipe->mfd->index : -1, rc); + pipe = ERR_PTR(-EBUSY); + goto end; + } else if (rc == -ERESTARTSYS) { + pr_debug("interrupt signal received\n"); + retry_count++; + continue; + } else { + break; + } + } while (true); + + mutex_lock(&mdss_mdp_sspp_lock); } pipe->mixer_left = mixer; @@ -1171,6 +1197,7 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata, error: mutex_unlock(&mdss_mdp_sspp_lock); +end: return pipe; } @@ -1499,6 +1526,7 @@ int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe) return -EBUSY; } + wake_up_all(&pipe->free_waitq); mutex_unlock(&mdss_mdp_sspp_lock); return 0; @@ -1566,8 +1594,7 @@ int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe) pipe->is_handed_off = true; pipe->play_cnt = 1; - kref_init(&pipe->kref); - INIT_LIST_HEAD(&pipe->buf_queue); + mdss_mdp_init_pipe_params(pipe); error: return rc; |
