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

Commit fa73055e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: sde: fix release fence signaling in error cases"

parents 50e8ef62 5a2dfc1e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3362,6 +3362,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
			sde_enc->phys_encs[i]->cont_splash_enabled = false;
			sde_enc->phys_encs[i]->connector = NULL;
		}
		atomic_set(&sde_enc->frame_done_cnt[i], 0);
	}

	sde_enc->cur_master = NULL;
@@ -3647,8 +3648,7 @@ static void sde_encoder_frame_done_callback(

		/* One of the physical encoders has become idle */
		for (i = 0; i < sde_enc->num_phys_encs; i++) {
			if ((sde_enc->phys_encs[i] == ready_phys) ||
			     (event & SDE_ENCODER_FRAME_EVENT_ERROR)) {
			if (sde_enc->phys_encs[i] == ready_phys) {
				SDE_EVT32_VERBOSE(DRMID(drm_enc), i,
				     atomic_read(&sde_enc->frame_done_cnt[i]));
				if (!atomic_add_unless(
+2 −1
Original line number Diff line number Diff line
@@ -365,12 +365,12 @@ struct sde_encoder_phys_cmd_autorefresh {
 * struct sde_encoder_phys_cmd - sub-class of sde_encoder_phys to handle command
 *	mode specific operations
 * @base:	Baseclass physical encoder structure
 * @intf_idx:	Intf Block index used by this phys encoder
 * @stream_sel:	Stream selection for multi-stream interfaces
 * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
 * @autorefresh: autorefresh feature state
 * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
 * @pending_vblank_wq: Wait queue for blocking until VBLANK received
 * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger
 */
struct sde_encoder_phys_cmd {
	struct sde_encoder_phys base;
@@ -379,6 +379,7 @@ struct sde_encoder_phys_cmd {
	struct sde_encoder_phys_cmd_autorefresh autorefresh;
	atomic_t pending_vblank_cnt;
	wait_queue_head_t pending_vblank_wq;
	bool wr_ptr_wait_success;
};

/**
+31 −27
Original line number Diff line number Diff line
@@ -461,20 +461,18 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(

	conn = phys_enc->connector;

	if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0)
	/* decrement the kickoff_cnt before checking for ESD status */
	if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0))
		return 0;

	cmd_enc->pp_timeout_report_cnt++;
	pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
	pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1;

	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
			cmd_enc->pp_timeout_report_cnt,
			pending_kickoff_cnt,
			frame_event);

	/* decrement the kickoff_cnt before checking for ESD status */
	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);

	/* check if panel is still sending TE signal or not */
	if (sde_connector_esd_status(phys_enc->connector))
		goto exit;
@@ -651,13 +649,29 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
			to_sde_encoder_phys_cmd(phys_enc);
	struct sde_encoder_wait_info wait_info;
	bool recovery_events;
	int ret, i, pending_cnt;
	int ret;
	struct sde_hw_ctl *ctl;

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

	ctl = phys_enc->hw_ctl;
	if (cmd_enc->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) {

		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;
	}

	wait_info.wq = &phys_enc->pending_kickoff_wq;
	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
@@ -671,8 +685,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
			&wait_info);
	if (ret == -ETIMEDOUT) {
		pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
		for (i = 0; i < pending_cnt; i++)
		_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc,
				recovery_events);
	} else if (!ret) {
@@ -1368,19 +1380,9 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
			phys_enc->parent_ops.handle_frame_done(
				phys_enc->parent, phys_enc,
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);

	} else if ((ret == 0) &&
		(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) {
		phys_enc->parent_ops.handle_frame_done(
			phys_enc->parent, phys_enc,
			SDE_ENCODER_FRAME_EVENT_DONE |
			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE);
	}

	cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
	return ret;
}

@@ -1408,7 +1410,7 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete(
static int sde_encoder_phys_cmd_wait_for_commit_done(
		struct sde_encoder_phys *phys_enc)
{
	int rc = 0;
	int rc = 0, i, pending_cnt;
	struct sde_encoder_phys_cmd *cmd_enc;

	if (!phys_enc)
@@ -1421,11 +1423,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done(
		rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc);
		if (rc == -ETIMEDOUT)
			goto wait_for_idle;
	}

	if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) &&
			cmd_enc->autorefresh.cfg.enable)
		rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc);
		if (cmd_enc->autorefresh.cfg.enable)
			rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(
								phys_enc);
	}

	/* wait for posted start or serialize trigger */
	if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) ||
@@ -1435,14 +1437,16 @@ static int sde_encoder_phys_cmd_wait_for_commit_done(
	return rc;

wait_for_idle:
	rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc);
	pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
	for (i = 0; i < pending_cnt; i++)
		rc |= sde_encoder_wait_for_event(phys_enc->parent,
				MSM_ENC_TX_COMPLETE);
	if (rc) {
		SDE_EVT32(DRMID(phys_enc->parent),
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->frame_trigger_mode,
			atomic_read(&phys_enc->pending_kickoff_cnt),
			phys_enc->enable_state, rc);
		atomic_set(&phys_enc->pending_kickoff_cnt, 0);
		SDE_ERROR("pp:%d failed wait_for_idle: %d\n",
				phys_enc->hw_pp->idx - PINGPONG_0, rc);
		if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET)