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

Commit 29bccd4c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 0aaa0849 50ea2cf5
Loading
Loading
Loading
Loading
+32 −4
Original line number Diff line number Diff line
@@ -348,6 +348,24 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_irq *irq;
	struct sde_kms *sde_kms = phys_enc->sde_kms;
	int ret = 0;

	mutex_lock(&sde_kms->vblank_ctl_global_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;
@@ -368,6 +386,8 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
	irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
	irq->hw_idx = phys_enc->hw_pp->idx;
	irq->irq_idx = -EINVAL;

	mutex_unlock(&sde_kms->vblank_ctl_global_lock);
}

static void sde_encoder_phys_cmd_cont_splash_mode_set(
@@ -674,13 +694,15 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
		to_sde_encoder_phys_cmd(phys_enc);
	int ret = 0;
	int refcount;
	struct sde_kms *sde_kms;

	if (!phys_enc || !phys_enc->hw_pp) {
		SDE_ERROR("invalid encoder\n");
		return -EINVAL;
	}
	sde_kms = phys_enc->sde_kms;

	mutex_lock(phys_enc->vblank_ctl_lock);
	mutex_lock(&sde_kms->vblank_ctl_global_lock);
	refcount = atomic_read(&phys_enc->vblank_refcount);

	/* Slave encoders don't report vblank */
@@ -698,11 +720,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) {
@@ -714,7 +742,7 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
				enable, refcount, SDE_EVTLOG_ERROR);
	}

	mutex_unlock(phys_enc->vblank_ctl_lock);
	mutex_unlock(&sde_kms->vblank_ctl_global_lock);
	return ret;
}

+2 −0
Original line number Diff line number Diff line
@@ -3427,6 +3427,8 @@ static int sde_kms_hw_init(struct msm_kms *kms)
	dev->mode_config.max_height = sde_kms->catalog->max_display_height;

	mutex_init(&sde_kms->secure_transition_lock);
	mutex_init(&sde_kms->vblank_ctl_global_lock);

	atomic_set(&sde_kms->detach_sec_cb, 0);
	atomic_set(&sde_kms->detach_all_cb, 0);

+1 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ struct sde_kms {
	atomic_t detach_sec_cb;
	atomic_t detach_all_cb;
	struct mutex secure_transition_lock;
	struct mutex vblank_ctl_global_lock;

	bool first_kickoff;
};