Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 204474a6 authored by Lyude Paul's avatar Lyude Paul Committed by Jani Nikula
Browse files

drm/i915: Pass down rc in intel_encoder->compute_config()



Something that I completely missed when implementing the new MST VCPI
atomic helpers is that with those helpers, there's technically a chance
of us having to grab additional modeset locks in ->compute_config() and
furthermore, that means we have the potential to hit a normal modeset
deadlock. However, because ->compute_config() only returns a bool this
means we can't return -EDEADLK when we need to drop locks and try again
which means we end up just failing the atomic check permanently. Whoops.

So, fix this by modifying ->compute_config() to pass down an actual
error code instead of a bool so that the atomic check can be restarted
on modeset deadlocks.

Thanks to Ville Syrjälä for pointing this out!

Changes since v1:
* Add some newlines
* Return only -EINVAL from hsw_crt_compute_config()
* Propogate return code from intel_dp_compute_dsc_params()
* Change all of the intel_dp_compute_link_config*() variants
* Don't miss if (hdmi_port_clock_valid()) branch in
  intel_hdmi_compute_config()

[Cherry-picked from drm-misc-next to drm-intel-next-queued to fix
 linux-next & drm-tip conflict, while waiting for proper propagation of
 the DP MST series that this commit fixes. In hindsight, a topic branch
 might have been a better approach for it.]

Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Fixes: eceae147 ("drm/dp_mst: Start tracking per-port VCPI allocations")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109320


Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190115200800.3121-1-lyude@redhat.com


(cherry picked from commit 96550555)
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Acked-by: default avatarDaniel Vetter <daniel@ffwll.ch>
parent 9e267d28
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1188,7 +1188,7 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder,
	pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
}

static bool gen11_dsi_compute_config(struct intel_encoder *encoder,
static int gen11_dsi_compute_config(struct intel_encoder *encoder,
				    struct intel_crtc_state *pipe_config,
				    struct drm_connector_state *conn_state)
{
@@ -1215,7 +1215,7 @@ static bool gen11_dsi_compute_config(struct intel_encoder *encoder,
	pipe_config->clock_set = true;
	pipe_config->port_clock = intel_dsi_bitrate(intel_dsi) / 5;

	return true;
	return 0;
}

static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder,
+18 −17
Original line number Diff line number Diff line
@@ -345,7 +345,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
	return MODE_OK;
}

static bool intel_crt_compute_config(struct intel_encoder *encoder,
static int intel_crt_compute_config(struct intel_encoder *encoder,
				    struct intel_crtc_state *pipe_config,
				    struct drm_connector_state *conn_state)
{
@@ -353,13 +353,14 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
		&pipe_config->base.adjusted_mode;

	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
		return false;
		return -EINVAL;

	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
	return true;

	return 0;
}

static bool pch_crt_compute_config(struct intel_encoder *encoder,
static int pch_crt_compute_config(struct intel_encoder *encoder,
				  struct intel_crtc_state *pipe_config,
				  struct drm_connector_state *conn_state)
{
@@ -367,15 +368,15 @@ static bool pch_crt_compute_config(struct intel_encoder *encoder,
		&pipe_config->base.adjusted_mode;

	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
		return false;
		return -EINVAL;

	pipe_config->has_pch_encoder = true;
	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;

	return true;
	return 0;
}

static bool hsw_crt_compute_config(struct intel_encoder *encoder,
static int hsw_crt_compute_config(struct intel_encoder *encoder,
				  struct intel_crtc_state *pipe_config,
				  struct drm_connector_state *conn_state)
{
@@ -384,12 +385,12 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
		&pipe_config->base.adjusted_mode;

	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
		return false;
		return -EINVAL;

	/* HSW/BDW FDI limited to 4k */
	if (adjusted_mode->crtc_hdisplay > 4096 ||
	    adjusted_mode->crtc_hblank_start > 4096)
		return false;
		return -EINVAL;

	pipe_config->has_pch_encoder = true;
	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -398,7 +399,7 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
	if (HAS_PCH_LPT(dev_priv)) {
		if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
			DRM_DEBUG_KMS("LPT only supports 24bpp\n");
			return false;
			return -EINVAL;
		}

		pipe_config->pipe_bpp = 24;
@@ -407,7 +408,7 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
	/* FDI must always be 2.7 GHz */
	pipe_config->port_clock = 135000 * 2;

	return true;
	return 0;
}

static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
+3 −3
Original line number Diff line number Diff line
@@ -3837,7 +3837,7 @@ intel_ddi_compute_output_type(struct intel_encoder *encoder,
	}
}

static bool intel_ddi_compute_config(struct intel_encoder *encoder,
static int intel_ddi_compute_config(struct intel_encoder *encoder,
				    struct intel_crtc_state *pipe_config,
				    struct drm_connector_state *conn_state)
{
+7 −4
Original line number Diff line number Diff line
@@ -11553,10 +11553,13 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
			continue;

		encoder = to_intel_encoder(connector_state->best_encoder);

		if (!(encoder->compute_config(encoder, pipe_config, connector_state))) {
			DRM_DEBUG_KMS("Encoder config failure\n");
			return -EINVAL;
		ret = encoder->compute_config(encoder, pipe_config,
					      connector_state);
		if (ret < 0) {
			if (ret != -EDEADLK)
				DRM_DEBUG_KMS("Encoder config failure: %d\n",
					      ret);
			return ret;
		}
	}

+38 −33
Original line number Diff line number Diff line
@@ -1819,7 +1819,7 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
}

/* Optimize link config in order: max bpp, min clock, min lanes */
static bool
static int
intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
				  struct intel_crtc_state *pipe_config,
				  const struct link_config_limits *limits)
@@ -1845,17 +1845,17 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
					pipe_config->pipe_bpp = bpp;
					pipe_config->port_clock = link_clock;

					return true;
					return 0;
				}
			}
		}
	}

	return false;
	return -EINVAL;
}

/* Optimize link config in order: max bpp, min lanes, min clock */
static bool
static int
intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
				  struct intel_crtc_state *pipe_config,
				  const struct link_config_limits *limits)
@@ -1881,13 +1881,13 @@ intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
					pipe_config->pipe_bpp = bpp;
					pipe_config->port_clock = link_clock;

					return true;
					return 0;
				}
			}
		}
	}

	return false;
	return -EINVAL;
}

static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
@@ -1905,7 +1905,7 @@ static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
	return 0;
}

static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
				       struct intel_crtc_state *pipe_config,
				       struct drm_connector_state *conn_state,
				       struct link_config_limits *limits)
@@ -1915,9 +1915,10 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
	u8 dsc_max_bpc;
	int pipe_bpp;
	int ret;

	if (!intel_dp_supports_dsc(intel_dp, pipe_config))
		return false;
		return -EINVAL;

	dsc_max_bpc = min_t(u8, DP_DSC_MAX_SUPPORTED_BPC,
			    conn_state->max_requested_bpc);
@@ -1925,7 +1926,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
	pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, dsc_max_bpc);
	if (pipe_bpp < DP_DSC_MIN_SUPPORTED_BPC * 3) {
		DRM_DEBUG_KMS("No DSC support for less than 8bpc\n");
		return false;
		return -EINVAL;
	}

	/*
@@ -1959,7 +1960,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
						     adjusted_mode->crtc_hdisplay);
		if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
			DRM_DEBUG_KMS("Compressed BPP/Slice Count not supported\n");
			return false;
			return -EINVAL;
		}
		pipe_config->dsc_params.compressed_bpp = min_t(u16,
							       dsc_max_output_bpp >> 4,
@@ -1976,16 +1977,19 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
			pipe_config->dsc_params.dsc_split = true;
		} else {
			DRM_DEBUG_KMS("Cannot split stream to use 2 VDSC instances\n");
			return false;
			return -EINVAL;
		}
	}
	if (intel_dp_compute_dsc_params(intel_dp, pipe_config) < 0) {

	ret = intel_dp_compute_dsc_params(intel_dp, pipe_config);
	if (ret < 0) {
		DRM_DEBUG_KMS("Cannot compute valid DSC parameters for Input Bpp = %d "
			      "Compressed BPP = %d\n",
			      pipe_config->pipe_bpp,
			      pipe_config->dsc_params.compressed_bpp);
		return false;
		return ret;
	}

	pipe_config->dsc_params.compression_enable = true;
	DRM_DEBUG_KMS("DP DSC computed with Input Bpp = %d "
		      "Compressed Bpp = %d Slice Count = %d\n",
@@ -1993,10 +1997,10 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
		      pipe_config->dsc_params.compressed_bpp,
		      pipe_config->dsc_params.slice_count);

	return true;
	return 0;
}

static bool
static int
intel_dp_compute_link_config(struct intel_encoder *encoder,
			     struct intel_crtc_state *pipe_config,
			     struct drm_connector_state *conn_state)
@@ -2005,7 +2009,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
	struct link_config_limits limits;
	int common_len;
	bool ret;
	int ret;

	common_len = intel_dp_common_len_rate_limit(intel_dp,
						    intel_dp->max_link_rate);
@@ -2063,10 +2067,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,

	/* enable compression if the mode doesn't fit available BW */
	DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
	if (!ret || intel_dp->force_dsc_en) {
		if (!intel_dp_dsc_compute_config(intel_dp, pipe_config,
						 conn_state, &limits))
			return false;
	if (ret || intel_dp->force_dsc_en) {
		ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
						  conn_state, &limits);
		if (ret < 0)
			return ret;
	}

	if (pipe_config->dsc_params.compression_enable) {
@@ -2091,10 +2096,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
			      intel_dp_max_data_rate(pipe_config->port_clock,
						     pipe_config->lane_count));
	}
	return true;
	return 0;
}

bool
int
intel_dp_compute_config(struct intel_encoder *encoder,
			struct intel_crtc_state *pipe_config,
			struct drm_connector_state *conn_state)
@@ -2110,6 +2115,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
		to_intel_digital_connector_state(conn_state);
	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
					   DP_DPCD_QUIRK_CONSTANT_N);
	int ret;

	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
		pipe_config->has_pch_encoder = true;
@@ -2131,8 +2137,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
				       adjusted_mode);

		if (INTEL_GEN(dev_priv) >= 9) {
			int ret;

			ret = skl_update_scaler_crtc(pipe_config);
			if (ret)
				return ret;
@@ -2147,20 +2151,21 @@ intel_dp_compute_config(struct intel_encoder *encoder,
	}

	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
		return false;
		return -EINVAL;

	if (HAS_GMCH_DISPLAY(dev_priv) &&
	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
		return false;
		return -EINVAL;

	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
		return false;
		return -EINVAL;

	pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
				  intel_dp_supports_fec(intel_dp, pipe_config);

	if (!intel_dp_compute_link_config(encoder, pipe_config, conn_state))
		return false;
	ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state);
	if (ret < 0)
		return ret;

	if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
		/*
@@ -2208,7 +2213,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,

	intel_psr_compute_config(intel_dp, pipe_config);

	return true;
	return 0;
}

void intel_dp_set_link_params(struct intel_dp *intel_dp,
Loading