]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/i915: Check PSR errors instead of retrain while PSR is enabled
authorJosé Roberto de Souza <jose.souza@intel.com>
Wed, 21 Nov 2018 22:54:37 +0000 (14:54 -0800)
committerJosé Roberto de Souza <jose.souza@intel.com>
Thu, 22 Nov 2018 21:51:16 +0000 (13:51 -0800)
When a PSR error happens sink sets the PSR error register and also
set the link status to a error status.
So in the short pulse handling it was returning earlier and doing a
full detection and attempting to retrain but it fails as PSR HW is
in change of the main-link.

Just call intel_psr_short_pulse() before
intel_dp_needs_link_retrain() is not the right fix as
intel_dp_needs_link_retrain() would return true and trigger a full
detection while PSR HW is still in change of main-link.

Check for PSR active is also not safe as it could be inactive due a
frontbuffer invalidate and still doing the PSR exit sequence.

v3: added comment in intel_dp_needs_link_retrain()

Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181121225441.18785-2-jose.souza@intel.com
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_psr.c

index a6c654e1795504ec3ec722354b88f633109714db..70ae3d57316ba5a9181055ebcd6be1b6ef614a58 100644 (file)
@@ -4383,6 +4383,17 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
        if (!intel_dp->link_trained)
                return false;
 
+       /*
+        * While PSR source HW is enabled, it will control main-link sending
+        * frames, enabling and disabling it so trying to do a retrain will fail
+        * as the link would or not be on or it could mix training patterns
+        * and frame data at the same time causing retrain to fail.
+        * Also when exiting PSR, HW will retrain the link anyways fixing
+        * any link status error.
+        */
+       if (intel_psr_enabled(intel_dp))
+               return false;
+
        if (!intel_dp_get_link_status(intel_dp, link_status))
                return false;
 
index a7d9ac9121259685df03273726a1ad4e70e376ca..a62d77b762919628c19892751fe78bd641ccf6c6 100644 (file)
@@ -2047,6 +2047,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir);
 void intel_psr_short_pulse(struct intel_dp *intel_dp);
 int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state,
                            u32 *out_value);
+bool intel_psr_enabled(struct intel_dp *intel_dp);
 
 /* intel_quirks.c */
 void intel_init_quirks(struct drm_i915_private *dev_priv);
index 54fa17a5596a4850cfde042d76a15bffa5b54258..ebb255f230b75ce5e9b3508f9da54e377a6a87f5 100644 (file)
@@ -1147,3 +1147,18 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp)
 exit:
        mutex_unlock(&psr->lock);
 }
+
+bool intel_psr_enabled(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       bool ret;
+
+       if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp))
+               return false;
+
+       mutex_lock(&dev_priv->psr.lock);
+       ret = (dev_priv->psr.dp == intel_dp && dev_priv->psr.enabled);
+       mutex_unlock(&dev_priv->psr.lock);
+
+       return ret;
+}