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

Commit d122742c 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: delay iommu mapping of buffers until commit"

parents 613a988d ab393a46
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -636,8 +636,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
@@ -296,8 +296,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;
};
@@ -720,11 +722,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);
@@ -886,9 +883,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