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

Commit 923b5718 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

msm: mdss: wait for pipe free before returning busy error



Client waits for retire fence and reuse the pipe
on another display interface. This pipe is not
stagged on MDP hardware but software structures
are not updated because retire fence is signaled
first. Due scheduling priorities between two threads,
validate call from another interface may come first
and try to reuse the same pipe. MDSS driver fails
this call because software structures are not
updated with pipe status.

Ideally, driver should wait for timeout duration
to allow other interface (or software structure) to
release the pipe. This allow clients to reuse the
same pipe on multiple displays without switching
composition method.

Change-Id: I999874f38a829162de7708cf2e5b3b425c9d5f2a
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent c952020e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -567,6 +567,7 @@ struct mdss_mdp_pipe {
	u8 chroma_sample_h;
	u8 chroma_sample_v;

	wait_queue_head_t free_waitq;
	u32 frame_rate;
};

+2 −3
Original line number Diff line number Diff line
@@ -937,7 +937,6 @@ static struct mdss_mdp_pipe *__assign_pipe_for_layer(
	struct mdss_mdp_pipe *pipe;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_data_type *mdata = mfd_to_mdata(mfd);
	u32 pipe_list = 0;

	pipe = __find_used_pipe(mfd, pipe_ndx);
	*new_pipe = pipe ? false : true;
@@ -963,8 +962,8 @@ static struct mdss_mdp_pipe *__assign_pipe_for_layer(

	pipe = mdss_mdp_pipe_assign(mdata, mixer, pipe_ndx);
	if (IS_ERR_OR_NULL(pipe)) {
		pr_err("error reserving pipe. pipe_ndx=0x%x pipe_list=0x%x\n",
				pipe_ndx, pipe_list);
		pr_err("error reserving pipe. pipe_ndx=0x%x mfd ndx=%d\n",
			pipe_ndx, mfd->index);
		goto end;
	}

+2 −2
Original line number Diff line number Diff line
@@ -2336,7 +2336,7 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
	if (!mdp5_data || !mdp5_data->ctl)
		return;

	if (fbi->fix.smem_len == 0 ||
	if (IS_ERR_OR_NULL(mfd->fbmem_buf) || fbi->fix.smem_len == 0 ||
		mdp5_data->borderfill_enable) {
		mfd->mdp.kickoff_fnc(mfd, NULL);
		return;
+36 −9
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#define SMP_MB_ENTRY_SIZE	16
#define MAX_BPP 4

#define PIPE_CLEANUP_TIMEOUT_US 100000

/* following offsets are relative to ctrl register bit offset */
#define CLK_FORCE_ON_OFFSET	0x0
#define CLK_FORCE_OFF_OFFSET	0x1
@@ -958,6 +960,13 @@ static void mdss_mdp_fixed_qos_arbiter_setup(struct mdss_data_type *mdata,
	mutex_unlock(&mdata->reg_lock);
}

static void mdss_mdp_init_pipe_params(struct mdss_mdp_pipe *pipe)
{
	kref_init(&pipe->kref);
	init_waitqueue_head(&pipe->free_waitq);
	INIT_LIST_HEAD(&pipe->buf_queue);
}

static int mdss_mdp_pipe_init_config(struct mdss_mdp_pipe *pipe,
	struct mdss_mdp_mixer *mixer, bool pipe_share)
{
@@ -986,8 +995,7 @@ static int mdss_mdp_pipe_init_config(struct mdss_mdp_pipe *pipe,

	if (pipe) {
		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
		kref_init(&pipe->kref);
		INIT_LIST_HEAD(&pipe->buf_queue);
		mdss_mdp_init_pipe_params(pipe);

		is_realtime = !((mixer->ctl->intf_num == MDSS_MDP_NO_INTF)
				|| mixer->rotator_mode);
@@ -1083,8 +1091,7 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
	}

	if (pipe && type == MDSS_MDP_PIPE_TYPE_CURSOR) {
		kref_init(&pipe->kref);
		INIT_LIST_HEAD(&pipe->buf_queue);
		mdss_mdp_init_pipe_params(pipe);
		pr_debug("cursor: type=%x pnum=%d\n",
			pipe->type, pipe->num);
		goto cursor_done;
@@ -1162,6 +1169,7 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata,
{
	struct mdss_mdp_pipe *pipe = NULL;
	int rc;
	int retry_count = 0;

	if (!ndx)
		return ERR_PTR(-EINVAL);
@@ -1175,9 +1183,27 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata,
	}

	if (atomic_read(&pipe->kref.refcount) != 0) {
		pr_err("pipe is in use\n");
		mutex_unlock(&mdss_mdp_sspp_lock);
		do {
			rc = wait_event_interruptible_timeout(pipe->free_waitq,
				!atomic_read(&pipe->kref.refcount),
				usecs_to_jiffies(PIPE_CLEANUP_TIMEOUT_US));
			if (rc == 0 || retry_count == 5) {
				pr_err("pipe ndx:%d free wait failed, mfd ndx:%d rc=%d\n",
					pipe->ndx,
					pipe->mfd ? pipe->mfd->index : -1, rc);
				pipe = ERR_PTR(-EBUSY);
		goto error;
				goto end;
			} else if (rc == -ERESTARTSYS) {
				pr_debug("interrupt signal received\n");
				retry_count++;
				continue;
			} else {
				break;
			}
		} while (true);

		mutex_lock(&mdss_mdp_sspp_lock);
	}
	pipe->mixer_left = mixer;

@@ -1187,6 +1213,7 @@ struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata,

error:
	mutex_unlock(&mdss_mdp_sspp_lock);
end:
	return pipe;
}

@@ -1520,6 +1547,7 @@ int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
		return -EBUSY;
	}

	wake_up_all(&pipe->free_waitq);
	mutex_unlock(&mdss_mdp_sspp_lock);

	return 0;
@@ -1587,8 +1615,7 @@ int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe)

	pipe->is_handed_off = true;
	pipe->play_cnt = 1;
	kref_init(&pipe->kref);
	INIT_LIST_HEAD(&pipe->buf_queue);
	mdss_mdp_init_pipe_params(pipe);

error:
	return rc;