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

Commit ab393a46 authored by Adrian Salido-Moreno's avatar Adrian Salido-Moreno
Browse files

msm: mdss: delay iommu mapping of buffers until commit



Currently iommu map call is done in client's context during overlay
play, this requires iommu attachment to correctly map buffers.
This mapping can be delayed until the actual commit and avoid
unnecessary delays in client's context. Also, only unmap buffers if they
have been mapped, instead of checking if iommu is attached.

Change-Id: I6b26acb3ed843f03b42df1386ee7bdd412365aff
Signed-off-by: default avatarAdrian Salido-Moreno <adrianm@codeaurora.org>
parent e4b5be8f
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -635,8 +635,11 @@ int mdss_iommu_ctrl(int enable)
		__builtin_return_address(0), enable, mdata->iommu_ref_cnt);

	if (enable) {

		if (mdata->iommu_ref_cnt == 0)
		/*
		 * delay iommu attach until continous splash screen has
		 * finished handoff, as it may still be working with phys addr
		 */
		if (!mdata->iommu_attached && !mdata->handoff_pending)
			rc = mdss_iommu_attach(mdata);
		mdata->iommu_ref_cnt++;
	} else {
+7 −8
Original line number Diff line number Diff line
@@ -290,8 +290,10 @@ struct mdss_mdp_plane_sizes {
struct mdss_mdp_img_data {
	dma_addr_t addr;
	unsigned long len;
	u32 offset;
	u32 flags;
	int p_need;
	bool mapped;
	struct file *srcp_file;
	struct ion_handle *srcp_ihdl;
};
@@ -705,11 +707,6 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
			       struct mdp_overlay *req,
			       struct mdss_mdp_format_params *fmt);
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
			     struct mdss_mdp_data *data,
			     struct msmfb_data *planes,
			     int num_planes,
			     u32 flags);
int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
	struct mdp_overlay *req, struct mdss_mdp_pipe **ppipe,
	struct mdss_mdp_pipe *left_blend_pipe, bool is_single_layer);
@@ -871,9 +868,11 @@ int mdss_mdp_get_rau_strides(u32 w, u32 h, struct mdss_mdp_format_params *fmt,
void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
	struct mdss_mdp_plane_sizes *ps, struct mdss_mdp_format_params *fmt);
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data);
int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
		int num_planes, u32 flags);
int mdss_mdp_data_map(struct mdss_mdp_data *data);
void mdss_mdp_data_free(struct mdss_mdp_data *data);

u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);
void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
+39 −69
Original line number Diff line number Diff line
@@ -969,61 +969,6 @@ static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
	return ret;
}

int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
					   struct mdss_mdp_data *data,
					   struct msmfb_data *planes,
					   int num_planes,
					   u32 flags)
{
	int i, rc;

	if ((num_planes <= 0) || (num_planes > MAX_PLANES))
		return -EINVAL;

	rc = mdss_iommu_ctrl(1);
	if (IS_ERR_VALUE(rc)) {
		pr_err("Iommu attach failed\n");
		goto end;
	}

	memset(data, 0, sizeof(*data));
	for (i = 0; i < num_planes; i++) {
		data->p[i].flags = flags;
		rc = mdss_mdp_get_img(&planes[i], &data->p[i]);
		if (rc) {
			pr_err("failed to map buf p=%d flags=%x\n", i, flags);
			while (i > 0) {
				i--;
				mdss_mdp_put_img(&data->p[i]);
			}
			break;
		}
	}

	mdss_iommu_ctrl(0);
	data->num_planes = i;
end:
	return rc;
}

int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
{
	int i, rc;

	rc = mdss_iommu_ctrl(1);
	if (IS_ERR_VALUE(rc)) {
		pr_err("Iommu attach failed\n");
		return rc;
	}

	for (i = 0; i < data->num_planes && data->p[i].len; i++)
		mdss_mdp_put_img(&data->p[i]);

	mdss_iommu_ctrl(0);
	data->num_planes = 0;
	return 0;
}

/**
 * __mdss_mdp_overlay_free_list_purge() - clear free list of buffers
 * @mfd:	Msm frame buffer data structure for the associated fb
@@ -1037,7 +982,7 @@ static void __mdss_mdp_overlay_free_list_purge(struct msm_fb_data_type *mfd)

	pr_debug("purging fb%d free list\n", mfd->index);
	for (i = 0; i < mdp5_data->free_list_size; i++)
		mdss_mdp_overlay_free_buf(&mdp5_data->free_list[i]);
		mdss_mdp_data_free(&mdp5_data->free_list[i]);
	mdp5_data->free_list_size = 0;
}

@@ -1115,10 +1060,10 @@ static void mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
		 * soon as session is closed.
		 */
		if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)
			mdss_mdp_overlay_free_buf(&pipe->front_buf);
			mdss_mdp_data_free(&pipe->front_buf);
		else
			__mdss_mdp_overlay_free_list_add(mfd, &pipe->front_buf);
		mdss_mdp_overlay_free_buf(&pipe->back_buf);
		mdss_mdp_data_free(&pipe->back_buf);
		list_del_init(&pipe->list);
		if (recovery_mode) {
			mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
@@ -1186,6 +1131,15 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd)
			mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
		mdss_mdp_release_splash_pipe(mfd);
		return 0;
	} else if (mfd->panel_info->cont_splash_enabled) {
		mutex_lock(&mdp5_data->list_lock);
		rc = list_empty(&mdp5_data->pipes_used);
		mutex_unlock(&mdp5_data->list_lock);
		if (rc) {
			pr_debug("empty kickoff on fb%d during cont splash\n",
					mfd->index);
			return 0;
		}
	}

	pr_debug("starting fb%d overlay\n", mfd->index);
@@ -1321,6 +1275,8 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)

		if (pipe->back_buf.num_planes) {
			buf = &pipe->back_buf;

			ret = mdss_mdp_data_map(buf);
		} else if (!pipe->params_changed) {
			continue;
		} else if (pipe->front_buf.num_planes) {
@@ -1331,7 +1287,9 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
			buf = NULL;
		}

		if (!IS_ERR_VALUE(ret))
			ret = mdss_mdp_pipe_queue_data(pipe, buf);

		if (IS_ERR_VALUE(ret)) {
			pr_warn("Unable to queue data for pnum=%d\n",
					pipe->num);
@@ -1403,6 +1361,23 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
	}

	mutex_lock(&mdp5_data->ov_lock);
	ret = mdss_mdp_overlay_start(mfd);
	if (ret) {
		pr_err("unable to start overlay %d (%d)\n", mfd->index, ret);
		mutex_unlock(&mdp5_data->ov_lock);
		if (ctl->shared_lock)
			mutex_unlock(ctl->shared_lock);
		return ret;
	}

	ret = mdss_iommu_ctrl(1);
	if (IS_ERR_VALUE(ret)) {
		pr_err("iommu attach failed rc=%d\n", ret);
		mutex_unlock(&mdp5_data->ov_lock);
		if (ctl->shared_lock)
			mutex_unlock(ctl->shared_lock);
		return ret;
	}
	mutex_lock(&mdp5_data->list_lock);

	/*
@@ -1523,7 +1498,9 @@ commit_fail:
	mutex_unlock(&mdp5_data->ov_lock);
	if (ctl->shared_lock)
		mutex_unlock(ctl->shared_lock);
	mdss_iommu_ctrl(0);
	ATRACE_END(__func__);

	return ret;
}

@@ -1722,13 +1699,12 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
	if (src_data->num_planes) {
		pr_warn("dropped buffer pnum=%d play=%d addr=0x%pa\n",
			pipe->num, pipe->play_cnt, &src_data->p[0].addr);
		mdss_mdp_overlay_free_buf(src_data);
		mdss_mdp_data_free(src_data);
	}

	ret = mdss_mdp_overlay_get_buf(mfd, src_data, &req->data, 1, flags);
	if (IS_ERR_VALUE(ret)) {
	ret = mdss_mdp_data_get(src_data, &req->data, 1, flags);
	if (IS_ERR_VALUE(ret))
		pr_err("src_data pmem error\n");
	}

	mdss_mdp_pipe_unmap(pipe);

@@ -1752,12 +1728,6 @@ static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
		goto done;
	}

	ret = mdss_mdp_overlay_start(mfd);
	if (ret) {
		pr_err("unable to start overlay %d (%d)\n", mfd->index, ret);
		goto done;
	}

	if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
		ret = mdss_mdp_rotator_play(mfd, req);
	} else if (req->id == BORDERFILL_NDX) {
+26 −9
Original line number Diff line number Diff line
@@ -730,33 +730,48 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
	if (!rot) {
		pr_err("invalid session id=%x\n", req->id);
		ret = -ENOENT;
		goto dst_buf_fail;
		goto session_fail;
	}

	memset(&src_buf, 0, sizeof(struct mdss_mdp_data));

	flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;

	mdss_iommu_ctrl(1);
	ret = mdss_mdp_rotator_busy_wait_ex(rot);
	if (ret) {
		pr_err("rotator busy wait error\n");
		goto dst_buf_fail;
	}

	ret = mdss_mdp_overlay_get_buf(mfd, &src_buf, &req->data, 1, flgs);
	ret = mdss_mdp_data_get(&src_buf, &req->data, 1, flgs);
	if (ret) {
		pr_err("src_data pmem error\n");
		mdss_mdp_overlay_free_buf(&rot->src_buf);
		goto dst_buf_fail;
	}
	mdss_mdp_overlay_free_buf(&rot->src_buf);

	ret = mdss_mdp_data_map(&src_buf);
	if (ret) {
		pr_err("unable to map source buffer\n");
		mdss_mdp_data_free(&src_buf);
		goto dst_buf_fail;
	}
	mdss_mdp_data_free(&rot->src_buf);
	memcpy(&rot->src_buf, &src_buf, sizeof(struct mdss_mdp_data));

	mdss_mdp_overlay_free_buf(&rot->dst_buf);
	ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
			&req->dst_data, 1, flgs);
	mdss_mdp_data_free(&rot->dst_buf);
	ret = mdss_mdp_data_get(&rot->dst_buf, &req->dst_data, 1, flgs);
	if (ret) {
		pr_err("dst_data pmem error\n");
		mdss_mdp_data_free(&rot->src_buf);
		goto dst_buf_fail;
	}

	ret = mdss_mdp_data_map(&rot->dst_buf);
	if (ret) {
		pr_err("unable to map destination buffer\n");
		mdss_mdp_data_free(&rot->dst_buf);
		mdss_mdp_data_free(&rot->src_buf);
		goto dst_buf_fail;
	}

@@ -766,6 +781,8 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
		pr_err("rotator queue error session id=%x\n", req->id);

dst_buf_fail:
	mdss_iommu_ctrl(0);
session_fail:
	mutex_unlock(&rotator_lock);
	return ret;
}
@@ -777,8 +794,8 @@ int mdss_mdp_rotator_unset(int ndx)
	mutex_lock(&rotator_lock);
	rot = mdss_mdp_rotator_session_get(ndx);
	if (rot) {
		mdss_mdp_overlay_free_buf(&rot->src_buf);
		mdss_mdp_overlay_free_buf(&rot->dst_buf);
		mdss_mdp_data_free(&rot->src_buf);
		mdss_mdp_data_free(&rot->dst_buf);

		rot->pid = 0;
		ret = mdss_mdp_rotator_finish(rot);
+112 −12
Original line number Diff line number Diff line
@@ -496,7 +496,7 @@ void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
	}
}

int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
static int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
{
	struct ion_client *iclient = mdss_get_ionclient();
	if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
@@ -513,7 +513,7 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
			pr_err("invalid ion client\n");
			return -ENOMEM;
		} else {
			if (is_mdss_iommu_attached()) {
			if (data->mapped) {
				int domain;
				if (data->flags & MDP_SECURE_OVERLAY_SESSION)
					domain = MDSS_IOMMU_DOMAIN_SECURE;
@@ -526,6 +526,7 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
					msm_ion_unsecure_buffer(iclient,
							data->srcp_ihdl);
				}
				data->mapped = false;
			}
			ion_free(iclient, data->srcp_ihdl);
			data->srcp_ihdl = NULL;
@@ -538,7 +539,8 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
	return 0;
}

int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
static int mdss_mdp_get_img(struct msmfb_data *img,
		struct mdss_mdp_img_data *data)
{
	struct file *file;
	int ret = -EINVAL;
@@ -551,6 +553,7 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
	len = &data->len;
	data->flags |= img->flags;
	data->p_need = 0;
	data->offset = img->offset;

	if (img->flags & MDP_BLIT_SRC_GEM) {
		data->srcp_file = NULL;
@@ -582,7 +585,43 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
			data->srcp_ihdl = NULL;
			return ret;
		}
		data->addr = 0;
		data->len = 0;
		data->mapped = false;
		/* return early, mapping will be done later */

		return 0;
	}

	if (!*start) {
		pr_err("start address is zero!\n");
		mdss_mdp_put_img(data);
		return -ENOMEM;
	}

	if (!ret && (data->offset < data->len)) {
		data->addr += data->offset;
		data->len -= data->offset;

		pr_debug("mem=%d ihdl=%p buf=0x%pa len=0x%lu\n", img->memory_id,
			 data->srcp_ihdl, &data->addr, data->len);
	} else {
		mdss_mdp_put_img(data);
		return ret ? : -EOVERFLOW;
	}

	return ret;
}

static int mdss_mdp_map_buffer(struct mdss_mdp_img_data *data)
{
	int ret = -EINVAL;
	struct ion_client *iclient = mdss_get_ionclient();

	if (data->addr && data->len)
		return 0;

	if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
		if (is_mdss_iommu_attached()) {
			int domain;
			if (data->flags & MDP_SECURE_OVERLAY_SESSION) {
@@ -601,13 +640,16 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)

			ret = ion_map_iommu(iclient, data->srcp_ihdl,
						mdss_get_iommu_domain(domain),
					    0, SZ_4K, 0, start, len, 0, 0);
						0, SZ_4K, 0, &data->addr,
						&data->len, 0, 0);
			if (ret && (domain == MDSS_IOMMU_DOMAIN_SECURE))
				msm_ion_unsecure_buffer(iclient,
						data->srcp_ihdl);

			data->mapped = true;
		} else {
			ret = ion_phys(iclient, data->srcp_ihdl, start,
				       (size_t *) len);
			ret = ion_phys(iclient, data->srcp_ihdl,
					&data->addr, (size_t *) &data->len);
		}

		if (IS_ERR_VALUE(ret)) {
@@ -617,17 +659,17 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
		}
	}

	if (!*start) {
	if (!data->addr) {
		pr_err("start address is zero!\n");
		mdss_mdp_put_img(data);
		return -ENOMEM;
	}

	if (!ret && (img->offset < data->len)) {
		data->addr += img->offset;
		data->len -= img->offset;
	if (!ret && (data->offset < data->len)) {
		data->addr += data->offset;
		data->len -= data->offset;

		pr_debug("mem=%d ihdl=%p buf=0x%pa len=%lu\n", img->memory_id,
		pr_debug("ihdl=%p buf=0x%pa len=0x%lu\n",
			 data->srcp_ihdl, &data->addr, data->len);
	} else {
		mdss_mdp_put_img(data);
@@ -637,6 +679,64 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data)
	return ret;
}

int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
		int num_planes, u32 flags)
{
	int i, rc = 0;

	if ((num_planes <= 0) || (num_planes > MAX_PLANES))
		return -EINVAL;

	for (i = 0; i < num_planes; i++) {
		data->p[i].flags = flags;
		rc = mdss_mdp_get_img(&planes[i], &data->p[i]);
		if (rc) {
			pr_err("failed to get buf p=%d flags=%x\n", i, flags);
			while (i > 0) {
				i--;
				mdss_mdp_put_img(&data->p[i]);
			}
			break;
		}
	}

	data->num_planes = i;

	return rc;
}

int mdss_mdp_data_map(struct mdss_mdp_data *data)
{
	int i, rc = 0;

	if (!data || !data->num_planes)
		return -EINVAL;

	for (i = 0; i < data->num_planes; i++) {
		rc = mdss_mdp_map_buffer(&data->p[i]);
		if (rc) {
			pr_err("failed to map buf p=%d\n", i);
			while (i > 0) {
				i--;
				mdss_mdp_put_img(&data->p[i]);
			}
			break;
		}
	}

	return rc;
}

void mdss_mdp_data_free(struct mdss_mdp_data *data)
{
	int i;

	for (i = 0; i < data->num_planes && data->p[i].len; i++)
		mdss_mdp_put_img(&data->p[i]);

	data->num_planes = 0;
}

int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase)
{
	u32 unit, residue, result;
Loading