msm: mdss: remove process id based refcounting from fb

FrameBuffer driver is tracking each fb_open and fb_release
call with process id and file descriptor node. This is
duplicate logic to track single call. This change removes
process id based framebuffer driver call tracking to
reduce the complexity. File descriptor is different for
each call. That's the main reason for choosing it to
track the calls.

CRs-fixed: 716379
Change-Id: Ida1728d3878aeedf486bebef0f6f70c1e68d006e
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
Dhaval Patel 2015-03-27 19:03:33 -07:00 committed by David Keitel
parent 38be49e8b7
commit d6bf565bed
6 changed files with 71 additions and 212 deletions

View file

@ -1227,6 +1227,9 @@ static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (!info)
return -ENODEV;
mutex_lock(&info->lock);
info->file = file;
mutex_unlock(&info->lock);
return do_fb_ioctl(info, cmd, arg);
}

View file

@ -877,7 +877,7 @@ static int mdss_fb_probe(struct platform_device *pdev)
&(mfd->boot_notification_led));
}
INIT_LIST_HEAD(&mfd->proc_list);
INIT_LIST_HEAD(&mfd->file_list);
mutex_init(&mfd->bl_lock);
mutex_init(&mfd->switch_lock);
@ -2281,80 +2281,16 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
return 0;
}
/**
* mdss_fb_release_file_entry() - Releases file node entry from list
* @info: Frame buffer info
* @pinfo: Process list node in which file node entry is going to
* be removed
* @release_all: Releases all file node entries from list if this parameter
* is true
*
* This function is called to remove the file node entry/entries from main
* list. It also helps to find the process id if fb_open and fb_close
* callers are different.
*/
static struct mdss_fb_proc_info *mdss_fb_release_file_entry(
struct fb_info *info,
struct mdss_fb_proc_info *pinfo, bool release_all)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdss_fb_file_info *file_info = NULL, *temp_file_info = NULL;
struct mdss_fb_proc_info *proc_info = NULL, *temp_proc_info = NULL;
struct file *file = info->file;
bool node_found = false;
if (!pinfo && release_all) {
pr_err("process node not provided for release all case\n");
goto end;
}
if (pinfo) {
proc_info = pinfo;
list_for_each_entry_safe(file_info, temp_file_info,
&pinfo->file_list, list) {
if (!release_all && file_info->file != file)
continue;
list_del(&file_info->list);
kfree(file_info);
node_found = true;
if (!release_all)
break;
}
}
if (!node_found) {
list_for_each_entry_safe(proc_info, temp_proc_info,
&mfd->proc_list, list) {
list_for_each_entry_safe(file_info, temp_file_info,
&proc_info->file_list, list) {
if (file_info->file == file) {
list_del(&file_info->list);
kfree(file_info);
goto end;
}
}
}
}
end:
return proc_info;
}
static int mdss_fb_open(struct fb_info *info, int user)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdss_fb_proc_info *pinfo = NULL;
struct mdss_fb_file_info *file_info = NULL;
int result;
int pid = current->tgid;
struct task_struct *task = current->group_leader;
if (mfd->shutdown_pending) {
pr_err_once("Shutdown pending. Aborting operation. Request from pid:%d name=%s\n",
pid, task->comm);
current->tgid, task->comm);
sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
return -ESHUTDOWN;
}
@ -2365,27 +2301,8 @@ static int mdss_fb_open(struct fb_info *info, int user)
return -ENOMEM;
}
list_for_each_entry(pinfo, &mfd->proc_list, list) {
if (pinfo->pid == pid)
break;
}
if ((pinfo == NULL) || (pinfo->pid != pid)) {
pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL);
if (!pinfo) {
pr_err("unable to alloc process info\n");
kfree(file_info);
return -ENOMEM;
}
pinfo->pid = pid;
pinfo->ref_cnt = 0;
list_add(&pinfo->list, &mfd->proc_list);
INIT_LIST_HEAD(&pinfo->file_list);
pr_debug("new process entry pid=%d\n", pinfo->pid);
}
file_info->file = info->file;
list_add(&file_info->list, &pinfo->file_list);
list_add(&file_info->list, &mfd->file_list);
result = pm_runtime_get_sync(info->dev);
@ -2404,37 +2321,31 @@ static int mdss_fb_open(struct fb_info *info, int user)
}
}
pinfo->ref_cnt++;
mfd->ref_cnt++;
pr_debug("mfd refcount:%d file:%p\n", mfd->ref_cnt, info->file);
return 0;
blank_error:
pm_runtime_put(info->dev);
pm_error:
list_del(&file_info->list);
kfree(file_info);
if (pinfo && !pinfo->ref_cnt) {
list_del(&pinfo->list);
kfree(pinfo);
}
return result;
}
static int mdss_fb_release_all(struct fb_info *info, bool release_all)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdss_fb_proc_info *pinfo = NULL, *temp_pinfo = NULL;
struct mdss_fb_proc_info *proc_info = NULL;
struct mdss_fb_file_info *file_info = NULL, *temp_file_info = NULL;
struct file *file = info->file;
int ret = 0;
int pid = current->tgid;
bool unknown_pid = true, release_needed = false;
bool node_found = false;
struct task_struct *task = current->group_leader;
if (!mfd->ref_cnt) {
pr_info("try to close unopened fb %d! from pid:%d name:%s\n",
mfd->index, pid, task->comm);
mfd->index, current->tgid, task->comm);
return -EINVAL;
}
@ -2454,95 +2365,54 @@ static int mdss_fb_release_all(struct fb_info *info, bool release_all)
pr_debug("release_all = %s\n", release_all ? "true" : "false");
list_for_each_entry_safe(pinfo, temp_pinfo, &mfd->proc_list, list) {
if (!release_all && (pinfo->pid != pid))
list_for_each_entry_safe(file_info, temp_file_info, &mfd->file_list,
list) {
if (!release_all && file_info->file != file)
continue;
unknown_pid = false;
pr_debug("found file node mfd->ref=%d\n", mfd->ref_cnt);
list_del(&file_info->list);
kfree(file_info);
pr_debug("found process %s pid=%d mfd->ref=%d pinfo->ref=%d\n",
task->comm, pinfo->pid, mfd->ref_cnt, pinfo->ref_cnt);
mfd->ref_cnt--;
pm_runtime_put(info->dev);
proc_info = mdss_fb_release_file_entry(info, pinfo,
release_all);
/*
* if fb_release is called from different known process then
* release the ref_count of original proc_info instead of
* current process.
*/
if (!release_all && proc_info && proc_info != pinfo) {
pr_info("fb_release called from different process for current file node\n");
pinfo = proc_info;
}
do {
if (mfd->ref_cnt < pinfo->ref_cnt)
pr_warn("WARN:mfd->ref=%d < pinfo->ref=%d\n",
mfd->ref_cnt, pinfo->ref_cnt);
else
mfd->ref_cnt--;
pinfo->ref_cnt--;
pm_runtime_put(info->dev);
} while (release_all && pinfo->ref_cnt);
if (pinfo->ref_cnt == 0) {
list_del(&pinfo->list);
kfree(pinfo);
release_needed = !release_all;
}
node_found = true;
if (!release_all)
break;
}
if (unknown_pid) {
pinfo = mdss_fb_release_file_entry(info, NULL, false);
if (pinfo) {
pr_debug("found known pid=%d reference for unknown caller pid=%d\n",
pinfo->pid, pid);
pid = pinfo->pid;
mfd->ref_cnt--;
pinfo->ref_cnt--;
pm_runtime_put(info->dev);
if (!pinfo->ref_cnt) {
list_del(&pinfo->list);
kfree(pinfo);
release_needed = true;
}
} else {
WARN("unknown caller:: process %s mfd->ref=%d\n",
task->comm, mfd->ref_cnt);
}
}
if (!node_found || (release_all && mfd->ref_cnt))
pr_warn("file node not found or wrong ref cnt: release all:%d refcnt:%d\n",
release_all, mfd->ref_cnt);
pr_debug("current process=%s pid=%d mfd->ref=%d file:%p\n",
task->comm, current->tgid, mfd->ref_cnt, info->file);
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);
mfd->mdp.release_fnc(mfd, NULL);
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
mfd->op_enable);
if (ret) {
pr_err("can't turn off fb%d! rc=%d current process=%s pid=%d known pid=%d\n",
mfd->index, ret, task->comm, current->tgid, pid);
pr_err("can't turn off fb%d! rc=%d current process=%s pid=%d\n",
mfd->index, ret, task->comm, current->tgid);
return ret;
}
if (mfd->fb_ion_handle)
mdss_fb_free_fb_ion_memory(mfd);
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);
} else {
if (mfd->mdp.release_fnc)
ret = mfd->mdp.release_fnc(mfd, file);
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);
}
/* display commit is needed to release resources */
if (ret)
mdss_fb_pan_display(&mfd->fbi->var, mfd->fbi);
}
return ret;
@ -2980,6 +2850,7 @@ int mdss_fb_atomic_commit(struct fb_info *info,
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdp_layer_commit_v1 *commit_v1;
struct file *file = info->file;
bool wait_for_finish;
int ret = -EPERM;
@ -3014,7 +2885,7 @@ int mdss_fb_atomic_commit(struct fb_info *info,
} else {
__ioctl_transition_dyn_mode_state(mfd,
MSMFB_ATOMIC_COMMIT, 1);
ret = mfd->mdp.atomic_validate(mfd, commit_v1);
ret = mfd->mdp.atomic_validate(mfd, file, commit_v1);
}
goto end;
} else {
@ -3024,7 +2895,7 @@ int mdss_fb_atomic_commit(struct fb_info *info,
goto end;
}
ret = mfd->mdp.pre_commit(mfd, commit_v1);
ret = mfd->mdp.pre_commit(mfd, file, commit_v1);
if (ret) {
pr_err("atomic pre commit failed\n");
goto end;

View file

@ -188,17 +188,16 @@ struct msm_mdp_interface {
int (*on_fnc)(struct msm_fb_data_type *mfd);
int (*off_fnc)(struct msm_fb_data_type *mfd);
/* called to release resources associated to the process */
int (*release_fnc)(struct msm_fb_data_type *mfd, bool release_all,
uint32_t pid);
int (*release_fnc)(struct msm_fb_data_type *mfd, struct file *file);
int (*mode_switch)(struct msm_fb_data_type *mfd,
u32 mode);
int (*mode_switch_post)(struct msm_fb_data_type *mfd,
u32 mode);
int (*kickoff_fnc)(struct msm_fb_data_type *mfd,
struct mdp_display_commit *data);
int (*atomic_validate)(struct msm_fb_data_type *mfd,
int (*atomic_validate)(struct msm_fb_data_type *mfd, struct file *file,
struct mdp_layer_commit_v1 *commit);
int (*pre_commit)(struct msm_fb_data_type *mfd,
int (*pre_commit)(struct msm_fb_data_type *mfd, struct file *file,
struct mdp_layer_commit_v1 *commit);
int (*pre_commit_fnc)(struct msm_fb_data_type *mfd);
int (*ioctl_handler)(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
@ -234,13 +233,6 @@ struct mdss_fb_file_info {
struct list_head list;
};
struct mdss_fb_proc_info {
int pid;
u32 ref_cnt;
struct list_head file_list;
struct list_head list;
};
struct msm_fb_backup_type {
struct fb_info info;
struct mdp_display_commit disp_commit;
@ -327,7 +319,7 @@ struct msm_fb_data_type {
u32 is_power_setting;
u32 dcm_state;
struct list_head proc_list;
struct list_head file_list;
struct ion_client *fb_ion_client;
struct ion_handle *fb_ion_handle;
struct dma_buf *fbmem_buf;

View file

@ -507,7 +507,7 @@ struct mdss_mdp_pipe {
struct kref kref;
u32 play_cnt;
int pid;
struct file *file;
bool is_handed_off;
u32 flags;
@ -955,14 +955,14 @@ int mdss_mdp_secure_display_ctrl(unsigned int enable);
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *ov_commit);
struct file *file, struct mdp_layer_commit_v1 *ov_commit);
int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *ov_commit);
struct file *file, struct mdp_layer_commit_v1 *ov_commit);
int mdss_mdp_layer_atomic_validate_wfd(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *ov_commit);
struct file *file, struct mdp_layer_commit_v1 *ov_commit);
int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *ov_commit);
struct file *file, struct mdp_layer_commit_v1 *ov_commit);
int mdss_mdp_async_position_update(struct msm_fb_data_type *mfd,
struct mdp_position_update *update_pos);

View file

@ -435,7 +435,6 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pipe->mixer_left = mixer;
pipe->mfd = mfd;
pipe->pid = current->tgid;
pipe->play_cnt = 0;
pipe->flags = 0;
@ -1024,7 +1023,7 @@ static void __handle_free_list(struct mdss_overlay_private *mdp5_data,
* to find failed layer from layer_list based on "error_code".
*/
static int __validate_layers(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *commit)
struct file *file, struct mdp_layer_commit_v1 *commit)
{
int ret, i, release_ndx = 0;
u32 left_lm_layers = 0, right_lm_layers = 0;
@ -1212,10 +1211,9 @@ validate_exit:
pr_debug("err=%d total_layer:%d left:%d right:%d release_ndx=0x%x processed=%d\n",
ret, layer_count, left_lm_layers, right_lm_layers,
release_ndx, i);
if (IS_ERR_VALUE(ret)) {
mutex_lock(&mdp5_data->list_lock);
list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used,
list) {
mutex_lock(&mdp5_data->list_lock);
list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) {
if (IS_ERR_VALUE(ret)) {
if (pipe->ndx & release_ndx) {
mdss_mdp_smp_unreserve(pipe);
pipe->params_changed = 0;
@ -1224,9 +1222,13 @@ validate_exit:
list_del_init(&pipe->list);
mdss_mdp_pipe_destroy(pipe);
}
} else {
pipe->file = file;
pr_debug("file pointer attached with pipe is %p\n",
file);
}
mutex_unlock(&mdp5_data->list_lock);
}
mutex_unlock(&mdp5_data->list_lock);
end:
mutex_unlock(&mdp5_data->ov_lock);
@ -1248,7 +1250,7 @@ end:
* This function is called from client context and can return the error.
*/
int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *commit)
struct file *file, struct mdp_layer_commit_v1 *commit)
{
int ret, i;
int layer_count = commit->input_layer_cnt;
@ -1282,7 +1284,7 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
}
if (validate_failed) {
ret = __validate_layers(mfd, commit);
ret = __validate_layers(mfd, file, commit);
if (ret)
goto end;
} else {
@ -1338,7 +1340,7 @@ end:
* display.
*/
int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *commit)
struct file *file, struct mdp_layer_commit_v1 *commit)
{
struct mdss_overlay_private *mdp5_data;
@ -1360,11 +1362,11 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
return -EPERM;
}
return __validate_layers(mfd, commit);
return __validate_layers(mfd, file, commit);
}
int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *commit)
struct file *file, struct mdp_layer_commit_v1 *commit)
{
int rc, count;
struct mdss_overlay_private *mdp5_data;
@ -1402,7 +1404,7 @@ int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd,
}
}
rc = mdss_mdp_layer_pre_commit(mfd, commit);
rc = mdss_mdp_layer_pre_commit(mfd, file, commit);
if (rc) {
pr_err("fail to import input layer buffers\n");
goto input_layer_err;
@ -1428,7 +1430,7 @@ fence_get_err:
}
int mdss_mdp_layer_atomic_validate_wfd(struct msm_fb_data_type *mfd,
struct mdp_layer_commit_v1 *commit)
struct file *file, struct mdp_layer_commit_v1 *commit)
{
int rc = 0;
struct mdss_overlay_private *mdp5_data;
@ -1465,7 +1467,7 @@ int mdss_mdp_layer_atomic_validate_wfd(struct msm_fb_data_type *mfd,
goto validate_failed;
}
rc = mdss_mdp_layer_atomic_validate(mfd, commit);
rc = mdss_mdp_layer_atomic_validate(mfd, file, commit);
if (rc) {
pr_err("fail to validate the input layers = %d\n", rc);
goto validate_failed;

View file

@ -735,7 +735,6 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
mutex_unlock(&mdp5_data->list_lock);
pipe->mixer_left = mixer;
pipe->mfd = mfd;
pipe->pid = current->tgid;
pipe->play_cnt = 0;
} else {
pipe = __overlay_find_pipe(mfd, req->id);
@ -1981,7 +1980,7 @@ int mdss_mdp_overlay_release(struct msm_fb_data_type *mfd, int ndx)
unset_ndx |= pipe->ndx;
pipe->pid = 0;
pipe->file = NULL;
destroy_pipe = pipe->play_cnt == 0;
if (!destroy_pipe)
list_move(&pipe->list,
@ -2063,20 +2062,20 @@ done:
* Return number of resources released
*/
static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
bool release_all, uint32_t pid)
struct file *file)
{
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_rotator_session *rot, *tmp;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
u32 unset_ndx = 0;
int cnt = 0;
pr_debug("releasing all resources for fb%d pid=%d\n", mfd->index, pid);
pr_debug("releasing all resources for fb%d file:%p\n",
mfd->index, file);
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mdp5_data->list_lock);
list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
if (release_all || (pipe->pid == pid)) {
if (!file || pipe->file == file) {
unset_ndx |= pipe->ndx;
cnt++;
}
@ -2088,8 +2087,8 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
cnt++;
}
pr_debug("release_all=%d mfd->ref_cnt=%d unset_ndx=0x%x cnt=%d\n",
release_all, mfd->ref_cnt, unset_ndx, cnt);
pr_debug("mfd->ref_cnt=%d unset_ndx=0x%x cnt=%d\n",
mfd->ref_cnt, unset_ndx, cnt);
mutex_unlock(&mdp5_data->list_lock);
@ -2099,14 +2098,6 @@ static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
}
mutex_unlock(&mdp5_data->ov_lock);
list_for_each_entry_safe(rot, tmp, &mdp5_data->rot_proc_list, list) {
if (rot->pid == pid) {
if (!list_empty(&rot->list))
list_del_init(&rot->list);
mdss_mdp_rotator_release(rot);
}
}
return cnt;
}