From a521f8040d0397718f6dc113dbb6e57d484a3869 Mon Sep 17 00:00:00 2001 From: Dhaval Patel Date: Wed, 30 Dec 2015 15:12:35 -0800 Subject: [PATCH] msm: mdss: protect retire count with mutex lock The retire timeline counter in command mode is used by vsync worker queue, validate/commit ioctl thread and overlay off. However, this counter is not protected with any locking mechanism and each thread updates the value. Race condition with updated value between two thread can lead to invalid vsync operation or list corruption. This change protects the counter with mutex lock to avoid all such race conditions. Change-Id: Ib3c3f6c839fc82c6d31fa28066df1f23dab19746 Signed-off-by: Dhaval Patel --- drivers/video/fbdev/msm/mdss_mdp_overlay.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index ef640f4c448f..face458be16c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -4651,6 +4651,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) struct mdss_overlay_private *mdp5_data; struct mdss_mdp_mixer *mixer; int need_cleanup; + int retire_cnt; if (!mfd) return -ENODEV; @@ -4717,13 +4718,19 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) * for retire fence to be updated. * As a last resort signal the timeline if vsync doesn't arrive. */ - if (mdp5_data->retire_cnt) { + mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); + retire_cnt = mdp5_data->retire_cnt; + mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); + if (retire_cnt) { u32 fps = mdss_panel_get_framerate(mfd->panel_info); u32 vsync_time = 1000 / (fps ? : DEFAULT_FRAME_RATE); msleep(vsync_time); - __vsync_retire_signal(mfd, mdp5_data->retire_cnt); + mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); + retire_cnt = mdp5_data->retire_cnt; + mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); + __vsync_retire_signal(mfd, retire_cnt); /* * the retire work can still schedule after above retire_signal @@ -5008,10 +5015,13 @@ static int __vsync_set_vsync_handler(struct msm_fb_data_type *mfd) struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); struct mdss_mdp_ctl *ctl; int rc; + int retire_cnt; ctl = mdp5_data->ctl; - if (!mdp5_data->retire_cnt || - mdp5_data->vsync_retire_handler.enabled) + mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); + retire_cnt = mdp5_data->retire_cnt; + mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex); + if (!retire_cnt || mdp5_data->vsync_retire_handler.enabled) return 0; if (!ctl->ops.add_vsync_handler)