msm: mdss: avoid race conditions during fb release

During fb release we should release all resources that are associated to
that process. However, in current release function this can lead to
kickoff being done, if this is done while display thread is running
there can be race condition between the updates from two different
threads. Fix this by pushing the commit through the display thread in
cases where display thread should be running, or otherwise shutdown this
thread and do it along with panel blanking.

Change-Id: I9ff6316c18adfdb67d0250a144ddc2f9f2634273
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
This commit is contained in:
Adrian Salido-Moreno 2014-10-17 12:31:47 -07:00 committed by David Keitel
parent 4cd847cf76
commit f44a833d60
2 changed files with 19 additions and 30 deletions

View file

@ -2174,7 +2174,7 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
unknown_pid = false;
pr_debug("found process %s pid=%d mfd->ref=%d pinfo->ref=%d\n",
task->comm, mfd->ref_cnt, pinfo->pid, pinfo->ref_cnt);
task->comm, pinfo->pid, mfd->ref_cnt, pinfo->ref_cnt);
proc_info = mdss_fb_release_file_entry(info, pinfo,
release_all);
@ -2199,10 +2199,6 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
pm_runtime_put(info->dev);
} while (release_all && pinfo->ref_cnt);
/* we need to stop display thread before release */
if (release_all && mfd->disp_thread)
mdss_fb_stop_disp_thread(mfd);
if (pinfo->ref_cnt == 0) {
list_del(&pinfo->list);
kfree(pinfo);
@ -2233,27 +2229,10 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
}
}
if (release_needed) {
pr_debug("current process=%s pid=%d known pid=%d mfd->ref=%d\n",
task->comm, current->tgid, pid, mfd->ref_cnt);
if (mfd->mdp.release_fnc) {
ret = mfd->mdp.release_fnc(mfd, false, pid);
if (ret)
pr_err("error releasing fb%d for current pid=%d known pid=%d\n",
mfd->index, current->tgid, pid);
}
} else if (release_all && mfd->ref_cnt) {
pr_err("reference count mismatch with proc list entries\n");
}
if (!mfd->ref_cnt) {
if (mfd->mdp.release_fnc) {
ret = mfd->mdp.release_fnc(mfd, true, pid);
if (ret)
pr_err("error fb%d release current process=%s pid=%d known pid=%d\n",
mfd->index, task->comm, current->tgid, pid);
}
if (!mfd->ref_cnt || release_all) {
/* resources (if any) will be released during blank */
if (mfd->mdp.release_fnc)
mfd->mdp.release_fnc(mfd, true, pid);
if (mfd->fb_ion_handle)
mdss_fb_free_fb_ion_memory(mfd);
@ -2266,6 +2245,17 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
return ret;
}
atomic_set(&mfd->ioctl_ref_cnt, 0);
} else if (release_needed) {
pr_debug("current process=%s pid=%d known pid=%d mfd->ref=%d\n",
task->comm, current->tgid, pid, mfd->ref_cnt);
if (mfd->mdp.release_fnc) {
ret = mfd->mdp.release_fnc(mfd, false, pid);
/* display commit is needed to release resources */
if (ret)
mdss_fb_pan_display(&mfd->fbi->var, mfd->fbi);
}
}
return ret;

View file

@ -1683,6 +1683,8 @@ done:
*
* Release any resources allocated by calling process, this can be called
* on fb_release to release any overlays/rotator sessions left open.
*
* Return number of resources released
*/
static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
bool release_all, uint32_t pid)
@ -1721,9 +1723,6 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
}
mutex_unlock(&mdp5_data->ov_lock);
if (cnt)
mfd->mdp.kickoff_fnc(mfd, NULL);
list_for_each_entry_safe(rot, tmp, &mdp5_data->rot_proc_list, list) {
if (rot->pid == pid) {
if (!list_empty(&rot->list))
@ -1732,7 +1731,7 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
}
}
return 0;
return cnt;
}
static int mdss_mdp_overlay_play_wait(struct msm_fb_data_type *mfd,