msm_fb: display: fix dsi_busy_wait race condition
After pipe_commit() released mutex and before kickoff happens,
There has possibility that dcs command may start transmitted.
This patch add dsi_mdp_busy flag to fix this race condition.
Change-Id: I0d9a81cd0719085c91c03386117261ad3bb6b182
Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index e0d065b..10410a7 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -228,8 +228,10 @@
vctrl = &vsync_ctrl_db[cndx];
- if (atomic_read(&vctrl->suspend) > 0)
+ if (atomic_read(&vctrl->suspend)) {
+ pr_err("%s: suspended, no more pipe queue\n", __func__);
return;
+ }
mutex_lock(&vctrl->update_lock);
undx = vctrl->update_ndx;
@@ -369,7 +371,7 @@
vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
vctrl->dmap_koff++;
}
- pr_debug("%s: kickoff\n", __func__);
+ pr_debug("%s: kickoff, pid=%d\n", __func__, current->pid);
/* kickoff overlay engine */
mdp4_stat.kickoff_ov0++;
outpdw(MDP_BASE + 0x0004, 0);
@@ -639,7 +641,6 @@
vctrl->clk_enabled = 0;
vctrl->clk_control = 0;
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
- pr_debug("%s: SET_CLK_OFF\n", __func__);
/* make sure dsi link is idle */
mipi_dsi_mdp_busy_wait();
mipi_dsi_clk_cfg(0);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index f3669aa..a58010e 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -69,6 +69,8 @@
struct msm_fb_data_type *mfd;
struct msm_panel_info *pinfo;
+ pr_debug("%s+:\n", __func__);
+
mfd = platform_get_drvdata(pdev);
pinfo = &mfd->panel_info;
@@ -145,6 +147,8 @@
u32 dummy_xres, dummy_yres;
int target_type = 0;
+ pr_debug("%s+:\n", __func__);
+
mfd = platform_get_drvdata(pdev);
fbi = mfd->fbi;
var = &fbi->var;
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 152a662..bea6b4e 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -187,7 +187,8 @@
}
}
}
- pr_debug("%s: on=%d clk_cnt=%d\n", __func__, on, dsi_clk_cnt);
+ pr_debug("%s: on=%d clk_cnt=%d pid=%d\n", __func__,
+ on, dsi_clk_cnt, current->pid);
mutex_unlock(&clk_mutex);
}
@@ -1033,7 +1034,6 @@
mutex_unlock(&cmd_mutex);
}
-
void mipi_dsi_cmd_mdp_start(void)
{
unsigned long flag;
@@ -1043,6 +1043,7 @@
spin_lock_irqsave(&dsi_mdp_lock, flag);
mipi_dsi_enable_irq(DSI_MDP_TERM);
dsi_mdp_busy = TRUE;
+ INIT_COMPLETION(dsi_mdp_comp);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -1505,22 +1506,24 @@
void mipi_dsi_cmd_mdp_busy(void)
{
- u32 status;
unsigned long flags;
int need_wait = 0;
+ pr_debug("%s: start pid=%d\n",
+ __func__, current->pid);
spin_lock_irqsave(&dsi_mdp_lock, flags);
- status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
- if (status & 0x04) { /* MDP BUSY */
- INIT_COMPLETION(dsi_mdp_comp);
- need_wait = 1;
- pr_debug("%s: status=%x need_wait\n", __func__, (int)status);
- mipi_dsi_enable_irq(DSI_MDP_TERM);
- }
+ if (dsi_mdp_busy == TRUE)
+ need_wait++;
spin_unlock_irqrestore(&dsi_mdp_lock, flags);
- if (need_wait)
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ pr_debug("%s: pending pid=%d\n",
+ __func__, current->pid);
wait_for_completion(&dsi_mdp_comp);
+ }
+ pr_debug("%s: done pid=%d\n",
+ __func__, current->pid);
}
/*
@@ -1582,10 +1585,12 @@
mutex_lock(&cmd_mutex);
req = mipi_dsi_cmdlist_get();
- if (req == NULL) {
- mutex_unlock(&cmd_mutex);
- return;
- }
+
+ /* make sure dsi_cmd_mdp is idle */
+ mipi_dsi_cmd_mdp_busy();
+
+ if (req == NULL)
+ goto need_lock;
video = MIPI_INP(MIPI_DSI_BASE + 0x0000);
video &= 0x02; /* VIDEO_MODE */
@@ -1598,7 +1603,7 @@
dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
if (dsi_ctrl & 0x02) {
/* video mode, make sure dsi_cmd_mdp is busy
- * sodcs command will be txed at start of BLLP
+ * so dcs command will be txed at start of BLLP
*/
mipi_dsi_wait_for_video_eng_busy();
} else {
@@ -1617,6 +1622,11 @@
if (!video)
mipi_dsi_clk_cfg(0);
+need_lock:
+
+ if (from_mdp) /* from pipe_commit */
+ mipi_dsi_cmd_mdp_start();
+
mutex_unlock(&cmd_mutex);
}
@@ -1768,6 +1778,7 @@
mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
spin_lock(&dsi_mdp_lock);
dsi_ctrl_lock = FALSE;
+ dsi_mdp_busy = FALSE;
mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
complete(&dsi_mdp_comp);
spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index f1a197e..69ca0a3 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -470,7 +470,7 @@
cmdreq.cmds = &backlight_cmd;
cmdreq.cmds_cnt = 1;
- cmdreq.flags = 0;
+ cmdreq.flags = CMD_REQ_COMMIT;
cmdreq.rlen = 0;
cmdreq.cb = NULL;