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>
(cherry picked from commit c9427ced2ab4cf1094b61360a476305066044a54)
This commit is contained in:
Kuogee Hsieh 2012-10-13 17:27:55 -07:00 committed by Stephen Boyd
parent d821dcad2c
commit fc72ce5619
4 changed files with 37 additions and 21 deletions

View file

@ -228,8 +228,10 @@ void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)
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 @@ int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
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);
@ -635,7 +637,6 @@ static void clk_ctrl_work(struct work_struct *work)
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);

View file

@ -69,6 +69,8 @@ static int mipi_dsi_off(struct platform_device *pdev)
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;
@ -147,6 +149,8 @@ static int mipi_dsi_on(struct platform_device *pdev)
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;

View file

@ -188,7 +188,8 @@ void mipi_dsi_clk_cfg(int on)
}
}
}
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);
}
@ -1034,7 +1035,6 @@ void mipi_dsi_mdp_busy_wait(void)
mutex_unlock(&cmd_mutex);
}
void mipi_dsi_cmd_mdp_start(void)
{
unsigned long flag;
@ -1044,6 +1044,7 @@ void mipi_dsi_cmd_mdp_start(void)
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);
}
@ -1508,22 +1509,24 @@ static void mipi_dsi_wait_for_video_eng_busy(void)
void mipi_dsi_cmd_mdp_busy(void)
{
u32 status;
unsigned long flags;
int need_wait;
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);
}
/*
@ -1585,10 +1588,12 @@ void mipi_dsi_cmdlist_commit(int from_mdp)
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 */
@ -1601,7 +1606,7 @@ void mipi_dsi_cmdlist_commit(int from_mdp)
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 {
@ -1620,6 +1625,11 @@ void mipi_dsi_cmdlist_commit(int from_mdp)
if (!video)
mipi_dsi_clk_cfg(0);
need_lock:
if (from_mdp) /* from pipe_commit */
mipi_dsi_cmd_mdp_start();
mutex_unlock(&cmd_mutex);
}
@ -1771,6 +1781,7 @@ irqreturn_t mipi_dsi_isr(int irq, void *ptr)
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);

View file

@ -470,7 +470,7 @@ static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
cmdreq.cmds = &backlight_cmd;
cmdreq.cmds_cnt = 1;
cmdreq.flags = 0;
cmdreq.flags = CMD_REQ_COMMIT;
cmdreq.rlen = 0;
cmdreq.cb = NULL;