diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 6e2ccc83f544..82fcda763fbf 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -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); } diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 42a66dd77cbd..7f81fa32b8c2 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -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; diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index b5419ca127eb..c9659c3b934d 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -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; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 88656c827195..5a05661c1b93 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -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); diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 8e62d49817ea..a610cb92f8b5 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -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; diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 658ecfa91336..426de7be12e4 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -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; }