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

Commit 132458d8 authored by Raviteja Tamatam's avatar Raviteja Tamatam
Browse files

drm/msm/sde: fix race condition in vblank control interrupts



In Dual display concurrencies there are certain cases where
irq_idx and vblank_refcount state mismatch can occur.
To avoid it, during setup of irq_hw_idx, reset the vblank_refcount
and unregister read ptr irq if not yet done by then.
Also, if register IRQ fails, correct vblank_refcount so
that IRQ registration can be tried again.

Change-Id: I06bcbf71c6a43bd161ff61093d9f6063a292d6bc
Signed-off-by: default avatarRaviteja Tamatam <travitej@codeaurora.org>
parent 1d8b3d68
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -375,6 +375,7 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_irq *irq;
	int ret = 0;

	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl) {
		SDE_ERROR("invalid args %d %d\n", !phys_enc,
@@ -387,6 +388,22 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
		return;
	}

	mutex_lock(phys_enc->vblank_ctl_lock);

	if (atomic_read(&phys_enc->vblank_refcount)) {
		SDE_ERROR(
		"vblank_refcount mismatch detected, try to reset %d\n",
				atomic_read(&phys_enc->vblank_refcount));
		ret = sde_encoder_helper_unregister_irq(phys_enc,
				INTR_IDX_RDPTR);
		if (ret)
			SDE_ERROR(
			"control vblank irq registration error %d\n",
				ret);
	}

	atomic_set(&phys_enc->vblank_refcount, 0);

	irq = &phys_enc->irq[INTR_IDX_CTL_START];
	irq->hw_idx = phys_enc->hw_ctl->idx;
	irq->irq_idx = -EINVAL;
@@ -412,6 +429,8 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
		irq->hw_idx = phys_enc->hw_intf->idx;
	else
		irq->hw_idx = phys_enc->hw_pp->idx;

	mutex_unlock(phys_enc->vblank_ctl_lock);
}

static void sde_encoder_phys_cmd_cont_splash_mode_set(
@@ -825,11 +844,17 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
			enable, refcount);

	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) {
		ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR);
	else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
		if (ret)
			atomic_dec_return(&phys_enc->vblank_refcount);
	} else if (!enable &&
			atomic_dec_return(&phys_enc->vblank_refcount) == 0) {
		ret = sde_encoder_helper_unregister_irq(phys_enc,
				INTR_IDX_RDPTR);
		if (ret)
			atomic_inc_return(&phys_enc->vblank_refcount);
	}

end:
	if (ret) {