From 77e93ca69cc4ac642e39193bfd35dbdf0bfd32d0 Mon Sep 17 00:00:00 2001 From: Vishnuvardhan Prodduturi Date: Sat, 14 Sep 2013 15:42:42 +0530 Subject: [PATCH] msm: msm_fb: wait for VSYNC instead of DMA_P for commit completion. In the current implementation, we are waiting for DMA_P interrupt in commit call to signal completion. This can cause 2 commits happening in the same vsync period due to which IOMMU page faults can happen when vsync comes while second commit is programming resgisters. To avoid this, wait for DMA_P is replaced by wait for VSYNC. Change-Id: I68d4d4b4e7a574f86faecd5b4812e1f5852f4209 Signed-off-by: Vishnuvardhan Prodduturi --- drivers/video/msm/mdp4_overlay_dsi_video.c | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c index 968e67f0fcd5..2907074bab98 100644 --- a/drivers/video/msm/mdp4_overlay_dsi_video.c +++ b/drivers/video/msm/mdp4_overlay_dsi_video.c @@ -66,6 +66,7 @@ static struct vsycn_ctrl { struct vsync_update vlist[2]; int vsync_irq_enabled; ktime_t vsync_time; + wait_queue_head_t wait_queue_internal; wait_queue_head_t wait_queue; } vsync_ctrl_db[MAX_CONTROLLER]; @@ -266,10 +267,6 @@ int mdp4_dsi_video_pipe_commit(int cndx, int wait) /* kickoff overlay engine */ mdp4_stat.kickoff_ov0++; outpdw(MDP_BASE + 0x0004, 0); - } else { - /* schedule second phase update at dmap */ - INIT_COMPLETION(vctrl->dmap_comp); - vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM); } spin_unlock_irqrestore(&vctrl->spin_lock, flags); @@ -279,7 +276,7 @@ int mdp4_dsi_video_pipe_commit(int cndx, int wait) if (pipe->ov_blt_addr) mdp4_dsi_video_wait4ov(0); else - mdp4_dsi_video_wait4dmap(0); + mdp4_dsi_video_wait4vsync(0); } return cnt; @@ -329,8 +326,9 @@ void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable) void mdp4_dsi_video_wait4vsync(int cndx) { struct vsycn_ctrl *vctrl; - struct mdp4_overlay_pipe *pipe; int ret; + ktime_t timestamp; + unsigned long flags; if (cndx >= MAX_CONTROLLER) { pr_err("%s: out or range: cndx=%d\n", __func__, cndx); @@ -338,14 +336,16 @@ void mdp4_dsi_video_wait4vsync(int cndx) } vctrl = &vsync_ctrl_db[cndx]; - pipe = vctrl->base_pipe; - if (atomic_read(&vctrl->suspend) > 0) return; + spin_lock_irqsave(&vctrl->spin_lock, flags); + timestamp = vctrl->vsync_time; + spin_unlock_irqrestore(&vctrl->spin_lock, flags); mdp4_video_vsync_irq_ctrl(cndx, 1); - ret = wait_event_interruptible_timeout(vctrl->wait_queue, 1, + ret = wait_event_timeout(vctrl->wait_queue_internal, + !ktime_equal(timestamp, vctrl->vsync_time), msecs_to_jiffies(VSYNC_PERIOD * 8)); if (ret <= 0) @@ -417,10 +417,14 @@ ssize_t mdp4_dsi_video_show_event(struct device *dev, ssize_t ret = 0; u64 vsync_tick; ktime_t timestamp; + unsigned long flags; cndx = 0; vctrl = &vsync_ctrl_db[0]; + + spin_lock_irqsave(&vctrl->spin_lock, flags); timestamp = vctrl->vsync_time; + spin_unlock_irqrestore(&vctrl->spin_lock, flags); ret = wait_event_interruptible(vctrl->wait_queue, !ktime_equal(timestamp, vctrl->vsync_time) && @@ -428,7 +432,10 @@ ssize_t mdp4_dsi_video_show_event(struct device *dev, if (ret == -ERESTARTSYS) return ret; + spin_lock_irqsave(&vctrl->spin_lock, flags); vsync_tick = ktime_to_ns(vctrl->vsync_time); + spin_unlock_irqrestore(&vctrl->spin_lock, flags); + ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick); buf[strlen(buf) + 1] = '\0'; return ret; @@ -456,6 +463,7 @@ void mdp4_dsi_vsync_init(int cndx) init_completion(&vctrl->ov_comp); atomic_set(&vctrl->suspend, 1); spin_lock_init(&vctrl->spin_lock); + init_waitqueue_head(&vctrl->wait_queue_internal); init_waitqueue_head(&vctrl->wait_queue); } @@ -977,6 +985,7 @@ void mdp4_primary_vsync_dsi_video(void) spin_lock(&vctrl->spin_lock); vctrl->vsync_time = ktime_get(); + wake_up_all(&vctrl->wait_queue_internal); wake_up_interruptible_all(&vctrl->wait_queue); spin_unlock(&vctrl->spin_lock); }