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

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

msm: mdss: refactor ping pong completion logic



Replace completion structures with waitq and track the completion of
ping pong transfer with a single kickoff count variable. This prevents
race conditions when using completion structure and provides a cleaner
way to identify whether wait is required.

CRs-Fixed: 720541
Change-Id: Iebb8077d520649db427470fc4963d892967a920c
Signed-off-by: default avatarAdrian Salido-Moreno <adrianm@codeaurora.org>
parent 169417fe
Loading
Loading
Loading
Loading
+52 −61
Original line number Diff line number Diff line
@@ -34,8 +34,8 @@ struct mdss_mdp_cmd_ctx {
	struct mdss_mdp_ctl *ctl;
	u32 pp_num;
	u8 ref_cnt;
	struct completion pp_comp;
	struct completion stop_comp;
	wait_queue_head_t pp_waitq;
	struct list_head vsync_handlers;
	int panel_power_state;
	atomic_t koff_cnt;
@@ -332,7 +332,6 @@ static void mdss_mdp_cmd_underflow_recovery(void *data)
		atomic_dec(&ctx->koff_cnt);
		mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
						ctx->pp_num);
		complete_all(&ctx->pp_comp);
	}
	spin_unlock_irqrestore(&ctx->koff_lock, flags);
}
@@ -361,22 +360,21 @@ static void mdss_mdp_cmd_pingpong_done(void *arg)

	spin_lock(&ctx->koff_lock);
	mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
	complete_all(&ctx->pp_comp);
	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
					ctx->rdptr_enabled);

	if (atomic_read(&ctx->koff_cnt)) {
		if (atomic_dec_return(&ctx->koff_cnt)) {
	if (atomic_add_unless(&ctx->koff_cnt, -1, 0)) {
		if (atomic_read(&ctx->koff_cnt))
			pr_err("%s: too many kickoffs=%d!\n", __func__,
			       atomic_read(&ctx->koff_cnt));
			atomic_set(&ctx->koff_cnt, 0);
		}
		if (mdss_mdp_cmd_do_notifier(ctx)) {
			atomic_inc(&ctx->pp_done_cnt);
			schedule_work(&ctx->pp_done_work);
		}
	} else
		wake_up_all(&ctx->pp_waitq);
	} else {
		pr_err("%s: should not have pingpong interrupt!\n", __func__);
	}

	trace_mdp_cmd_pingpong_done(ctl, ctx->pp_num,
					atomic_read(&ctx->koff_cnt));
@@ -516,7 +514,6 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
	struct mdss_mdp_cmd_ctx *ctx;
	struct mdss_panel_data *pdata;
	unsigned long flags;
	int need_wait = 0;
	int rc = 0;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -527,11 +524,6 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)

	pdata = ctl->panel_data;

	spin_lock_irqsave(&ctx->koff_lock, flags);
	if (atomic_read(&ctx->koff_cnt) > 0)
		need_wait = 1;
	spin_unlock_irqrestore(&ctx->koff_lock, flags);

	ctl->roi_bkup.w = ctl->width;
	ctl->roi_bkup.h = ctl->height;

@@ -539,12 +531,12 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
			ctx->rdptr_enabled, ctl->roi_bkup.w,
			ctl->roi_bkup.h);

	pr_debug("%s: need_wait=%d  intf_num=%d ctx=%p\n",
			__func__, need_wait, ctl->intf_num, ctx);
	pr_debug("%s: intf_num=%d ctx=%p koff_cnt=%d\n", __func__,
			ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt));

	if (need_wait) {
		rc = wait_for_completion_timeout(
				&ctx->pp_comp, KOFF_TIMEOUT);
	rc = wait_event_timeout(ctx->pp_waitq,
			atomic_read(&ctx->koff_cnt) == 0,
			KOFF_TIMEOUT);

	trace_mdp_cmd_wait_pingpong(ctl->num,
				atomic_read(&ctx->koff_cnt));
@@ -566,7 +558,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
			rc = 1;
		}

			rc = try_wait_for_completion(&ctx->pp_comp);
		rc = atomic_read(&ctx->koff_cnt) == 0;
	}

	if (rc <= 0) {
@@ -579,14 +571,19 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
		ctx->pp_timeout_report_cnt++;
		rc = -EPERM;
		mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
		atomic_add_unless(&ctx->koff_cnt, -1, 0);
	} else {
		rc = 0;
		ctx->pp_timeout_report_cnt = 0;
	}
	}

	/* signal any pending ping pong done events */
	while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
		mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
			ctx->rdptr_enabled, rc);

	return rc;
}

@@ -668,7 +665,6 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
{
	struct mdss_mdp_ctl *sctl = NULL;
	struct mdss_mdp_cmd_ctx *ctx, *sctx = NULL;
	unsigned long flags;
	int rc;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -713,14 +709,9 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
	MDSS_XLOG(ctl->num, ctl->roi.x, ctl->roi.y, ctl->roi.w,
						ctl->roi.h);

	spin_lock_irqsave(&ctx->koff_lock, flags);
	atomic_inc(&ctx->koff_cnt);
	INIT_COMPLETION(ctx->pp_comp);
	if (sctx) {
	if (sctx)
		atomic_inc(&sctx->koff_cnt);
		INIT_COMPLETION(sctx->pp_comp);
	}
	spin_unlock_irqrestore(&ctx->koff_lock, flags);

	trace_mdp_cmd_kickoff(ctl->num, atomic_read(&ctx->koff_cnt));

@@ -952,7 +943,7 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
	ctx->ctl = ctl;
	ctx->pp_num = (is_split_dst(ctl->mfd) ? session : mixer->num);
	ctx->pp_timeout_report_cnt = 0;
	init_completion(&ctx->pp_comp);
	init_waitqueue_head(&ctx->pp_waitq);
	init_completion(&ctx->stop_comp);
	spin_lock_init(&ctx->clk_lock);
	spin_lock_init(&ctx->koff_lock);