On Wed, Feb 14, 2024 at 01:23:42PM +0200, Jani Nikula wrote: > On Wed, 14 Feb 2024, "Murthy, Arun R" <arun.r.murthy@xxxxxxxxx> wrote: > >> -----Original Message----- > >> From: Nikula, Jani <jani.nikula@xxxxxxxxx> > >> Sent: Tuesday, February 13, 2024 11:41 PM > >> To: Murthy, Arun R <arun.r.murthy@xxxxxxxxx>; intel-gfx@xxxxxxxxxxxxxxxxxxxxx > >> Cc: Deak, Imre <imre.deak@xxxxxxxxx>; Syrjala, Ville <ville.syrjala@xxxxxxxxx>; > >> Shankar, Uma <uma.shankar@xxxxxxxxx>; Murthy, Arun R > >> <arun.r.murthy@xxxxxxxxx> > >> Subject: Re: [RFC 1/4] drm/i915/display/dp: Add DP fallback on LT > >> > >> On Tue, 06 Feb 2024, Arun R Murthy <arun.r.murthy@xxxxxxxxx> wrote: > >> > Fallback mandates on DP link training failure. This patch just covers > >> > the DP2.0 fallback sequence. > >> > > >> > TODO: Need to implement the DP1.4 fallback. > >> > > >> > Signed-off-by: Arun R Murthy <arun.r.murthy@xxxxxxxxx> > >> > --- > >> > drivers/gpu/drm/i915/display/intel_dp.c | 92 > >> > ++++++++++++++++++++++--- > >> > 1 file changed, 82 insertions(+), 10 deletions(-) > >> > > >> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c > >> > b/drivers/gpu/drm/i915/display/intel_dp.c > >> > index 10ec231acd98..82d354a6b0cd 100644 > >> > --- a/drivers/gpu/drm/i915/display/intel_dp.c > >> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > >> > @@ -104,6 +104,50 @@ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; > >> > */ > >> > static const u8 valid_dsc_slicecount[] = {1, 2, 4}; > >> > > >> > +/* DL Link Rates */ > >> > +#define UHBR20 2000000 > >> > +#define UHBR13P5 1350000 > >> > +#define UHBR10 1000000 > >> > +#define HBR3 810000 > >> > +#define HBR2 540000 > >> > +#define HBR 270000 > >> > +#define RBR 162000 > >> > + > >> > +/* DP Lane Count */ > >> > +#define LANE_COUNT_4 4 > >> > +#define LANE_COUNT_2 2 > >> > +#define LANE_COUNT_1 1 > >> > + > >> > +/* DP2.0 fallback values */ > >> > +struct dp_fallback { > >> > + u32 link_rate; > >> > + u8 lane_count; > >> > +}; > >> > + > >> > +struct dp_fallback dp2dot0_fallback[] = { > >> > + {UHBR20, LANE_COUNT_4}, > >> > + {UHBR13P5, LANE_COUNT_4}, > >> > + {UHBR20, LANE_COUNT_2}, > >> > + {UHBR10, LANE_COUNT_4}, > >> > + {UHBR13P5, LANE_COUNT_2}, > >> > + {HBR3, LANE_COUNT_4}, > >> > + {UHBR20, LANE_COUNT_1}, > >> > + {UHBR10, LANE_COUNT_2}, > >> > + {HBR2, LANE_COUNT_4}, > >> > + {UHBR13P5, LANE_COUNT_1}, > >> > + {HBR3, LANE_COUNT_2}, > >> > + {UHBR10, LANE_COUNT_1}, > >> > + {HBR2, LANE_COUNT_2}, > >> > + {HBR, LANE_COUNT_4}, > >> > + {HBR3, LANE_COUNT_1}, > >> > + {RBR, LANE_COUNT_4}, > >> > + {HBR2, LANE_COUNT_1}, > >> > + {HBR, LANE_COUNT_2}, > >> > + {RBR, LANE_COUNT_2}, > >> > + {HBR, LANE_COUNT_1}, > >> > + {RBR, LANE_COUNT_1}, > >> > +}; > >> > + > >> > /** > >> > * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or > >> PCH) > >> > * @intel_dp: DP struct > >> > @@ -299,6 +343,19 @@ static int intel_dp_common_len_rate_limit(const > >> struct intel_dp *intel_dp, > >> > intel_dp->num_common_rates, max_rate); > >> } > >> > > >> > +static bool intel_dp_link_rate_supported(struct intel_dp *intel_dp, > >> > +u32 link_rate) { > >> > + u8 i; > >> > + > >> > + for (i = 0; i < ARRAY_SIZE(intel_dp->common_rates); i++) { > >> > + if (intel_dp->common_rates[i] == link_rate) > >> > + return true; > >> > + else > >> > + continue; > >> > + } > >> > + return false; > >> > +} > >> > + > >> > static int intel_dp_common_rate(struct intel_dp *intel_dp, int index) > >> > { > >> > if (drm_WARN_ON(&dp_to_i915(intel_dp)->drm, > >> > @@ -671,15 +728,6 @@ int intel_dp_get_link_train_fallback_values(struct > >> intel_dp *intel_dp, > >> > struct drm_i915_private *i915 = dp_to_i915(intel_dp); > >> > int index; > >> > > >> > - /* > >> > - * TODO: Enable fallback on MST links once MST link compute can > >> handle > >> > - * the fallback params. > >> > - */ > >> > - if (intel_dp->is_mst) { > >> > - drm_err(&i915->drm, "Link Training Unsuccessful\n"); > >> > - return -1; > >> > - } > >> > - > >> > >> By removing this, the claim is both 8b/10b and 128b/132b DP MST link training > >> fallbacks work... > > Yes! This series focuses on the fallback mandates mentioned in DP2.1 spec and doesn't fallback from MST to SST or vicecersa. > > Hence if it is MST the fallback will be within MST and if its SST the fallback will be within SST. > > > >> > >> > if (intel_dp_is_edp(intel_dp) && !intel_dp->use_max_params) { > >> > drm_dbg_kms(&i915->drm, > >> > "Retrying Link training for eDP with max > >> parameters\n"); @@ > >> > -687,6 +735,31 @@ int intel_dp_get_link_train_fallback_values(struct > >> intel_dp *intel_dp, > >> > return 0; > >> > } > >> > > >> > + /* DP fallback values */ > >> > + if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & > >> > +DP_CAP_ANSI_128B132B) { > >> > >> ...but this only addresses 128b/132b, and the 8b/10b MST drops to the existing > >> SST fallback path. > > Yes! As said above this fallback is based on fallback mandates mentioned in DP2.1 spec in Table 3.31 and Figure 3-52 which focuses on reducing the link rate/lance count and nothing to with MST/SST > > > >> > >> And with the current code, DP_CAP_ANSI_128B132B does not decide whether > >> we use DP MST or not. So this will also cover 8b/10b fallback for displays that > >> support 128b/132b but have DP_MSTM_CAP == 0. > > > > Yes, the series doent depend on MST and SST and doest fallback from MST to SST or viceversa. > > What I'm saying is, this changes the way 8b/10b link training fallback > is handled. > > First, it starts handling 8b/10b MST link training fallback. > > Second, it changes the way 8b/10b *and* 128b/132b *and* SST *and* MST > link training fallback is handled for all displays that support > 128b/132b channel coding. > > That's *wildly* too much in one patch. > > It also duplicates the existing code in the same function, with a > different mechanism. We don't want to have two different ways to do > this, and of all things based on sink's 128b/132b cap. Just one. > > > > >> > >> > + for(index = 0; index < ARRAY_SIZE(dp2dot0_fallback); index++) > >> { > >> > + if (link_rate == dp2dot0_fallback[index].link_rate && > >> > + lane_count == > >> dp2dot0_fallback[index].lane_count) { > >> > + for(index += 1; index < > >> ARRAY_SIZE(dp2dot0_fallback); index++) { > >> > >> I honestly do not understand the double looping here, and how index is > >> managed. > > The first loop is to find the present link rate and lane count in the fallback table. Once we find this, we will have to traverse from that index below to get the next fallback link rate and lane count. The second loop is now to traverse from this index to see the supported link rate and lane count. > > For ex: if the link rate is 10Gbps and lane count is 4. First loop is to find this in the fallback table, index would be 3. Then next loop is to traverse from this index 3 to find the fallback values. This would essentially be UHBR13P5 lane count 2. But MTL doesn' support this. Hence will have to move index by 1 to get UHBR10 lane count 2. This second loop will be used for this purpose. > > Needs abstractions i.e. more functions instead of trying to make it all > happen in one loop. > > > > >> > >> > + if > >> (intel_dp_link_rate_supported(intel_dp, > >> > + > >> dp2dot0_fallback[index].link_rate)) { > >> > + > >> intel_dp_set_link_params(intel_dp, > >> > + > >> dp2dot0_fallback[index].link_rate, > >> > + > >> dp2dot0_fallback[index].lane_count); > >> > >> intel_dp_set_link_params() is supposed to be called in the DP encoder (pre- > >> )enable paths to set the link rates. If you do it here, the subsequent enable will > >> just overwrite whatever you did here. > > This is taken care of so as to not override and retain this fallback value. > > I don't understand. > > > > >> > >> The mechanism in this function should be to to adjust intel_dp->max_link_rate > >> and intel_dp->max_link_lane_count, and then the caller will send an uevent to > >> have the userspace do everything again, but with reduced max values. > >> > > If falling back within UHBR rate, so with a mode that supports the new fallback link rate then we don't essentially have to send uevent to user and new modeset may not be required. > > For Ex: the link rate is 20Gbps with mode 6k, Link training fails. So with the new fallback linkrate falling within UHBR need not do a modeset. Only if the fallback link rate falls to HBR rate for which 6k is not supported, only then uevent will be sent to user. > > For SST paths we'll always choose the optimal link parameters, and the > mode will not fit if we have to reduce the parameters. And as I just > explained, your changes impact SST paths as well. > > For MST we'll start with max parameters, so yeah there's a possibility > we could reduce the link parameters without having to reduce the > mode. However, I'm inclined to always go through userspace here, using > the same tested paths for link training failures. This will also give > userspace some form of transparency into what is going on, and why an > additional MST stream might not fit when it should. Sudden loss of link -> try a blind retrain: This is rather sketchy as we don't go through the full modeset sequence. Probably should replace this by either just always punting to userspace, or by just doing a proper atomic commit with the current parameters from a work. I'm not sure all userspace/fb-helper handle everything correctly so might still want to keep this in kernel... If link training fails then reduce link parms and punt to userspace: This could in theory also try a blind modeset in kernel first and if that fails then punt to userspace. Again the concern might be that not all userspace is perhaps very good, but I might be wrong about that. Anyways all of that is kinda orthogonal stuff to just getting MST to reduce its link rate. For that I think we should just need: a) remove the MST check from the fallback stuff b) handle all the MST connectors on the same link in the retry work -- Ville Syrjälä Intel