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

Commit 3d685517 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: remove process id based refcounting from fb"

parents bca62a9b f7c46290
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
@@ -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);
@@ -2272,80 +2272,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;
	}
@@ -2356,27 +2292,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);

@@ -2395,37 +2312,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;
	}

@@ -2445,96 +2356,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;
}
@@ -2971,6 +2841,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;

@@ -3005,7 +2876,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 {
@@ -3015,7 +2886,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
@@ -516,7 +516,7 @@ struct mdss_mdp_pipe {
	struct kref kref;

	u32 play_cnt;
	int pid;
	struct file *file;
	bool is_handed_off;

	u32 flags;
@@ -966,14 +966,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;

@@ -1061,7 +1060,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;
@@ -1251,10 +1250,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;
@@ -1263,9 +1261,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);

@@ -1287,7 +1289,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;
@@ -1321,7 +1323,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 {
@@ -1382,7 +1384,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;

@@ -1404,11 +1406,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;
@@ -1446,7 +1448,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;
@@ -1472,7 +1474,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;
@@ -1509,7 +1511,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