mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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:
parent
d821dcad2c
commit
fc72ce5619
4 changed files with 37 additions and 21 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue