Send a modeset-retry uevent to all connectors in the same MST topology after a link training failure and reduction of the link parameters. This matches the way the same uevent is sent after a DP tunnel BW allocation failure. v2: Add NOTE that the atomic state may not be valid for SST links and assert that it's valid for MST links. (Ville) Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++++- drivers/gpu/drm/i915/display/intel_dp.h | 1 - .../drm/i915/display/intel_dp_link_training.c | 16 ++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4438ec2989249..8259d91d2d041 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2793,7 +2793,7 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder, intel_dp_is_uhbr(pipe_config); } -void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) +static void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -2802,6 +2802,7 @@ void intel_dp_queue_modeset_retry_work(struct intel_connector *connector) drm_connector_put(&connector->base); } +/* NOTE: @state is only valid for MST links and can be %NULL for SST. */ void intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_encoder *encoder, @@ -2810,6 +2811,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_connector *connector; struct intel_digital_connector_state *conn_state; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct drm_i915_private *i915 = dp_to_i915(intel_dp); int i; if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { @@ -2818,6 +2820,9 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, return; } + if (drm_WARN_ON(&i915->drm, !state)) + return; + for_each_new_intel_connector_in_state(state, connector, conn_state, i) { if (!conn_state->base.crtc) continue; diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 279cca23b95fa..ec4131db07439 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -44,7 +44,6 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); int intel_dp_min_bpp(enum intel_output_format output_format); void intel_dp_init_modeset_retry_work(struct intel_connector *connector); -void intel_dp_queue_modeset_retry_work(struct intel_connector *connector); void intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 04629a4341eef..bb8680ac7f4da 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -1187,10 +1187,13 @@ static int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, return 0; } -static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp, +/* NOTE: @state is only valid for MST links and can be %NULL for SST. */ +static void intel_dp_schedule_fallback_link_training(struct intel_atomic_state *state, + struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - struct intel_connector *intel_connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; if (!intel_digital_port_connected(&dp_to_dig_port(intel_dp)->base)) { lt_dbg(intel_dp, DP_PHY_DPRX, "Link Training failed on disconnected sink.\n"); @@ -1205,8 +1208,13 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp, return; } + if (drm_WARN_ON(&i915->drm, + intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) && + !state)) + return; + /* Schedule a Hotplug Uevent to userspace to start modeset */ - intel_dp_queue_modeset_retry_work(intel_connector); + intel_dp_queue_modeset_retry_for_link(state, encoder, crtc_state); } /* Perform the link training on all LTTPRs and the DPRX on a link. */ @@ -1525,7 +1533,7 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, return; } - intel_dp_schedule_fallback_link_training(intel_dp, crtc_state); + intel_dp_schedule_fallback_link_training(state, intel_dp, crtc_state); } void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, -- 2.43.3