Commit 9900e35a authored by Jouni Högander's avatar Jouni Högander
Browse files

drm/i915/psr: Add PSR pause/resume reference count



We have now seen this:

<4> [2120.434153] i915 0000:00:02.0: [drm] drm_WARN_ON(psr->paused)
<4> [2120.434196] WARNING: CPU: 3 PID: 4430 at drivers/gpu/drm/i915/display/intel_psr.c:2227 intel_psr_pause+0x16e/0x180 [i915]

Comment for drm_WARN_ON(display->drm, psr->paused) in intel_psr_pause says:

"If we ever hit this, we will need to add refcount to pause/resume"

This patch is implementing PSR pause/resume refcount.

v3: Incorporate changes missing from v2
v2: Add drm_warn for detecting possible unbalanced pause/resume

Signed-off-by: default avatarJouni Högander <jouni.hogander@intel.com>
Reviewed-by: default avatarAnimesh Manna <animesh.manna@intel.com>
Link: https://lore.kernel.org/r/20250328080623.1183669-1-jouni.hogander@intel.com
parent 94f60899
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1620,7 +1620,7 @@ struct intel_psr {
	bool sink_support;
	bool source_support;
	bool enabled;
	bool paused;
	int pause_counter;
	enum pipe pipe;
	enum transcoder transcoder;
	bool active;
+17 −14
Original line number Diff line number Diff line
@@ -2014,7 +2014,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,

	intel_psr_enable_source(intel_dp, crtc_state);
	intel_dp->psr.enabled = true;
	intel_dp->psr.paused = false;
	intel_dp->psr.pause_counter = 0;

	/*
	 * Link_ok is sticky and set here on PSR enable. We can assume link
@@ -2199,7 +2199,6 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 */
void intel_psr_pause(struct intel_dp *intel_dp)
{
	struct intel_display *display = to_intel_display(intel_dp);
	struct intel_psr *psr = &intel_dp->psr;

	if (!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp))
@@ -2212,12 +2211,10 @@ void intel_psr_pause(struct intel_dp *intel_dp)
		return;
	}

	/* If we ever hit this, we will need to add refcount to pause/resume */
	drm_WARN_ON(display->drm, psr->paused);

	if (intel_dp->psr.pause_counter++ == 0) {
		intel_psr_exit(intel_dp);
		intel_psr_wait_exit_locked(intel_dp);
	psr->paused = true;
	}

	mutex_unlock(&psr->lock);

@@ -2233,6 +2230,7 @@ void intel_psr_pause(struct intel_dp *intel_dp)
 */
void intel_psr_resume(struct intel_dp *intel_dp)
{
	struct intel_display *display = to_intel_display(intel_dp);
	struct intel_psr *psr = &intel_dp->psr;

	if (!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp))
@@ -2240,13 +2238,18 @@ void intel_psr_resume(struct intel_dp *intel_dp)

	mutex_lock(&psr->lock);

	if (!psr->paused)
		goto unlock;
	if (!psr->enabled)
		goto out;

	if (!psr->pause_counter) {
		drm_warn(display->drm, "Unbalanced PSR pause/resume!\n");
		goto out;
	}

	psr->paused = false;
	if (--intel_dp->psr.pause_counter == 0)
		intel_psr_activate(intel_dp);

unlock:
out:
	mutex_unlock(&psr->lock);
}

@@ -3298,7 +3301,7 @@ void intel_psr_flush(struct intel_display *display,
		 * we have to ensure that the PSR is not activated until
		 * intel_psr_resume() is called.
		 */
		if (intel_dp->psr.paused)
		if (intel_dp->psr.pause_counter)
			goto unlock;

		if (origin == ORIGIN_FLIP ||