summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@codeaurora.org>2016-01-29 15:07:38 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:17:48 -0700
commit7dc5ab26693e259a737825904a425a004f5112e6 (patch)
tree96f4a9802542078ce54ab8ba812321e581c640dd /drivers/video/fbdev
parent6b236392b5b94390c4e11ef8f59a4c03be5bf586 (diff)
msm: mdss: fix race condition between vsync handler and ctl_stop
The ctl_stop and vsync_handler both can run in two different threads. That can lead to race condition in vsync handler. -> Core 0: vsync handler thread checks the ctl power status and get preempted by other priority task. -> Core 1: processes the ctl_stop and power off the display device. -> Core 0: Vsync handler task gets chance to run again and tries to access the ctl->op members. The third step leads to invalid structure member access because display is already powered off. This race condition should be fixed by moving all power state checks inside mutex lock. Change-Id: I452c9026074acda2d00954e530fc491d395f106b Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index f81c4b612656..7e09b080edf6 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2620,27 +2620,35 @@ int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
if (!ctl)
return -ENODEV;
- if (!ctl->ops.add_vsync_handler || !ctl->ops.remove_vsync_handler)
- return -EOPNOTSUPP;
+
+ mutex_lock(&mdp5_data->ov_lock);
+ if (!ctl->ops.add_vsync_handler || !ctl->ops.remove_vsync_handler) {
+ rc = -EOPNOTSUPP;
+ pr_err_once("fb%d vsync handlers are not registered\n",
+ mfd->index);
+ goto end;
+ }
+
if (!ctl->panel_data->panel_info.cont_splash_enabled
&& (!mdss_mdp_ctl_is_power_on(ctl) ||
mdss_panel_is_power_on_ulp(ctl->power_state))) {
- pr_debug("fb%d vsync pending first update en=%d\n",
- mfd->index, en);
- return -EPERM;
+ pr_debug("fb%d vsync pending first update en=%d, ctl power state:%d\n",
+ mfd->index, en, ctl->power_state);
+ rc = -EPERM;
+ goto end;
}
pr_debug("fb%d vsync en=%d\n", mfd->index, en);
- mutex_lock(&mdp5_data->ov_lock);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
if (en)
rc = ctl->ops.add_vsync_handler(ctl, &ctl->vsync_handler);
else
rc = ctl->ops.remove_vsync_handler(ctl, &ctl->vsync_handler);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
- mutex_unlock(&mdp5_data->ov_lock);
+end:
+ mutex_unlock(&mdp5_data->ov_lock);
return rc;
}