From f30f4564c46d19579334aecd83d0323afe967bd9 Mon Sep 17 00:00:00 2001 From: Ken Zhang Date: Sun, 13 Apr 2014 18:28:20 -0400 Subject: [PATCH] msm: display: reduce display commit prepare waiting time Unblock overlay_set, prepare and buffer sync ioctls when commit thread finishes hardware programming. Use wait_for_kickoff nstead of pan_idle for these ioctls. Change-Id: Iefb6cbc390d2130926fdcb93688b4d92bfb26937 Signed-off-by: Ken Zhang Signed-off-by: Neti Ravi Kumar --- drivers/video/msm/mdss/mdss_fb.c | 60 ++++++++++++++++---- drivers/video/msm/mdss/mdss_fb.h | 3 + drivers/video/msm/mdss/mdss_mdp_intf_video.c | 2 + drivers/video/msm/mdss/mdss_mdp_overlay.c | 5 ++ 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index b769dcbf4e3..1927fe2d9ce 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -1288,6 +1288,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) atomic_set(&mfd->mdp_sync_pt_data.commit_cnt, 0); atomic_set(&mfd->commits_pending, 0); atomic_set(&mfd->ioctl_ref_cnt, 0); + atomic_set(&mfd->kickoff_pending, 0); init_timer(&mfd->no_update.timer); mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb; @@ -1301,6 +1302,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) init_waitqueue_head(&mfd->commit_wait_q); init_waitqueue_head(&mfd->idle_wait_q); init_waitqueue_head(&mfd->ioctl_q); + init_waitqueue_head(&mfd->kickoff_wait_q); ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) @@ -1703,6 +1705,25 @@ static int mdss_fb_pan_idle(struct msm_fb_data_type *mfd) return 0; } +static int mdss_fb_wait_for_kickoff(struct msm_fb_data_type *mfd) +{ + int ret = 0; + + ret = wait_event_timeout(mfd->kickoff_wait_q, + (!atomic_read(&mfd->kickoff_pending) || + mfd->shutdown_pending), + msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT / 2)); + if (!ret) { + pr_err("wait for kickoff timeout %d pending=%d\n", + ret, atomic_read(&mfd->kickoff_pending)); + + } else if (mfd->shutdown_pending) { + pr_debug("Shutdown signalled\n"); + return -EPERM; + } + + return 0; +} static int mdss_fb_pan_display_ex(struct fb_info *info, struct mdp_display_commit *disp_commit) @@ -1741,6 +1762,7 @@ static int mdss_fb_pan_display_ex(struct fb_info *info, atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt); atomic_inc(&mfd->commits_pending); + atomic_inc(&mfd->kickoff_pending); wake_up_all(&mfd->commit_wait_q); mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); if (wait_for_finish) @@ -1833,6 +1855,8 @@ static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd) if (ret) pr_err("pan display failed %x on fb%d\n", ret, mfd->index); + atomic_set(&mfd->kickoff_pending, 0); + wake_up_all(&mfd->kickoff_wait_q); } if (!ret) mdss_fb_update_backlight(mfd); @@ -1869,6 +1893,7 @@ static int __mdss_fb_display_thread(void *data) } atomic_set(&mfd->commits_pending, 0); + atomic_set(&mfd->kickoff_pending, 0); wake_up_all(&mfd->idle_wait_q); return ret; @@ -2328,6 +2353,27 @@ static int mdss_fb_display_commit(struct fb_info *info, return ret; } +static int __ioctl_wait_idle(struct msm_fb_data_type *mfd, u32 cmd) +{ + int ret = 0; + + if (mfd->wait_for_kickoff && + ((cmd == MSMFB_OVERLAY_PREPARE) || + (cmd == MSMFB_BUFFER_SYNC) || + (cmd == MSMFB_OVERLAY_SET))) { + ret = mdss_fb_wait_for_kickoff(mfd); + } else if ((cmd != MSMFB_VSYNC_CTRL) && + (cmd != MSMFB_OVERLAY_VSYNC_CTRL) && + (cmd != MSMFB_ASYNC_BLIT) && + (cmd != MSMFB_BLIT) && + (cmd != MSMFB_NOTIFY_UPDATE)) { + ret = mdss_fb_pan_idle(mfd); + } + + if (ret) + pr_debug("Shutdown pending. Aborting operation %x\n", cmd); + return ret; +} static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) @@ -2353,17 +2399,9 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd, mdss_fb_power_setting_idle(mfd); - if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL) && - (cmd != MSMFB_ASYNC_BLIT) && (cmd != MSMFB_BLIT) && - (cmd != MSMFB_NOTIFY_UPDATE) && - (cmd != MSMFB_OVERLAY_PREPARE)) { - ret = mdss_fb_pan_idle(mfd); - if (ret) { - pr_debug("Shutdown pending. Aborting operation %x\n", - cmd); - goto exit; - } - } + ret = __ioctl_wait_idle(mfd, cmd); + if (ret) + goto exit; switch (cmd) { case MSMFB_CURSOR: diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h index 7c47a3e2f32..febd2537bbe 100644 --- a/drivers/video/msm/mdss/mdss_fb.h +++ b/drivers/video/msm/mdss/mdss_fb.h @@ -214,8 +214,10 @@ struct msm_fb_data_type { /* for non-blocking */ struct task_struct *disp_thread; atomic_t commits_pending; + atomic_t kickoff_pending; wait_queue_head_t commit_wait_q; wait_queue_head_t idle_wait_q; + wait_queue_head_t kickoff_wait_q; bool shutdown_pending; struct task_struct *splash_thread; @@ -230,6 +232,7 @@ struct msm_fb_data_type { u32 dcm_state; struct list_head proc_list; + u32 wait_for_kickoff; }; static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd) diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c index a9595a1fabf..e41bd49fb8a 100644 --- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c +++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c @@ -446,8 +446,10 @@ static int mdss_mdp_video_wait4comp(struct mdss_mdp_ctl *ctl, void *arg) if (ctx->polling_en) { rc = mdss_mdp_video_pollwait(ctl); } else { + mutex_unlock(&ctl->lock); rc = wait_for_completion_timeout(&ctx->vsync_comp, usecs_to_jiffies(VSYNC_TIMEOUT_US)); + mutex_lock(&ctl->lock); if (rc == 0) { pr_warn("vsync wait timeout %d, fallback to poll mode\n", ctl->num); diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 70b266d1a8e..677389a3d3e 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -1146,14 +1146,18 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, else ret = mdss_mdp_display_commit(mdp5_data->ctl, NULL); + atomic_set(&mfd->kickoff_pending, 0); + wake_up_all(&mfd->kickoff_wait_q); mutex_unlock(&mfd->lock); if (IS_ERR_VALUE(ret)) goto commit_fail; + mutex_unlock(&mdp5_data->ov_lock); mdss_mdp_overlay_update_pm(mdp5_data); ret = mdss_mdp_display_wait4comp(mdp5_data->ctl); + mutex_lock(&mdp5_data->ov_lock); if (ret == 0) { mutex_lock(&mfd->lock); @@ -3140,6 +3144,7 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) goto init_fail; } mfd->mdp.private1 = mdp5_data; + mfd->wait_for_kickoff = true; rc = mdss_mdp_overlay_fb_parse_dt(mfd); if (rc)