]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/i915/dp: Queue a link check after link training is complete
authorImre Deak <imre.deak@intel.com>
Wed, 5 Mar 2025 11:48:20 +0000 (13:48 +0200)
committerImre Deak <imre.deak@intel.com>
Tue, 11 Mar 2025 09:15:27 +0000 (11:15 +0200)
After link training - both in case of a passing and failing LT result -
a work is scheduled to check the link state. This check should take
place after the link training is completed by disabling the link
training pattern and setting intel_dp::link_trained=true. Atm, the work
is scheduled before these steps, which may result in checking the link
state too early (and thus not retraining the link as expected).

Fix the above by scheduling the link check work after link training is
complete.

v2:
- Add MAX_SEQ_TRAIN_FAILURES instead of open-coding it. (Jani)

Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250305114820.3523077-2-imre.deak@intel.com
drivers/gpu/drm/i915/display/intel_dp_link_training.c

index 5d549ac4de1c5af9ea5fd4609c8a9c9c5b3a1edd..ded246bbf23256ace0d888f87cef9c1f4843bde2 100644 (file)
@@ -56,6 +56,8 @@
                lt_dbg(_intel_dp, _dp_phy, "Sink disconnected: " _format, ## __VA_ARGS__); \
 } while (0)
 
+#define MAX_SEQ_TRAIN_FAILURES 2
+
 static void intel_dp_reset_lttpr_common_caps(struct intel_dp *intel_dp)
 {
        memset(intel_dp->lttpr_common_caps, 0, sizeof(intel_dp->lttpr_common_caps));
@@ -1124,6 +1126,7 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp,
 void intel_dp_stop_link_train(struct intel_dp *intel_dp,
                              const struct intel_crtc_state *crtc_state)
 {
+       struct intel_display *display = to_intel_display(intel_dp);
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
 
        intel_dp->link_trained = true;
@@ -1138,6 +1141,13 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp,
        }
 
        intel_hpd_unblock(encoder);
+
+       if (!display->hotplug.ignore_long_hpd &&
+           intel_dp->link.seq_train_failures < MAX_SEQ_TRAIN_FAILURES) {
+               int delay_ms = intel_dp->link.seq_train_failures ? 0 : 2000;
+
+               intel_encoder_link_check_queue_work(encoder, delay_ms);
+       }
 }
 
 static bool
@@ -1642,7 +1652,6 @@ void intel_dp_start_link_train(struct intel_atomic_state *state,
                lt_dbg(intel_dp, DP_PHY_DPRX, "Forcing link training failure\n");
        } else if (passed) {
                intel_dp->link.seq_train_failures = 0;
-               intel_encoder_link_check_queue_work(encoder, 2000);
                return;
        }
 
@@ -1665,10 +1674,8 @@ void intel_dp_start_link_train(struct intel_atomic_state *state,
                return;
        }
 
-       if (intel_dp->link.seq_train_failures < 2) {
-               intel_encoder_link_check_queue_work(encoder, 0);
+       if (intel_dp->link.seq_train_failures < MAX_SEQ_TRAIN_FAILURES)
                return;
-       }
 
        if (intel_dp_schedule_fallback_link_training(state, intel_dp, crtc_state))
                return;