Op 24-05-18 om 14:54 schreef Ville Syrjala: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > When encountering a connector with the scaling mode property both > intel and modesetting ddxs sometimes add tons of DBLSCAN modes > to the output's mode list. The idea presumably being that since the > output will be going through the panel fitter anyway we can pretend > to use any kind of mode. > > Sadly that means we can't reject user modes with the DBLSCAN flag > until we know whether we're going to be using the panel's native > mode or the user mode directly. Doing otherwise means X clients using > xf86vidmode/xrandr will get a protocol error (and often self > terminate as a result) when the kernel refuses to use the requested > mode with the DBLSCAN flag. > > To undo the regression we'll move the DBLSCAN checks into the > connector->mode_valid() and encoder->compute_config() hooks. > > Cc: Vito Caputo <vcaputo@xxxxxxxxxxx> > Reported-by: Vito Caputo <vcaputo@xxxxxxxxxxx> > Fixes: e995ca0b8139 ("drm/i915: Provide a device level .mode_valid() hook") > References: https://lkml.org/lkml/2018/5/21/715 > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/intel_crt.c | 20 ++++++++++++++++++++ > drivers/gpu/drm/i915/intel_display.c | 16 +++++++++++++--- > drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ > drivers/gpu/drm/i915/intel_dp_mst.c | 6 ++++++ > drivers/gpu/drm/i915/intel_dsi.c | 6 ++++++ > drivers/gpu/drm/i915/intel_dvo.c | 6 ++++++ > drivers/gpu/drm/i915/intel_hdmi.c | 6 ++++++ > drivers/gpu/drm/i915/intel_lvds.c | 5 +++++ > drivers/gpu/drm/i915/intel_sdvo.c | 6 ++++++ > drivers/gpu/drm/i915/intel_tv.c | 12 ++++++++++-- > 10 files changed, 84 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c > index 211d601cd1b1..95aa29cf2d9c 100644 > --- a/drivers/gpu/drm/i915/intel_crt.c > +++ b/drivers/gpu/drm/i915/intel_crt.c > @@ -304,6 +304,9 @@ intel_crt_mode_valid(struct drm_connector *connector, > int max_dotclk = dev_priv->max_dotclk_freq; > int max_clock; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > if (mode->clock < 25000) > return MODE_CLOCK_LOW; > > @@ -337,6 +340,12 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config, > struct drm_connector_state *conn_state) > { > + struct drm_display_mode *adjusted_mode = > + &pipe_config->base.adjusted_mode; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > return true; > } > > @@ -344,6 +353,12 @@ static bool pch_crt_compute_config(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config, > struct drm_connector_state *conn_state) > { > + struct drm_display_mode *adjusted_mode = > + &pipe_config->base.adjusted_mode; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > pipe_config->has_pch_encoder = true; > > return true; > @@ -354,6 +369,11 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder, > struct drm_connector_state *conn_state) > { > struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > + struct drm_display_mode *adjusted_mode = > + &pipe_config->base.adjusted_mode; > + > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > > pipe_config->has_pch_encoder = true; > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 8b385176ce3c..02651298a99b 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -14443,12 +14443,22 @@ static enum drm_mode_status > intel_mode_valid(struct drm_device *dev, > const struct drm_display_mode *mode) > { > + /* > + * Can't reject DBLSCAN here because Xorg ddxen can add piles > + * of DBLSCAN modes to the output's mode list when they detect > + * the scaling mode property on the connector. And they don't > + * ask the kernel to validate those modes in any way until > + * modeset time at which point the client gets a protocol error. > + * So in order to not upset those clients we silently ignore the > + * DBLSCAN flag on such connectors. For other connectors we will > + * reject modes with the DBLSCAN flag in encoder->compute_config(). > + * And we always reject DBLSCAN modes in connector->mode_valid() > + * as we never want such modes on the connector's mode list. > + */ > + > if (mode->vscan > 1) > return MODE_NO_VSCAN; > > - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > - return MODE_NO_DBLESCAN; > - > if (mode->flags & DRM_MODE_FLAG_HSKEW) > return MODE_H_ILLEGAL; > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index ce07bd794aed..91885f2500af 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -420,6 +420,9 @@ intel_dp_mode_valid(struct drm_connector *connector, > int max_rate, mode_rate, max_lanes, max_link_clock; > int max_dotclk; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > max_dotclk = intel_dp_downstream_max_dotclock(intel_dp); > > if (intel_dp_is_edp(intel_dp) && fixed_mode) { > @@ -1862,6 +1865,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, > conn_state->scaling_mode); > } > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && > adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) > return false; > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c > index 9e6956c08688..5890500a3a8b 100644 > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > @@ -48,6 +48,9 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, > bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, > DP_DPCD_QUIRK_LIMITED_M_N); > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > pipe_config->has_pch_encoder = false; > bpp = 24; > if (intel_dp->compliance.test_data.bpc) { > @@ -366,6 +369,9 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, > if (!intel_dp) > return MODE_ERROR; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > max_link_clock = intel_dp_max_link_rate(intel_dp); > max_lanes = intel_dp_max_lane_count(intel_dp); > > diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c > index cf39ca90d887..f349b3920199 100644 > --- a/drivers/gpu/drm/i915/intel_dsi.c > +++ b/drivers/gpu/drm/i915/intel_dsi.c > @@ -326,6 +326,9 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, > conn_state->scaling_mode); > } > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > /* DSI uses short packets for sync events, so clear mode flags for DSI */ > adjusted_mode->flags = 0; > > @@ -1266,6 +1269,9 @@ intel_dsi_mode_valid(struct drm_connector *connector, > > DRM_DEBUG_KMS("\n"); > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > if (fixed_mode) { > if (mode->hdisplay > fixed_mode->hdisplay) > return MODE_PANEL; > diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c > index 7b942b6c1700..27f16db8953a 100644 > --- a/drivers/gpu/drm/i915/intel_dvo.c > +++ b/drivers/gpu/drm/i915/intel_dvo.c > @@ -215,6 +215,9 @@ intel_dvo_mode_valid(struct drm_connector *connector, > int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; > int target_clock = mode->clock; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > /* XXX: Validate clock range */ > > if (fixed_mode) { > @@ -250,6 +253,9 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, > if (fixed_mode) > intel_fixed_panel_mode(fixed_mode, adjusted_mode); > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > return true; > } > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c > index 0ca4cc877520..47e6cca3e208 100644 > --- a/drivers/gpu/drm/i915/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > @@ -1544,6 +1544,9 @@ intel_hdmi_mode_valid(struct drm_connector *connector, > bool force_dvi = > READ_ONCE(to_intel_digital_connector_state(connector->state)->force_audio) == HDMI_AUDIO_OFF_DVI; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > clock = mode->clock; > > if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) > @@ -1664,6 +1667,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, > int desired_bpp; > bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI; > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink; > > if (pipe_config->has_hdmi_sink) > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c > index bacad88ad7ae..5b4a35299531 100644 > --- a/drivers/gpu/drm/i915/intel_lvds.c > +++ b/drivers/gpu/drm/i915/intel_lvds.c > @@ -378,6 +378,8 @@ intel_lvds_mode_valid(struct drm_connector *connector, > struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; > int max_pixclk = to_i915(connector->dev)->max_dotclk_freq; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > if (mode->hdisplay > fixed_mode->hdisplay) > return MODE_PANEL; > if (mode->vdisplay > fixed_mode->vdisplay) > @@ -427,6 +429,9 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, > intel_fixed_panel_mode(intel_connector->panel.fixed_mode, > adjusted_mode); > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > if (HAS_PCH_SPLIT(dev_priv)) { > pipe_config->has_pch_encoder = true; > > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c > index a02e4d73c7a4..e6a64b3ecd91 100644 > --- a/drivers/gpu/drm/i915/intel_sdvo.c > +++ b/drivers/gpu/drm/i915/intel_sdvo.c > @@ -1160,6 +1160,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, > adjusted_mode); > } > > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > /* > * Make the CRTC code factor in the SDVO pixel multiplier. The > * SDVO device will factor out the multiplier during mode_set. > @@ -1631,6 +1634,9 @@ intel_sdvo_mode_valid(struct drm_connector *connector, > struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); > int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > if (intel_sdvo->pixel_clock_min > mode->clock) > return MODE_CLOCK_LOW; > > diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c > index 99bc2368dda0..24dc368fdaa1 100644 > --- a/drivers/gpu/drm/i915/intel_tv.c > +++ b/drivers/gpu/drm/i915/intel_tv.c > @@ -846,6 +846,9 @@ intel_tv_mode_valid(struct drm_connector *connector, > const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state); > int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; > > + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return MODE_NO_DBLESCAN; > + > if (mode->clock > max_dotclk) > return MODE_CLOCK_HIGH; > > @@ -873,16 +876,21 @@ intel_tv_compute_config(struct intel_encoder *encoder, > struct drm_connector_state *conn_state) > { > const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state); > + struct drm_display_mode *adjusted_mode = > + &pipe_config->base.adjusted_mode; > > if (!tv_mode) > return false; > > - pipe_config->base.adjusted_mode.crtc_clock = tv_mode->clock; > + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) > + return false; > + > + adjusted_mode->crtc_clock = tv_mode->clock; > DRM_DEBUG_KMS("forcing bpc to 8 for TV\n"); > pipe_config->pipe_bpp = 8*3; > > /* TV has it's own notion of sync and other mode flags, so clear them. */ > - pipe_config->base.adjusted_mode.flags = 0; > + adjusted_mode->flags = 0; > > /* > * FIXME: We don't check whether the input mode is actually what we want Reviewed-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx