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

Commit ff76cdcc authored by Veera Sundaram Sankaran's avatar Veera Sundaram Sankaran Committed by Ray Zhang
Browse files

disp: msm: sde: fix handling the missing pp-done interrupt cases



With posted-start, ctl scheduler status and pending-kickoff
count are checked to address the missing pp-done interrupt
cases, which can occur if the IRQs are disabled for a long
time by some entity. Currently this check is done after
the wr-ptr-irq. At this point the scheduler status may
or may not be idle, based on the frame-transfer. Move this
handling after the timeout, so the scheduler is guaranteed
to be in idle state for working use-case.

Change-Id: I3fa9ecce8139ff667c1882e286571169c543c797
Signed-off-by: default avatarVeera Sundaram Sankaran <veeras@codeaurora.org>
Signed-off-by: default avatarRay Zhang <rayz@codeaurora.org>
Signed-off-by: default avatarBruce Hoo <bingchua@codeaurora.org>
parent 1cb8e403
Loading
Loading
Loading
Loading
+42 −14
Original line number Diff line number Diff line
@@ -663,38 +663,60 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx(
	return false;
}

static int _sde_encoder_phys_cmd_wait_for_idle(
static bool _sde_encoder_phys_cmd_is_scheduler_idle(
		struct sde_encoder_phys *phys_enc)
{
	bool wr_ptr_wait_success = true;
	unsigned long lock_flags;
	bool ret = false;
	struct sde_encoder_phys_cmd *cmd_enc =
			to_sde_encoder_phys_cmd(phys_enc);
	struct sde_encoder_wait_info wait_info;
	bool recovery_events;
	int ret;
	struct sde_hw_ctl *ctl;
	bool wr_ptr_wait_success = true;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}

	ctl = phys_enc->hw_ctl;
	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;

	if (sde_encoder_phys_cmd_is_master(phys_enc))
		wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;

	/*
	 * Handle cases where a pp-done interrupt is missed
	 * due to irq latency with POSTED start
	 */
	if (wr_ptr_wait_success &&
	  (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
	  ctl->ops.get_scheduler_status &&
	  (ctl->ops.get_scheduler_status(ctl) & BIT(0)) &&
	  atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) &&
	  phys_enc->parent_ops.handle_frame_done) {

		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
		phys_enc->parent_ops.handle_frame_done(
			phys_enc->parent, phys_enc,
			SDE_ENCODER_FRAME_EVENT_DONE |
			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
		return 0;
		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);

		SDE_EVT32(DRMID(phys_enc->parent),
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			atomic_read(&phys_enc->pending_kickoff_cnt));

			ret = true;
	}

	return ret;
}

static int _sde_encoder_phys_cmd_wait_for_idle(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_cmd *cmd_enc =
			to_sde_encoder_phys_cmd(phys_enc);
	struct sde_encoder_wait_info wait_info = {NULL};
	bool recovery_events;
	int ret;

	if (!phys_enc) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}

	if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1)
@@ -710,9 +732,15 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
	if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
		return 0;

	if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
		return 0;

	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
			&wait_info);
	if (ret == -ETIMEDOUT) {
		if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
			return 0;

		_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc,
				recovery_events);
	} else if (!ret) {