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

Commit 28b1be3b authored by Krishna Manikandan's avatar Krishna Manikandan
Browse files

disp: msm: sde: wait for ctl to be idle to ensure transfer complete



With posted start, transfer complete cannot be guaranteed from
esd thread context if pending kickoff count is 1. While the
wait is going on, another commit can come and increment the
kickoff count. This can lead to scenarios where we wait for
pending kickoff count to be 0 during the wait period, which
can never happen if continuous commits are coming when
posted start is enabled. Add support to wait for ctl
to be idle to ensure frame transfer complete.

Change-Id: I3f6ac9fbef4087e08fd0b5c48bb691138c6bac12
Signed-off-by: default avatarKrishna Manikandan <mkrishn@codeaurora.org>
parent dbae03d9
Loading
Loading
Loading
Loading
+47 −3
Original line number Diff line number Diff line
@@ -6039,12 +6039,41 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder,
	return ret;
}

static void sde_encoder_wait_for_ctl_idle(struct sde_encoder_virt *sde_enc)
{
	int i = 0, rc = 0;
	struct sde_encoder_phys *phys;
	struct sde_hw_ctl *ctl;

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		phys = sde_enc->phys_encs[i];

		if (!phys || !phys->hw_ctl)
			return;

		ctl = phys->hw_ctl;
		if (ctl && ctl->ops.get_scheduler_status) {
			rc = wait_event_timeout(phys->pending_kickoff_wq,
				(ctl->ops.get_scheduler_status(ctl) & BIT(0)),
				msecs_to_jiffies(KICKOFF_TIMEOUT_MS));
			if (!rc) {
				SDE_ERROR("wait for ctl idle failed\n");
				SDE_EVT32(SDE_EVTLOG_ERROR);
				return;
			}

			SDE_EVT32(ctl->ops.get_scheduler_status(ctl));
		}
	}
}

int sde_encoder_display_failure_notification(struct drm_encoder *enc,
	bool skip_pre_kickoff)
{
	struct msm_drm_thread *event_thread = NULL;
	struct msm_drm_private *priv = NULL;
	struct sde_encoder_virt *sde_enc = NULL;
	bool posted_start_en = false;

	if (!enc || !enc->dev || !enc->dev->dev_private) {
		SDE_ERROR("invalid parameters\n");
@@ -6062,10 +6091,16 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc,
		return -EINVAL;
	}

	SDE_EVT32_VERBOSE(DRMID(enc));

	event_thread = &priv->event_thread[sde_enc->crtc->index];

	if (sde_enc->cur_master && sde_enc->cur_master->connector)
		posted_start_en = (sde_connector_get_property(
				sde_enc->cur_master->connector->state,
				CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE) ==
				FRAME_DONE_WAIT_POSTED_START) ? true : false;

	SDE_EVT32_VERBOSE(DRMID(enc), posted_start_en);

	if (!skip_pre_kickoff) {
		kthread_queue_work(&event_thread->worker,
				   &sde_enc->esd_trigger_work);
@@ -6079,7 +6114,16 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc,
	 */
	sde_encoder_helper_switch_vsync(enc, true);

	if (!skip_pre_kickoff)
	if (skip_pre_kickoff)
		return 0;
	else if (posted_start_en)
		/*
		 * Make sure that the frame transfer is completed after
		 * switching to watchdog vsync. The timeout will be
		 * handled in the commit context for posted start usecases.
		 */
		sde_encoder_wait_for_ctl_idle(sde_enc);
	else
		sde_encoder_wait_for_event(enc, MSM_ENC_TX_COMPLETE);

	return 0;