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, > ¤t_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.
