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

Commit fb29f691 authored by Krishna Manikandan's avatar Krishna Manikandan Committed by Nirmal Abraham
Browse files

drm/msm/sde: stage border fill after ctl start timeout



In some error cases ctl start irq is delayed more than ctl start
timeout period and it is received after programming the
next commit CTL registers but before next flush. Due to this
only new CTL register configuration takes effect but not the pipe
configuration. This is leading to smmu fault. Staging border-fill
in these cases after ctl start timeout will help prevent illegal
iova 0x0 (non-configured pipe) transactions onto the bus.

Change-Id: I85418df3a922a8468f31adc285fac217e8f2eee4
Signed-off-by: default avatarRaviteja Tamatam <travitej@codeaurora.org>
Signed-off-by: default avatarKrishna Manikandan <mkrishn@codeaurora.org>
parent d3c9ac17
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -757,6 +757,25 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,

	return true;
}
static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc)
{
	struct drm_encoder *encoder;
	int rc = 0;

	if (!crtc || !crtc->dev)
		return 0;

	list_for_each_entry(encoder,
			&crtc->dev->mode_config.encoder_list, head) {
		if (encoder->crtc != crtc)
			continue;

		if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD)
			rc += sde_encoder_get_ctlstart_timeout_state(encoder);
	}

	return rc;
}

static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
	struct sde_plane_state *pstate, struct sde_format *format)
@@ -3184,7 +3203,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
	if (unlikely(!sde_crtc->num_mixers))
		return;

	if (_sde_crtc_get_ctlstart_timeout(crtc)) {
		_sde_crtc_blend_setup(crtc, old_state, false);
		SDE_ERROR("border fill only commit after ctlstart timeout\n");
	} else {
		_sde_crtc_blend_setup(crtc, old_state, true);
	}

	_sde_crtc_dest_scaler_setup(crtc);

	/* cancel the idle notify delayed work */
+18 −0
Original line number Diff line number Diff line
@@ -3229,6 +3229,24 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
	return 0;
}

int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	int i, count = 0;

	if (!drm_enc)
		return 0;

	sde_enc = to_sde_encoder_virt(drm_enc);

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout);
		atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0);
	}

	return count;
}

/**
 * _sde_encoder_trigger_flush - trigger flush for a physical encoder
 * drm_enc: Pointer to drm encoder structure
+7 −0
Original line number Diff line number Diff line
@@ -266,4 +266,11 @@ int sde_encoder_in_clone_mode(struct drm_encoder *enc);
 */
void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);

/**
 * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened
 * @drm_enc:    Pointer to drm encoder structure
 * @Return:     non zero value if ctl start timeout occurred
 */
int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc);

#endif /* __SDE_ENCODER_H__ */
+2 −0
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ struct sde_encoder_irq {
 * @pending_retire_fence_cnt:   Atomic counter tracking the pending retire
 *                              fences that have to be signalled.
 * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
 * @ctlstart_timeout:		Indicates if ctl start timeout occurred
 * @irq:			IRQ tracking structures
 * @cont_splash_single_flush	Variable to check if single flush is enabled.
 * @cont_splash_settings	Variable to store continuous splash settings.
@@ -301,6 +302,7 @@ struct sde_encoder_phys {
	atomic_t pending_kickoff_cnt;
	atomic_t pending_retire_fence_cnt;
	wait_queue_head_t pending_kickoff_wq;
	atomic_t ctlstart_timeout;
	struct sde_encoder_irq irq[INTR_IDX_MAX];
	u32 cont_splash_single_flush;
	bool cont_splash_settings;
+8 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -193,6 +193,7 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
				phys_enc,
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
		atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
		atomic_set(&phys_enc->ctlstart_timeout, 0);
	}

	/* notify all synchronous clients first, then asynchronous clients */
@@ -292,6 +293,7 @@ static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx)

	ctl = phys_enc->hw_ctl;
	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
	atomic_set(&phys_enc->ctlstart_timeout, 0);

	time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp);

@@ -1054,6 +1056,7 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
		SDE_ERROR("invalid encoder\n");
		return;
	}
	atomic_set(&phys_enc->ctlstart_timeout, 0);
	SDE_DEBUG_CMDENC(cmd_enc, "pp %d state %d\n",
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->enable_state);
@@ -1176,6 +1179,9 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
					"ctl start interrupt wait failed\n");
		else
			ret = 0;

		if (sde_encoder_phys_cmd_is_master(phys_enc))
			atomic_inc_return(&phys_enc->ctlstart_timeout);
	}

	return ret;
@@ -1476,6 +1482,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
	atomic_set(&phys_enc->ctlstart_timeout, 0);
	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
	atomic_set(&cmd_enc->autorefresh.kickoff_cnt, 0);