On Wed, 2026-07-01 at 18:31 +0300, Imre Deak wrote:
> Disable the link configuration that failed training when selecting
> fallback parameters.
> 
> Fallback still selects the next configuration using the existing
> fallback order, but now also removes the failed configuration from the
> allowed set. Functionally, this only affects the case where an MST <-> SST
> mode switch occurs on the same root connector: previously, a configuration
> that failed training in one mode could be reused in the other mode due
> to the differing config iteration orders.
> 
> The current fallback logic also sets a temporary maximum link limit
> across the allowed configurations to constrain subsequent modesets. This
> legacy behavior is preserved for now; it will be removed once the
> fallback logic relies solely on the individually disabled configurations
> to restrict the allowed set.
> 
> Signed-off-by: Imre Deak <[email protected]>
> ---
>  .../gpu/drm/i915/display/intel_dp_link_caps.c | 55 +++++++++++++++++++
>  .../gpu/drm/i915/display/intel_dp_link_caps.h |  3 +
>  .../drm/i915/display/intel_dp_link_training.c | 19 +++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c 
> b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> index c947e6511fbc5..76b7c0fc90115 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> @@ -596,6 +596,21 @@ bool intel_dp_link_caps_filter_add(struct 
> intel_dp_link_caps *link_caps,
>       return true;
>  }
>  
> +static bool intel_dp_link_caps_filter_remove(struct intel_dp_link_caps 
> *link_caps,
> +                                          struct intel_dp_link_caps_filter 
> *filter,
> +                                          const struct intel_dp_link_config 
> *config)
> +{
> +     int idx;
> +
> +     idx = find_config_idx(link_caps, get_allowed_config_filter(link_caps), 
> config);
> +     if (idx < 0)
> +             return false;
> +
> +     filter->config_mask &= ~BIT(idx);
> +
> +     return true;
> +}
> +
>  static void set_max_link_limits(struct intel_dp_link_caps *link_caps,
>                               const struct intel_dp_link_config 
> *max_link_limits)
>  {
> @@ -618,6 +633,46 @@ static void reset_max_link_limits_reenable_all(struct 
> intel_dp_link_caps *link_c
>       reset_max_link_limits(link_caps);
>  }
>  
> +/**
> + * intel_dp_link_caps_disable_config - disable a configuration
> + * @link_caps: link capabilities state
> + * @config: configuration to disable
> + *
> + * Disable the configuration identified by @config. This removes the
> + * configuration from the set of allowed configurations. The disabling
> + * shouldn't leave the remaining configuration set empty.
> + *
> + * The configuration remains disallowed until intel_dp_link_caps() with
> + * reset=%true or changed sink capabilities is called, or
> + * intel_dp_link_caps_reset() is called. Each of these happens after a
> + * new sink is connected or the currently connected sink changes its
> + * capabilities.
> + *
> + * Return:
> + * - %true  if @config was valid and the derived state was updated.
> + * - %false if @config was invalid or the remaining configuration set
> + *   would remain empty.
> + */
> +bool intel_dp_link_caps_disable_config(struct intel_dp_link_caps *link_caps,
> +                                    const struct intel_dp_link_config 
> *config)
> +{
> +     struct intel_dp_link_caps_filter enabled_configs = 
> link_caps->enabled_configs;
> +     struct intel_dp_link_config forced_params;
> +
> +     if (!intel_dp_link_caps_filter_remove(link_caps, &enabled_configs, 
> config))
> +             return false;
> +
> +     intel_dp_link_caps_get_forced_params(link_caps, &forced_params);
> +
> +     if (!calc_allowed_config_filter(link_caps, enabled_configs,
> +                                     &link_caps->max_limits, 
> &forced_params).config_mask)
> +             return false;
> +
> +     link_caps->enabled_configs = enabled_configs;
> +
> +     return true;
> +}
> +
>  /**
>   * intel_dp_link_caps_get_max_limits - get the current maximum link limits
>   * @link_caps: link capabilities state
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h 
> b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> index 5c0d660062149..56c585eb5a135 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> @@ -136,6 +136,9 @@ bool intel_dp_link_caps_get_max_config(struct 
> intel_dp_link_caps *link_caps,
>  void intel_dp_link_caps_get_max_bw_config(struct intel_dp_link_caps 
> *link_caps,
>                                         struct intel_dp_link_config 
> *max_config);
>  
> +bool intel_dp_link_caps_disable_config(struct intel_dp_link_caps *link_caps,
> +                                    const struct intel_dp_link_config 
> *config);
> +
>  void intel_dp_link_caps_get_max_limits(struct intel_dp_link_caps *link_caps,
>                                      struct intel_dp_link_config 
> *max_link_limits);
>  bool intel_dp_link_caps_set_max_limits(struct intel_dp_link_caps *link_caps,
> 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 1c12503908d80..a592bfab5ff0e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -1894,6 +1894,10 @@ static int 
> intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>       struct intel_display *display = to_intel_display(intel_dp);
>       struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
>       struct intel_dp_link_config max_link_limits;
> +     struct intel_dp_link_config current_config = {
> +             .rate = crtc_state->port_clock,
> +             .lane_count = crtc_state->lane_count,
> +     };
>       int new_link_rate;
>       int new_lane_count;
>       int err = -1;
> @@ -1920,6 +1924,13 @@ static int 
> intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>       intel_dp_link_caps_get_max_limits(link_caps, &max_link_limits);
>       intel_dp_link_caps_reset_max_limits(link_caps);
>  
> +     /*
> +      * TODO: Make fallback depend only on disabling the current config,
> +      * once max_limit no longer constrains the allowed config set. Then
> +      * disabling the current config will define the allowed configs for
> +      * the subsequent modeset, so there will be no need to select a
> +      * reduced config separately here.
> +      */
>       if (!reduce_link_params(intel_dp, crtc_state, &new_link_rate, 
> &new_lane_count))
>               goto out_restore_max_limits;
>  
> @@ -1933,6 +1944,14 @@ static int 
> intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
>               goto out_restore_max_limits;
>       }
>  
> +     /*
> +      * Shouldn't fail: the current config was enabled, and reducing the
> +      * link parameters should still leave the fallback config allowed.
> +      */
> +     if (drm_WARN_ON(display->drm,
> +                     !intel_dp_link_caps_disable_config(link_caps, 
> &current_config)))
> +             return -1;
> +
>       lt_dbg(intel_dp, DP_PHY_DPRX,
>              "Reducing link parameters from %dx%d to %dx%d\n",
>              crtc_state->lane_count, crtc_state->port_clock,

Reviewed-by: Luca Coelho <[email protected]>

--
Cheers,
Luca.

Reply via email to