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

Commit be57f384 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: signal release fence after flush accepted"

parents 721f7dd9 a1b52e7f
Loading
Loading
Loading
Loading
+25 −22
Original line number Diff line number Diff line
@@ -405,7 +405,7 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
			to_sde_encoder_phys_vid(phys_enc);
	struct sde_hw_ctl *hw_ctl;
	unsigned long lock_flags;
	u32 flush_register = 0;
	u32 flush_register = ~0;
	u32 reset_status = 0;
	int new_cnt = -1, old_cnt = -1;
	u32 event = 0;
@@ -419,42 +419,45 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)

	SDE_ATRACE_BEGIN("vblank_irq");

	/* signal only for master, where there is a pending kickoff */
	if (sde_encoder_phys_vid_is_master(phys_enc)
			&& atomic_add_unless(
				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
		event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
				| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;

		if (phys_enc->parent_ops.handle_frame_done)
			phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
				phys_enc, event);
	}

	if (phys_enc->parent_ops.handle_vblank_virt)
		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
				phys_enc);

	old_cnt  = atomic_read(&phys_enc->pending_kickoff_cnt);

	/*
	 * only decrement the pending flush count if we've actually flushed
	 * hardware. due to sw irq latency, vblank may have already happened
	 * so we need to double-check with hw that it accepted the flush bits
	 */
	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);

	old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);

	if (hw_ctl && hw_ctl->ops.get_flush_register)
		flush_register = hw_ctl->ops.get_flush_register(hw_ctl);

	if (flush_register == 0)
		new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt,
				-1, 0);
	if (flush_register)
		goto not_flushed;

	new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);

	/* signal only for master, where there is a pending kickoff */
	if (sde_encoder_phys_vid_is_master(phys_enc)) {
		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
					-1, 0))
			event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
				SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
	}

not_flushed:
	if (hw_ctl && hw_ctl->ops.get_reset)
		reset_status = hw_ctl->ops.get_reset(hw_ctl);

	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);

	if (event && phys_enc->parent_ops.handle_frame_done)
		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
			phys_enc, event);

	if (phys_enc->parent_ops.handle_vblank_virt)
		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
				phys_enc);

	SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
			old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0,
			flush_register, event);