Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7c46290 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

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: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 0baebc42
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
}

+35 −164
Original line number Diff line number Diff line
@@ -876,7 +876,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);
@@ -2280,80 +2280,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;
	}
@@ -2364,27 +2300,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);

@@ -2403,37 +2320,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;
	}

@@ -2453,96 +2364,55 @@ 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 process %s pid=%d mfd->ref=%d pinfo->ref=%d\n",
			task->comm, pinfo->pid, mfd->ref_cnt, pinfo->ref_cnt);

		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;
		}
		pr_debug("found file node mfd->ref=%d\n", mfd->ref_cnt);
		list_del(&file_info->list);
		kfree(file_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);

		if (mfd->mdp.release_fnc) {
			ret = mfd->mdp.release_fnc(mfd, false, pid);
	} else {
		if (mfd->mdp.release_fnc)
			ret = mfd->mdp.release_fnc(mfd, file);

		/* display commit is needed to release resources */
		if (ret)
			mdss_fb_pan_display(&mfd->fbi->var, mfd->fbi);
	}
	}

	return ret;
}
@@ -2979,6 +2849,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;

@@ -3013,7 +2884,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 {
@@ -3023,7 +2894,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;
+4 −12
Original line number Diff line number Diff line
@@ -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;
+5 −5
Original line number Diff line number Diff line
@@ -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);
+17 −15
Original line number Diff line number Diff line
@@ -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) {
	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;
Loading