> -----Original Message-----
> From: Golani, Mitulkumar Ajitkumar
> <[email protected]>
> Sent: 16 October 2026 00:27
> To: Kandpal, Suraj <[email protected]>; [email protected];
> [email protected]
> Cc: Nautiyal, Ankit K <[email protected]>; Murthy, Arun R
> <[email protected]>; Kandpal, Suraj <[email protected]>
> Subject: RE: [PATCH v4 04/10] drm/i915/dp: Add M/N ratio check for DP link
> config
> 
> 
> 
> > -----Original Message-----
> > From: Intel-gfx <[email protected]> On Behalf Of
> > Suraj Kandpal
> > Sent: 17 September 2026 10:37
> > To: [email protected]; [email protected]
> > Cc: Nautiyal, Ankit K <[email protected]>; Murthy, Arun R
> > <[email protected]>; Kandpal, Suraj <[email protected]>
> > Subject: [PATCH v4 04/10] drm/i915/dp: Add M/N ratio check for DP link
> > config
> >
> > From: Ankit Nautiyal <[email protected]>
> >
> > Introduce intel_dp_check_m_n_ratio() to validate the computed link M/N
> > ratio against the maximum allowed value, and log it if the ratio
> > exceeds the limit.
> >
> > The link config limits computed in the previous patches only restrict
> > the configurations that may be selected; this catches anything that
> > still slips through.
> >
> > Log it rather than warn about it: the link config filter already
> > excludes the configurations violating the limit, so the only way to
> > get here is with link parameters forced through debugfs, which are
> > applied after that filter. A user triggerable drm_WARN() with its
> > backtrace would be out of proportion for that.
> >
> > This check works off the M/N values as actually computed, which
> > exposes a mismatch with the prediction done while computing the
> > limits: the pixel clock there is the one before
> > intel_dp_compute_config() divides adjusted_mode-
> > >crtc_clock by the MSO link count. Divide in the prediction too, so
> > >both
> > agree. The joiner needs no such handling, as
> > intel_joiner_adjust_timings() only rewrites the pipe mode and leaves
> > the adjusted mode the link M/N is derived from untouched.
> >
> > For MST the check goes after the bpp loop rather than inside it. The
> > link M/N is computed from the pixel clock and the link symbol clock,
> > so it does not depend on the bpp being tried and the result is the same on
> every iteration.
> >
> > v2:
> > -Use the platform specific ratio limit. (Wa_14014191401) -Use the MSO
> > adjusted pixel clock when predicting the ratio, matching what the link
> > M/N is actually computed from. (Imre) -Drop the check from
> > ilk_fdi_compute_config(): it was passing dp_m_n rather than the
> > fdi_m_n it had just computed, and an FDI link cannot get anywhere near
> > the ratio limit anyway.
> > v3:
> > -Check the ratio once after the MST bpp loop instead of on every
> > iteration, the result does not depend on the bpp. (Sashiko) -Log
> > instead of warning, since the link config filter already excludes
> > these configurations and only forced link parameters can reach it.
> > (Sashiko)
> >
> > Signed-off-by: Ankit Nautiyal <[email protected]>
> > Signed-off-by: Suraj Kandpal <[email protected]>
> > ---
> >  drivers/gpu/drm/i915/display/intel_dp.c     | 37 +++++++++++++++++++--
> >  drivers/gpu/drm/i915/display/intel_dp.h     |  4 +++
> >  drivers/gpu/drm/i915/display/intel_dp_mst.c |  2 ++
> >  3 files changed, 41 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index f6a2152c4432..fbfc00101886 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -1294,6 +1294,14 @@ intel_dp_can_support_m_n(struct intel_display
> > *display,
> >     return m_n_ratio <= max_m_n_ratio;
> >  }
> >
> > +static int intel_dp_mso_pixel_clock(struct intel_dp *intel_dp, int
> > +pixel_clock) {
> > +   if (!intel_dp->mso_link_count)
> > +           return pixel_clock;
> > +
> > +   return pixel_clock / intel_dp->mso_link_count; }
> > +
> 
> These hunks fix the prediction added in "drm/i915/dp: Limit M/N ratio for DP
> SST". On its own that patch over-restricts MSO eDP by mso_link_count .
> Please squash them, together with the MSO/joiner explanation, into that
> patch so it is correct on its own, and keep this patch to the debug check.

Sure

> 
> >  static
> >  bool intel_dp_can_join(struct intel_dp *intel_dp,
> >                    int num_joined_pipes)
> > @@ -1332,6 +1340,7 @@ bool intel_dp_dotclk_valid(struct intel_display
> > *display,  bool intel_dp_mode_valid_m_n(struct intel_dp *intel_dp, int
> > pixel_clock)  {
> >     struct intel_display *display = to_intel_display(intel_dp);
> > +   int m_n_pixel_clock = intel_dp_mso_pixel_clock(intel_dp,
> > pixel_clock);
> >     struct intel_dp_link_caps_order order = {
> >             .key = INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE,
> >             .dir = INTEL_DP_LINK_CAPS_ORDER_DIR_DESC,
> > @@ -1343,7 +1352,8 @@ bool intel_dp_mode_valid_m_n(struct intel_dp
> > *intel_dp, int pixel_clock)
> >     intel_dp_link_caps_iter_start(&iter, intel_dp->link.caps, order,
> >                                   INTEL_DP_LINK_CAPS_FILTER_ALL);
> >     for_each_dp_link_config(&iter, &link_config) {
> > -           if (intel_dp_can_support_m_n(display, pixel_clock,
> > link_config.rate)) {
> > +           if (intel_dp_can_support_m_n(display, m_n_pixel_clock,
> > +                                        link_config.rate)) {
> >                     found = true;
> >
> >                     break;
> > @@ -2723,7 +2733,8 @@ intel_dp_compute_m_n_ratio_limits(struct
> > intel_dp *intel_dp,
> >     struct intel_dp_link_caps_order order =
> >             intel_dp_link_caps_connector_compute_order(connector);
> >     struct intel_dp_link_caps_filter new_filter =
> > INTEL_DP_LINK_CAPS_FILTER_NONE;
> > -   int pixel_clock = intel_dp_mode_clock(crtc_state, conn_state);
> > +   int pixel_clock = intel_dp_mso_pixel_clock(intel_dp,
> > +
> > intel_dp_mode_clock(crtc_state, conn_state));
> >     struct intel_dp_link_config link_config;
> >     struct intel_dp_link_caps_iter iter;
> >     bool found = false;
> > @@ -3382,6 +3393,24 @@ static bool can_enable_drrs(struct
> > intel_connector *connector,
> >             intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS;
> }
> >
> > +void intel_dp_check_m_n_ratio(struct intel_crtc_state *crtc_state,
> > +                         struct intel_link_m_n *m_n)
> > +{
> > +   struct intel_display *display = to_intel_display(crtc_state);
> > +   int max_m_n_ratio = intel_dp_get_max_m_n_ratio(display);
> > +   int m_n_ratio;
> > +
> > +   if (!m_n || !m_n->link_n)
> > +           return;
> > +
> > +   m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_n);
> > +
> > +   if (m_n_ratio > max_m_n_ratio)
> > +           drm_dbg_kms(display->drm,
> > +                       "Link M/N ratio (%d) exceeds max allowed (%d)\n",
> > +                       m_n_ratio, max_m_n_ratio);
> > +}
> 
> Could we reuse a small helper here, since the DIV_ROUND_UP(link_m,
> link_n) <= max check appears to duplicate intel_dp_can_support_m_n? 

I can do that.

> Also,
> are the !m_n and !m_n->link_n checks necessary, given that callers pass
> struct members and link_n is fixed at 0x80000?

Sure will drop the check

 Could the parameters be
> const as well? 

Finally, would it make sense to place this helper next to
> intel_dp_can_support_m_n ?

Can do 
> 
> > +
> >  static void
> >  intel_dp_drrs_compute_config(struct intel_connector *connector,
> >                          struct intel_crtc_state *pipe_config, @@ -3420,6
> > +3449,8 @@ intel_dp_drrs_compute_config(struct intel_connector
> > *connector,
> >                            intel_dp_bw_fec_overhead(pipe_config-
> > >fec_enable),
> >                            &pipe_config->dp_m2_n2);
> >
> > +   intel_dp_check_m_n_ratio(pipe_config, &pipe_config->dp_m2_n2);
> 
> Could we drop this check since dp_m2_n2 is computed using the same
> port_clock and its ratio should already be covered by the dp_m_n check? Or
> is this intended as a defensive check?

Sure will drop it.

> 
> > +
> >     /* FIXME: abstract this better */
> >     if (pipe_config->splitter.enable)
> >             pipe_config->dp_m2_n2.data_m *= pipe_config-
> > >splitter.link_count; @@ -3739,6 +3770,8 @@
> > intel_dp_compute_config(struct intel_atomic_state *state,
> >                                    pipe_config->port_clock,
> >                                    intel_dp_bw_fec_overhead(pipe_config-
> > >fec_enable),
> >                                    &pipe_config->dp_m_n);
> > +
> > +           intel_dp_check_m_n_ratio(pipe_config, &pipe_config-
> > >dp_m_n);
> >     }
> >
> >     ret = intel_dp_compute_min_hblank(pipe_config, conn_state); diff --
> > git a/drivers/gpu/drm/i915/display/intel_dp.h
> > b/drivers/gpu/drm/i915/display/intel_dp.h
> > index aa58833a405b..4c975358ab96 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > @@ -26,6 +26,7 @@ struct intel_display;  struct intel_dp;  struct
> > intel_dp_link_config;  struct intel_encoder;
> > +struct intel_link_m_n;
> >
> >  struct link_config_limits {
> >     struct intel_dp_link_caps_filter link_config_filter; @@ -244,4 +245,7
> > @@ bool intel_dp_mode_valid_m_n(struct intel_dp *intel_dp, int
> > pixel_clock);  int intel_dp_link_init(struct intel_dp *intel_dp);  void
> > intel_dp_link_cleanup(struct intel_dp *intel_dp);
> >
> > +void intel_dp_check_m_n_ratio(struct intel_crtc_state *crtc_state,
> > +                         struct intel_link_m_n *m_n);
> > +
> >  #endif /* __INTEL_DP_H__ */
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > index 823fe99ca0a1..6d2e234a9e9b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> > @@ -429,6 +429,8 @@ int intel_dp_mtp_tu_compute_config(struct
> intel_dp
> > *intel_dp,
> >             return slots;
> >     }
> >
> > +   intel_dp_check_m_n_ratio(crtc_state, &crtc_state->dp_m_n);
> > +
> >     if (!dsc)
> >             crtc_state->pipe_bpp = fxp_q4_to_int(bpp_x16);
> >     else
> > --
> > 2.34.1

Reply via email to