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;