[Intel-gfx] [PATCH 4/7] drm/i915: Disable PSR when a PSR aux error happen
Rodrigo Vivi
rodrigo.vivi at intel.com
Tue Nov 20 22:47:03 UTC 2018
On Fri, Nov 09, 2018 at 12:20:13PM -0800, José Roberto de Souza wrote:
> While PSR is active hardware will do aux transactions by it self to
> wakeup sink to receive a new frame when necessary. If that
> transaction is not acked by sink, hardware will trigger this
> interruption.
>
> So let's disable PSR as it is a hint that there is problem with this
> sink.
>
> The removed FIXME was asking to manually train the link but we don't
> need to do that as by spec sink should do a short pulse when it is
> out of sync with source, we just need to make sure it is awaken and
> the SDP header with PSR disable will trigger this condition.
>
> v3: added workarround to fix scheduled work starvation cause by
> to frequent PSR error interruption
> v4: only setting irq_aux_error as we don't care in clear it and
> not using dev_priv->irq_lock as consequence.
>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 1 +
> drivers/gpu/drm/i915/intel_psr.c | 41 ++++++++++++++++++++++++++++----
> 2 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index e13222518c1b..4022a317cf05 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -642,6 +642,7 @@ struct i915_psr {
> ktime_t last_entry_attempt;
> ktime_t last_exit;
> bool sink_not_reliable;
> + bool irq_aux_error;
> };
>
> enum intel_pch {
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index cc738497d551..93d8538a2383 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -152,6 +152,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
> u32 transcoders = BIT(TRANSCODER_EDP);
> enum transcoder cpu_transcoder;
> ktime_t time_ns = ktime_get();
> + u32 mask = 0;
>
> if (INTEL_GEN(dev_priv) >= 8)
> transcoders |= BIT(TRANSCODER_A) |
> @@ -159,10 +160,22 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
> BIT(TRANSCODER_C);
>
> for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
> - /* FIXME: Exit PSR and link train manually when this happens. */
> - if (psr_iir & EDP_PSR_ERROR(cpu_transcoder))
> - DRM_DEBUG_KMS("[transcoder %s] PSR aux error\n",
> - transcoder_name(cpu_transcoder));
> + if (psr_iir & EDP_PSR_ERROR(cpu_transcoder)) {
> + DRM_WARN("[transcoder %s] PSR aux error\n",
> + transcoder_name(cpu_transcoder));
> +
> + dev_priv->psr.irq_aux_error = true;
> +
> + /*
> + * If this interruption is not masked it will keep
> + * interrupting so fast that it prevents the scheduled
> + * work to run.
> + * Also after a PSR error, we don't want to arm PSR
> + * again so we don't care about unmask the interruption
> + * or unset irq_aux_error.
> + */
> + mask |= EDP_PSR_ERROR(cpu_transcoder);
> + }
>
> if (psr_iir & EDP_PSR_PRE_ENTRY(cpu_transcoder)) {
> dev_priv->psr.last_entry_attempt = time_ns;
> @@ -184,6 +197,13 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
> }
> }
> }
> +
> + if (mask) {
> + mask |= I915_READ(EDP_PSR_IMR);
> + I915_WRITE(EDP_PSR_IMR, mask);
> +
> + schedule_work(&dev_priv->psr.work);
> + }
> }
>
> static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
> @@ -898,6 +918,16 @@ int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> return ret;
> }
>
> +static void intel_psr_handle_irq(struct drm_i915_private *dev_priv)
> +{
> + struct i915_psr *psr = &dev_priv->psr;
> +
> + intel_psr_disable_locked(psr->dp);
> + psr->sink_not_reliable = true;
> + /* let's make sure that sink is awaken */
> + drm_dp_dpcd_writeb(&psr->dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
Hmmmm... my gut feeling and my bad memory about PSR tells this can flicker
in some panels. But at least you are disabling PSR for good after that what
is a good thing.
I wonder what other alternatives we would have here?
maybe the one suggested on FIXME? disable PSR and train link manually?
> +}
> +
> static void intel_psr_work(struct work_struct *work)
> {
> struct drm_i915_private *dev_priv =
> @@ -908,6 +938,9 @@ static void intel_psr_work(struct work_struct *work)
> if (!dev_priv->psr.enabled)
> goto unlock;
>
> + if (READ_ONCE(dev_priv->psr.irq_aux_error))
> + intel_psr_handle_irq(dev_priv);
> +
> /*
> * We have to make sure PSR is ready for re-enable
> * otherwise it keeps disabled until next full enable/disable cycle.
> --
> 2.19.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list