All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc.
@ 2016-07-28 14:50 ville.syrjala
  2016-07-28 14:50 ` [PATCH 01/12] drm/i915: Ignore initial lid state for eDP ville.syrjala
                   ` (14 more replies)
  0 siblings, 15 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Ok, so while looking at the upfront link training stuff, it became obvious
that we needs to do something about the link training stuff that we have
in hpd_pulse currently. The thing is, you can't grab any modeset locks from
that work since it could lead to a deadlock with MST sideband stuff.
So here's a quick attempt at moving the stuff over to the hotplug work.

I've included a few other things at the start just to make the
surroundings a little less broken (some of that I've posted before).
And there are a few potentially helpful snippets at the end too.
The main meat is in the middle.

Entire series avaialable here:
git://github.com/vsyrjala/linux.git dp_retrain_fixes

Ville Syrjälä (12):
  drm/i915: Ignore initial lid state for eDP
  drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
  drm/i915: Avoid mixing up SST and MST in DDI setup
  drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  drm/i915: Track active streams also for DP SST
  drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
  drm/i915: Move DP link retraining into intel_dp_detect()
  drm/i915: Skip dpcd/edid read unless there was a long hpd
  drm/i915: Remove useless rate_to_index() usage
  drm/i915: Allow rate_to_index() to return non-exact matches
  drm/i915: Don't try to ack sink irqs when there are none
  drm/i915: Add encoder .sync_state() hook

 drivers/gpu/drm/i915/intel_ddi.c     |  35 ++--
 drivers/gpu/drm/i915/intel_display.c |  14 ++
 drivers/gpu/drm/i915/intel_dp.c      | 390 ++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_dp_mst.c  |  16 +-
 drivers/gpu/drm/i915/intel_drv.h     |  12 +-
 5 files changed, 255 insertions(+), 212 deletions(-)

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 01/12] drm/i915: Ignore initial lid state for eDP
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-28 15:47   ` Chris Wilson
  2016-07-28 14:50 ` [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP ville.syrjala
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we try to check the lid status to see whether eDP is connected
or not. However we ignore the result anyway, and we have no lid notifier
to fire off uevents, so let's just ignore the lid stuff for eDP
entirely.

While at it, rip out the eDP case from intel_dp_detect_dpcd() since we
never call that thing with eDP displays anyway.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 21b04c3eda41..1fe9bb745de5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3965,9 +3965,6 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	if (!intel_dp_get_dpcd(intel_dp))
 		return connector_status_disconnected;
 
-	if (is_edp(intel_dp))
-		return connector_status_connected;
-
 	/* if there's no downstream port, we're done */
 	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
 		return connector_status_connected;
@@ -4003,19 +4000,6 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	return connector_status_disconnected;
 }
 
-static enum drm_connector_status
-edp_detect(struct intel_dp *intel_dp)
-{
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	enum drm_connector_status status;
-
-	status = intel_panel_detect(dev);
-	if (status == connector_status_unknown)
-		status = connector_status_connected;
-
-	return status;
-}
-
 static bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
 				       struct intel_digital_port *port)
 {
@@ -4223,9 +4207,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
 	intel_display_power_get(to_i915(dev), power_domain);
 
-	/* Can't disconnect eDP, but you can close the lid... */
 	if (is_edp(intel_dp))
-		status = edp_detect(intel_dp);
+		status = connector_status_connected;
 	else if (intel_digital_port_connected(to_i915(dev),
 					      dp_to_dig_port(intel_dp)))
 		status = intel_dp_detect_dpcd(intel_dp);
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
  2016-07-28 14:50 ` [PATCH 01/12] drm/i915: Ignore initial lid state for eDP ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-28 17:30   ` Chris Wilson
  2016-07-29 13:52   ` [PATCH v3 " ville.syrjala
  2016-07-28 14:50 ` [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup ville.syrjala
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we re-read a bunch of static eDP panel caps from the DPCD
over and over again. Let's do it only once to save some time and effort.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 121 +++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1fe9bb745de5..8c38e3483989 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3394,12 +3394,70 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 	intel_dp->DP = DP;
 }
 
+static void
+intel_edp_get_dpcd(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
+
+	/* Check if the panel supports PSR */
+	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
+			 intel_dp->psr_dpcd,
+			 sizeof(intel_dp->psr_dpcd));
+	if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
+		dev_priv->psr.sink_support = true;
+		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
+	}
+
+	if (INTEL_GEN(dev_priv) >= 9 &&
+	    (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
+		uint8_t frame_sync_cap;
+
+		dev_priv->psr.sink_support = true;
+		drm_dp_dpcd_read(&intel_dp->aux,
+				 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
+				 &frame_sync_cap, 1);
+		dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
+		/* PSR2 needs frame sync as well */
+		dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
+		DRM_DEBUG_KMS("PSR2 %s on sink",
+			      dev_priv->psr.psr2_support ? "supported" : "not supported");
+	}
+
+	/* Read the eDP Display control capabilities registers */
+	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
+	    drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
+			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) ==
+			     sizeof(intel_dp->edp_dpcd)))
+		DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
+			      intel_dp->edp_dpcd);
+
+	/* Intermediate frequency support */
+	if (intel_dp->edp_dpcd[0] >= 0x03) { /* eDp v1.4 or higher */
+		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
+		int i;
+
+		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
+				sink_rates, sizeof(sink_rates));
+
+		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
+			int val = le16_to_cpu(sink_rates[i]);
+
+			if (val == 0)
+				break;
+
+			/* Value read is in kHz while drm clock is saved in deca-kHz */
+			intel_dp->sink_rates[i] = (val * 200) / 10;
+		}
+		intel_dp->num_sink_rates = i;
+	}
+}
+
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	bool init_edp_dpcd = is_edp(intel_dp) &&
+		intel_dp->dpcd[DP_DPCD_REV] == 0;
 
 	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
 			     sizeof(intel_dp->dpcd)) < 0)
@@ -3431,66 +3489,13 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp) && !intel_dp->sink_count)
 		return false;
 
-	/* Check if the panel supports PSR */
-	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
-	if (is_edp(intel_dp)) {
-		drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
-				 intel_dp->psr_dpcd,
-				 sizeof(intel_dp->psr_dpcd));
-		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
-			dev_priv->psr.sink_support = true;
-			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
-		}
-
-		if (INTEL_INFO(dev)->gen >= 9 &&
-			(intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
-			uint8_t frame_sync_cap;
-
-			dev_priv->psr.sink_support = true;
-			drm_dp_dpcd_read(&intel_dp->aux,
-					 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
-					 &frame_sync_cap, 1);
-			dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
-			/* PSR2 needs frame sync as well */
-			dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
-			DRM_DEBUG_KMS("PSR2 %s on sink",
-				dev_priv->psr.psr2_support ? "supported" : "not supported");
-		}
-
-		/* Read the eDP Display control capabilities registers */
-		memset(intel_dp->edp_dpcd, 0, sizeof(intel_dp->edp_dpcd));
-		if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
-				(drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
-						intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) ==
-								sizeof(intel_dp->edp_dpcd)))
-			DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
-					intel_dp->edp_dpcd);
-	}
+	if (init_edp_dpcd)
+		intel_edp_get_dpcd(intel_dp);
 
 	DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
 		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
 		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
 
-	/* Intermediate frequency support */
-	if (is_edp(intel_dp) && (intel_dp->edp_dpcd[0] >= 0x03)) { /* eDp v1.4 or higher */
-		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
-		int i;
-
-		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
-				sink_rates, sizeof(sink_rates));
-
-		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
-			int val = le16_to_cpu(sink_rates[i]);
-
-			if (val == 0)
-				break;
-
-			/* Value read is in kHz while drm clock is saved in deca-kHz */
-			intel_dp->sink_rates[i] = (val * 200) / 10;
-		}
-		intel_dp->num_sink_rates = i;
-	}
-
 	intel_dp_print_rates(intel_dp);
 
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
  2016-07-28 14:50 ` [PATCH 01/12] drm/i915: Ignore initial lid state for eDP ville.syrjala
  2016-07-28 14:50 ` [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:16   ` Daniel Vetter
  2016-08-01  9:24   ` Maarten Lankhorst
  2016-07-28 14:50 ` [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port ville.syrjala
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The MST vs. SST selection should depend purely on the choice of the
connector/encoder. So don't try to determine the correct DDI mode
based on the intel_dp->is_mst, which simply tells us whether the sink
is in MST mode or not. Instead derive the information from the encoder
type. Since the link training code deals in non-fake encoders, we'll
also need to keep a second copy of that information around, which we'll
now designate as 'link_mst'.

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 21 +++------------------
 drivers/gpu/drm/i915/intel_dp.c  |  1 +
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 3 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index dd1d6fe12297..3b3a0a808477 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1111,7 +1111,6 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
-	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum pipe pipe = intel_crtc->pipe;
@@ -1177,29 +1176,15 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
 			temp |= TRANS_DDI_MODE_SELECT_HDMI;
 		else
 			temp |= TRANS_DDI_MODE_SELECT_DVI;
-
 	} else if (type == INTEL_OUTPUT_ANALOG) {
 		temp |= TRANS_DDI_MODE_SELECT_FDI;
 		temp |= (intel_crtc->config->fdi_lanes - 1) << 1;
-
 	} else if (type == INTEL_OUTPUT_DP ||
 		   type == INTEL_OUTPUT_EDP) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-		if (intel_dp->is_mst) {
-			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
-		} else
-			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
-
+		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
 		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
 	} else if (type == INTEL_OUTPUT_DP_MST) {
-		struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
-
-		if (intel_dp->is_mst) {
-			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
-		} else
-			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
-
+		temp |= TRANS_DDI_MODE_SELECT_DP_MST;
 		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
 	} else {
 		WARN(1, "Invalid encoder type %d for pipe %c\n",
@@ -2105,7 +2090,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
 
 	val = DP_TP_CTL_ENABLE |
 	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
-	if (intel_dp->is_mst)
+	if (intel_dp->link_mst)
 		val |= DP_TP_CTL_MODE_MST;
 	else {
 		val |= DP_TP_CTL_MODE_SST;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8c38e3483989..0096c651c21f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1651,6 +1651,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
 {
 	intel_dp->link_rate = pipe_config->port_clock;
 	intel_dp->lane_count = pipe_config->lane_count;
+	intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
 }
 
 static void intel_dp_prepare(struct intel_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e74d851868c5..70d7f33d6747 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -852,6 +852,7 @@ struct intel_dp {
 	int link_rate;
 	uint8_t lane_count;
 	uint8_t sink_count;
+	bool link_mst;
 	bool has_audio;
 	bool detect_done;
 	enum hdmi_force_audio force_audio;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (2 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:19   ` Daniel Vetter
  2016-08-01  9:28   ` Maarten Lankhorst
  2016-07-28 14:50 ` [PATCH 05/12] drm/i915: Track active streams also for DP SST ville.syrjala
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We can't mix MST with SST/HDMI on the same physical port, so we'll need
to reject such configurations in check_digital_port_conflicts(). Nothing
else will prevent this as MST has its fake encoders and its own connectors
so the cloning checks won't catch this.

The same digital port can be used multiple times, but only if all the
encoders involved are MST encoders, so we only want to check MST vs.
SST/HDMI, not MST vs. MST. And SST/HDMI vs. SST/HDMI we already check.

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c4c1c85366de..a6699c76bef3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12305,6 +12305,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct drm_connector *connector;
 	unsigned int used_ports = 0;
+	unsigned int used_mst_ports = 0;
 
 	/*
 	 * Walk the connector list instead of the encoder
@@ -12341,11 +12342,20 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 				return false;
 
 			used_ports |= port_mask;
+			break;
+		case INTEL_OUTPUT_DP_MST:
+			used_mst_ports |=
+				1 << enc_to_mst(&encoder->base)->primary->port;
+			break;
 		default:
 			break;
 		}
 	}
 
+	/* can't mix MST and SST/HDMI on the same port */
+	if (used_ports & used_mst_ports)
+		return false;
+
 	return true;
 }
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 05/12] drm/i915: Track active streams also for DP SST
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (3 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:22   ` Daniel Vetter
  2016-07-28 14:50 ` [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails ville.syrjala
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

s/active_mst_links/active_streams/ and use it also for SST. We can then
use this information in the hpd handling to see if the link is active
or not, and thus whether we may need to retrain.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c    | 10 ++++++++++
 drivers/gpu/drm/i915/intel_dp.c     |  8 +++++++-
 drivers/gpu/drm/i915/intel_dp_mst.c | 16 ++++++++--------
 drivers/gpu/drm/i915/intel_drv.h    |  2 +-
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 3b3a0a808477..bc188ee6e37f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1616,6 +1616,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
 		intel_ddi_init_dp_buf_reg(intel_encoder);
 
+		WARN_ON(intel_dp->active_streams != 0);
+		intel_dp->active_streams++;
+
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 		intel_dp_start_link_train(intel_dp);
 		if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
@@ -1733,6 +1736,13 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 		intel_psr_disable(intel_dp);
 		intel_edp_backlight_off(intel_dp);
 	}
+
+	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		intel_dp->active_streams--;
+		WARN_ON(intel_dp->active_streams != 0);
+	}
 }
 
 bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0096c651c21f..3a9c5d3b5c66 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2685,6 +2685,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 				    lane_mask);
 	}
 
+	WARN_ON(intel_dp->active_streams != 0);
+	intel_dp->active_streams++;
+
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
@@ -3344,6 +3347,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("\n");
 
+	intel_dp->active_streams--;
+	WARN_ON(intel_dp->active_streams != 0);
+
 	if ((IS_GEN7(dev) && port == PORT_A) ||
 	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
@@ -3826,7 +3832,7 @@ go_again:
 		if (bret == true) {
 
 			/* check link status - esi[10] = 0x200c */
-			if (intel_dp->active_mst_links &&
+			if (intel_dp->active_streams &&
 			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
 				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
 				intel_dp_start_link_train(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 68a005d729e9..857cfa6928b3 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -99,7 +99,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	int ret;
 
-	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
 
 	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
 
@@ -115,7 +115,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
 	struct intel_digital_port *intel_dig_port = intel_mst->primary;
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 
-	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
 
 	/* this can fail */
 	drm_dp_check_act_status(&intel_dp->mst_mgr);
@@ -124,10 +124,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
 
 	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
 
-	intel_dp->active_mst_links--;
+	intel_dp->active_streams--;
 
 	intel_mst->connector = NULL;
-	if (intel_dp->active_mst_links == 0) {
+	if (intel_dp->active_streams == 0) {
 		intel_dig_port->base.post_disable(&intel_dig_port->base);
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
 	}
@@ -165,11 +165,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
 	 */
 	found->encoder = encoder;
 
-	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
 
 	intel_mst->connector = found;
 
-	if (intel_dp->active_mst_links == 0) {
+	if (intel_dp->active_streams == 0) {
 		intel_prepare_ddi_buffer(&intel_dig_port->base);
 
 		intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
@@ -193,7 +193,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
 	}
 
 
-	intel_dp->active_mst_links++;
+	intel_dp->active_streams++;
 	temp = I915_READ(DP_TP_STATUS(port));
 	I915_WRITE(DP_TP_STATUS(port), temp);
 
@@ -210,7 +210,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
 	enum port port = intel_dig_port->port;
 	int ret;
 
-	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
 
 	if (intel_wait_for_register(dev_priv,
 				    DP_TP_STATUS(port),
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 70d7f33d6747..7fef18288aa2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -894,7 +894,7 @@ struct intel_dp {
 
 	bool can_mst; /* this port supports mst */
 	bool is_mst;
-	int active_mst_links;
+	int active_streams; /* number of active streams (for SST and MST both) */
 	/* connector directly attached - won't be use for modeset in mst world */
 	struct intel_connector *attached_connector;
 
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (4 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 05/12] drm/i915: Track active streams also for DP SST ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:29   ` Daniel Vetter
  2016-07-29 13:51   ` [PATCH v2 " ville.syrjala
  2016-07-28 14:50 ` [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect() ville.syrjala
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With HSW + Dell UP2414Q (at least) drm_probe_ddc() occasionally fails,
and then we'll assume that the entire display has been disconnected.
We don't need the EDID from the main link, so we can simply check if
the sink is MST capable, and if so treat is as connected.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3a9c5d3b5c66..4a4184c21989 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3538,7 +3538,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 }
 
 static bool
-intel_dp_probe_mst(struct intel_dp *intel_dp)
+intel_dp_can_mst(struct intel_dp *intel_dp)
 {
 	u8 buf[1];
 
@@ -3551,18 +3551,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
 		return false;
 
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
-		if (buf[0] & DP_MST_CAP) {
-			DRM_DEBUG_KMS("Sink is MST capable\n");
-			intel_dp->is_mst = true;
-		} else {
-			DRM_DEBUG_KMS("Sink is not MST capable\n");
-			intel_dp->is_mst = false;
-		}
-	}
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1) != 1)
+		return false;
 
-	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
-	return intel_dp->is_mst;
+	return buf[0] & DP_MST_CAP;
+}
+
+static void
+intel_dp_configure_mst(struct intel_dp *intel_dp)
+{
+	if (!i915.enable_dp_mst)
+		return;
+
+	if (!intel_dp->can_mst)
+		return;
+
+	intel_dp->is_mst = intel_dp_can_mst(intel_dp);
+
+	if (intel_dp->is_mst)
+		DRM_DEBUG_KMS("Sink is MST capable\n");
+	else
+		DRM_DEBUG_KMS("Sink is not MST capable\n");
+
+	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+					intel_dp->is_mst);
 }
 
 static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
@@ -3993,6 +4005,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	if (drm_probe_ddc(&intel_dp->aux.ddc))
 		return connector_status_connected;
 
+	if (intel_dp_can_mst(intel_dp))
+		return connector_status_connected;
+
 	/* Well we tried, say unknown for unreliable port types */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
 		type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
@@ -4213,7 +4228,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	enum intel_display_power_domain power_domain;
-	bool ret;
 	u8 sink_irq_vector;
 
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
@@ -4249,8 +4263,9 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 
 	intel_dp_probe_oui(intel_dp);
 
-	ret = intel_dp_probe_mst(intel_dp);
-	if (ret) {
+	intel_dp_configure_mst(intel_dp);
+
+	if (intel_dp->is_mst) {
 		/*
 		 * If we are in MST mode then this connector
 		 * won't appear connected or have anything
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (5 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-28 19:48   ` Manasi Navare
  2016-07-29 20:37   ` Jim Bride
  2016-07-28 14:50 ` [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd ville.syrjala
                   ` (7 subsequent siblings)
  14 siblings, 2 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

DP link retraining needs to grab some modeset locks to not race with
modesets, so we can't really do it safely from the hpd_pulse, lest we
risk deadlocking due to MST sideband stuff.

Move the link retraining to happen from the hotplug work instead.
Doing at the end of intel_dp_detect() seems like a good place in case
the sink already got disconnected, in which case retraining is
pointless.

To determine if we need to schedule the hotplug work, we'll just check
the sink lane status without locks from hpd_pulse. A little racy
still eg. due to useing intel_dp->lane_count, but no less racy than
what we already had. We'll repeat the check in from intel_dp_detect()
with proper locking, where we'll also check if the link as actually
active or not.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
 1 file changed, 66 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4a4184c21989..675b83f57a07 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
 go_again:
 		if (bret == true) {
-
-			/* check link status - esi[10] = 0x200c */
-			if (intel_dp->active_streams &&
-			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
-				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
-				intel_dp_start_link_train(intel_dp);
-				intel_dp_stop_link_train(intel_dp);
-			}
-
 			DRM_DEBUG_KMS("got esi %3ph\n", esi);
 			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
 
@@ -3886,34 +3877,42 @@ go_again:
 	return -EINVAL;
 }
 
-static void
-intel_dp_check_link_status(struct intel_dp *intel_dp)
+static bool
+intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
 {
-	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	if (intel_dp->active_streams == 0)
+		return false;
+
+	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
+		return true;
 
 	if (!intel_dp_get_link_status(intel_dp, link_status)) {
 		DRM_ERROR("Failed to get link status\n");
-		return;
+		return false;
 	}
 
-	if (!intel_encoder->base.crtc)
-		return;
+	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
+}
 
-	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
-		return;
+static void
+intel_dp_link_retrain(struct intel_dp *intel_dp)
+{
+	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
-	/* if link training is requested we should perform it always */
-	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
-	    (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
+	if (intel_dp_link_needs_retrain(intel_dp)) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
-			      intel_encoder->base.name);
+			      encoder->base.name);
+
 		intel_dp_start_link_train(intel_dp);
 		intel_dp_stop_link_train(intel_dp);
 	}
+
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 }
 
 /*
@@ -3932,7 +3931,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 static bool
 intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	u8 sink_irq_vector;
 	u8 old_sink_count = intel_dp->sink_count;
 	bool ret;
@@ -3972,10 +3970,6 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
 	}
 
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	intel_dp_check_link_status(intel_dp);
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-
 	return true;
 }
 
@@ -3986,6 +3980,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	uint8_t *dpcd = intel_dp->dpcd;
 	uint8_t type;
 
+	WARN_ON(is_edp(intel_dp));
+
 	if (!intel_dp_get_dpcd(intel_dp))
 		return connector_status_disconnected;
 
@@ -4218,7 +4214,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->has_audio = false;
 }
 
-static void
+static enum drm_connector_status
 intel_dp_long_pulse(struct intel_connector *intel_connector)
 {
 	struct drm_connector *connector = &intel_connector->base;
@@ -4273,18 +4269,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 		 */
 		status = connector_status_disconnected;
 		goto out;
-	} else if (connector->status == connector_status_connected) {
-		/*
-		 * If display was connected already and is still connected
-		 * check links status, there has been known issues of
-		 * link loss triggerring long pulse!!!!
-		 */
-		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-		intel_dp_check_link_status(intel_dp);
-		drm_modeset_unlock(&dev->mode_config.connection_mutex);
-		goto out;
 	}
 
+	/* connected->connected, nothing to do */
+	if (connector->status == connector_status_connected)
+		goto out;
+
 	/*
 	 * Clearing NACK and defer counts to get their exact values
 	 * while reading EDID which are required by Compliance tests
@@ -4296,7 +4286,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	intel_dp_set_edid(intel_dp);
 
 	status = connector_status_connected;
-	intel_dp->detect_done = true;
 
 	/* Try to read the source of the interrupt */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
@@ -4313,43 +4302,30 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	}
 
 out:
-	if ((status != connector_status_connected) &&
-	    (intel_dp->is_mst == false))
+	if (status != connector_status_connected)
 		intel_dp_unset_edid(intel_dp);
 
 	intel_display_power_put(to_i915(dev), power_domain);
-	return;
+
+	return status;
 }
 
 static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct intel_connector *intel_connector = to_intel_connector(connector);
+	enum drm_connector_status status;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
-	if (intel_dp->is_mst) {
-		/* MST devices are disconnected from a monitor POV */
-		intel_dp_unset_edid(intel_dp);
-		if (intel_encoder->type != INTEL_OUTPUT_EDP)
-			intel_encoder->type = INTEL_OUTPUT_DP;
-		return connector_status_disconnected;
-	}
-
-	/* If full detect is not performed yet, do a full detect */
-	if (!intel_dp->detect_done)
-		intel_dp_long_pulse(intel_dp->attached_connector);
+	status = intel_dp_long_pulse(intel_connector);
 
-	intel_dp->detect_done = false;
+	if (status == connector_status_connected || intel_dp->is_mst)
+		intel_dp_link_retrain(intel_dp);
 
-	if (is_edp(intel_dp) || intel_connector->detect_edid)
-		return connector_status_connected;
-	else
-		return connector_status_disconnected;
+	return status;
 }
 
 static void
@@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 		      port_name(intel_dig_port->port),
 		      long_hpd ? "long" : "short");
 
+	if (long_hpd)
+		return IRQ_NONE;
+
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
 	intel_display_power_get(dev_priv, power_domain);
 
-	if (long_hpd) {
-		intel_dp_long_pulse(intel_dp->attached_connector);
-		if (intel_dp->is_mst)
-			ret = IRQ_HANDLED;
-		goto put_power;
-
-	} else {
-		if (intel_dp->is_mst) {
-			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
-				/*
-				 * If we were in MST mode, and device is not
-				 * there, get out of MST mode
-				 */
-				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
-					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
-				intel_dp->is_mst = false;
-				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
-								intel_dp->is_mst);
-				goto put_power;
-			}
-		}
-
-		if (!intel_dp->is_mst) {
-			if (!intel_dp_short_pulse(intel_dp)) {
-				intel_dp_long_pulse(intel_dp->attached_connector);
-				goto put_power;
-			}
+	if (intel_dp->is_mst) {
+		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
+			/*
+			 * If we were in MST mode, and device is not
+			 * there, get out of MST mode
+			 */
+			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
+				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+			intel_dp->is_mst = false;
+			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+							intel_dp->is_mst);
+			goto put_power;
 		}
+	} else {
+		if (!intel_dp_short_pulse(intel_dp))
+			goto put_power;
 	}
 
+	/*
+	 * Link retraining happens from the hotplug work,
+	 * check if we might need to schdule it.
+	 *
+	 * There has been known issues of link loss
+	 * triggerring long pulse, so let's check both
+	 * for short and long pulse.
+	 */
+	if (intel_dp_link_needs_retrain(intel_dp))
+		goto put_power;
+
 	ret = IRQ_HANDLED;
 
 put_power:
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (6 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect() ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-28 15:38   ` Chris Wilson
  2016-07-28 14:50 ` [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage ville.syrjala
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Supposedly nothing should have change in the DPCD/EDID deparment unless
there was a long HPD. Let's skip the work in ->detect() in that case.
We'll still want to do the link status check thouhg.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 19 +++++++++++++++----
 drivers/gpu/drm/i915/intel_drv.h |  2 +-
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 675b83f57a07..d1dd351682d2 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4315,12 +4315,15 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct intel_connector *intel_connector = to_intel_connector(connector);
-	enum drm_connector_status status;
+	enum drm_connector_status status = connector->status;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
-	status = intel_dp_long_pulse(intel_connector);
+	if (intel_dp->long_hpd_pending) {
+		intel_dp->long_hpd_pending = false;
+		status = intel_dp_long_pulse(intel_connector);
+	}
 
 	if (status == connector_status_connected || intel_dp->is_mst)
 		intel_dp_link_retrain(intel_dp);
@@ -4608,6 +4611,8 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+	intel_dp->long_hpd_pending = true;
+
 	if (!HAS_DDI(dev_priv))
 		intel_dp->DP = I915_READ(intel_dp->output_reg);
 
@@ -4682,8 +4687,10 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 		      port_name(intel_dig_port->port),
 		      long_hpd ? "long" : "short");
 
-	if (long_hpd)
+	if (long_hpd) {
+		intel_dp->long_hpd_pending = true;
 		return IRQ_NONE;
+	}
 
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
 	intel_display_power_get(dev_priv, power_domain);
@@ -4699,11 +4706,14 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 			intel_dp->is_mst = false;
 			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
 							intel_dp->is_mst);
+			intel_dp->long_hpd_pending = true;
 			goto put_power;
 		}
 	} else {
-		if (!intel_dp_short_pulse(intel_dp))
+		if (!intel_dp_short_pulse(intel_dp)) {
+			intel_dp->long_hpd_pending = true;
 			goto put_power;
+		}
 	}
 
 	/*
@@ -5512,6 +5522,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		 intel_dig_port->max_lanes, port_name(port)))
 		return false;
 
+	intel_dp->long_hpd_pending = true;
 	intel_dp->pps_pipe = INVALID_PIPE;
 
 	/* intel_dp vfuncs */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7fef18288aa2..20cf7ad26357 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -854,7 +854,7 @@ struct intel_dp {
 	uint8_t sink_count;
 	bool link_mst;
 	bool has_audio;
-	bool detect_done;
+	bool long_hpd_pending;
 	enum hdmi_force_audio force_audio;
 	bool limited_color_range;
 	bool color_range_auto;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (7 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:33   ` Daniel Vetter
  2016-07-28 14:50 ` [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches ville.syrjala
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

No need to iterate the rates array in intel_dp_max_link_rate(). We know
the max rate will be the last entry, and we already know the size.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d1dd351682d2..40cae6202160 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1447,7 +1447,7 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 	if (WARN_ON(len <= 0))
 		return 162000;
 
-	return rates[rate_to_index(0, rates) - 1];
+	return rates[len - 1];
 }
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (8 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:35   ` Daniel Vetter
  2016-07-28 14:50 ` [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none ville.syrjala
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Let's make rate_to_index() return the highest rate available that's
less than or equal to the rate requested by the caller. The function
can then be used to filter out rates higher than a certain maximum
rate.

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 40cae6202160..08d95352ffd6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1431,10 +1431,13 @@ static int rate_to_index(int find, const int *rates)
 	int i = 0;
 
 	for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
-		if (find == rates[i])
+		if (find < rates[i])
 			break;
 
-	return i;
+	if (WARN_ON(i == 0))
+		return 0;
+
+	return i - 1;
 }
 
 int
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (9 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:38   ` Daniel Vetter
  2016-07-28 14:50 ` [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook ville.syrjala
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

My ASUS PB278 at least doesn't seem to appreciate when you try to
ack sink irqs when there are none. Results in thus sort of dmesg spam
[drm:drm_dp_dpcd_access] too many retries, giving up

Let's skip the ack if there are no pending irqs. I have no clue why we
do this in two places. One of them likely should just go away. Oh, and
MST has its own sink irq handler too...

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 08d95352ffd6..7551d92a3cfb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3934,7 +3934,7 @@ intel_dp_link_retrain(struct intel_dp *intel_dp)
 static bool
 intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
-	u8 sink_irq_vector;
+	u8 sink_irq_vector = 0;
 	u8 old_sink_count = intel_dp->sink_count;
 	bool ret;
 
@@ -3961,7 +3961,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 
 	/* Try to read the source of the interrupt */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
-	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
+	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector) &&
+	    sink_irq_vector != 0) {
 		/* Clear interrupt source */
 		drm_dp_dpcd_writeb(&intel_dp->aux,
 				   DP_DEVICE_SERVICE_IRQ_VECTOR,
@@ -4227,7 +4228,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	enum intel_display_power_domain power_domain;
-	u8 sink_irq_vector;
+	u8 sink_irq_vector = 0;
 
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
 	intel_display_power_get(to_i915(dev), power_domain);
@@ -4292,7 +4293,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 
 	/* Try to read the source of the interrupt */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
-	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
+	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector) &&
+	    sink_irq_vector != 0) {
 		/* Clear interrupt source */
 		drm_dp_dpcd_writeb(&intel_dp->aux,
 				   DP_DEVICE_SERVICE_IRQ_VECTOR,
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (10 preceding siblings ...)
  2016-07-28 14:50 ` [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none ville.syrjala
@ 2016-07-28 14:50 ` ville.syrjala
  2016-07-29  9:42   ` Daniel Vetter
  2016-07-28 15:39 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc Patchwork
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 54+ messages in thread
From: ville.syrjala @ 2016-07-28 14:50 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We cache a bunch of state under the encoders (eg. link freq and
lane count for DP). We need to refresh that cached state on
init/resume during hardware readout. Since we have already read out
most interesting details into the pipe config, let's add a new
optional encoder hook that can move the information from the pipe
config into the encoder.

We can't really use the pipe config directly since this cached
information is used during link retraining, which doesn't have
access to a pipe config (mainly due to MST). Redoing MST in a way where
the actual link would be part of the modeset with its own pipe config
could be an alternative solution, but that would be a much more massive
undertaking. For now, let's at least try to keep the two pieces of
state in sync.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     |  4 ++++
 drivers/gpu/drm/i915/intel_display.c |  4 ++++
 drivers/gpu/drm/i915/intel_dp.c      | 18 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  7 +++++++
 4 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index bc188ee6e37f..2b679f72eba4 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2314,6 +2314,9 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port)
 	return connector;
 }
 
+void intel_dp_sync_state(struct intel_encoder *encoder,
+			 const struct intel_crtc_state *pipe_config);
+
 void intel_ddi_init(struct drm_device *dev, enum port port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -2377,6 +2380,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	intel_encoder->post_disable = intel_ddi_post_disable;
 	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 	intel_encoder->get_config = intel_ddi_get_config;
+	intel_encoder->sync_state = intel_dp_sync_state;
 	intel_encoder->suspend = intel_dp_encoder_suspend;
 
 	intel_dig_port->port = port;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a6699c76bef3..dffcc814c178 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -16031,8 +16031,12 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			encoder->base.crtc = &crtc->base;
 			crtc->config->output_types |= 1 << encoder->type;
 			encoder->get_config(encoder, crtc->config);
+			if (encoder->sync_state)
+				encoder->sync_state(encoder, crtc->config);
 		} else {
 			encoder->base.crtc = NULL;
+			if (encoder->sync_state)
+				encoder->sync_state(encoder, NULL);
 		}
 
 		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7551d92a3cfb..44567dd68257 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2482,6 +2482,23 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
 	}
 }
 
+void intel_dp_sync_state(struct intel_encoder *encoder,
+			 const struct intel_crtc_state *pipe_config)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+	if (pipe_config) {
+		/* FIXME MST */
+		intel_dp->active_streams = 1;
+		intel_dp->link_rate = pipe_config->port_clock;
+		intel_dp->lane_count = pipe_config->lane_count;
+	} else {
+		intel_dp->active_streams = 0;
+		intel_dp->link_rate = 0;
+		intel_dp->lane_count = 0;
+	}
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -5675,6 +5692,7 @@ bool intel_dp_init(struct drm_device *dev,
 	intel_encoder->disable = intel_disable_dp;
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 	intel_encoder->get_config = intel_dp_get_config;
+	intel_encoder->sync_state = intel_dp_sync_state;
 	intel_encoder->suspend = intel_dp_encoder_suspend;
 	if (IS_CHERRYVIEW(dev)) {
 		intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 20cf7ad26357..49c75caa4150 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -213,6 +213,13 @@ struct intel_encoder {
 	void (*get_config)(struct intel_encoder *,
 			   struct intel_crtc_state *pipe_config);
 	/*
+	 * Used during init/resume to sync any cached state
+	 * stored outside the pipe config (eg. active DP link
+	 * parameters).
+	 */
+	void (*sync_state)(struct intel_encoder *,
+			   const struct intel_crtc_state *);
+	/*
 	 * Called during system suspend after all pending requests for the
 	 * encoder are flushed (for example for DP AUX transactions) and
 	 * device interrupts are disabled.
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd
  2016-07-28 14:50 ` [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd ville.syrjala
@ 2016-07-28 15:38   ` Chris Wilson
  2016-07-28 15:44     ` Ville Syrjälä
  0 siblings, 1 reply; 54+ messages in thread
From: Chris Wilson @ 2016-07-28 15:38 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:44PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Supposedly nothing should have change in the DPCD/EDID deparment unless
> there was a long HPD. Let's skip the work in ->detect() in that case.
> We'll still want to do the link status check thouhg.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c  | 19 +++++++++++++++----
>  drivers/gpu/drm/i915/intel_drv.h |  2 +-
>  2 files changed, 16 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 675b83f57a07..d1dd351682d2 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4315,12 +4315,15 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  {
>  	struct intel_dp *intel_dp = intel_attached_dp(connector);
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
> -	enum drm_connector_status status;
> +	enum drm_connector_status status = connector->status;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
>  
> -	status = intel_dp_long_pulse(intel_connector);
> +	if (intel_dp->long_hpd_pending) {

Set from a worker unlocked, consumed unlocked. At the very least you
want a WRITE_ONCE() to document this should be unset before
intel_dp_long_pulse(), if (cmpxchg(long_hpd_pending, 1, 0) {} and a
smp_store_mb() when setting for belt-and-braces approach.

> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 7fef18288aa2..20cf7ad26357 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -854,7 +854,7 @@ struct intel_dp {
>  	uint8_t sink_count;
>  	bool link_mst;
>  	bool has_audio;
> -	bool detect_done;

Unrelated cleanup?

> +	bool long_hpd_pending;
>  	enum hdmi_force_audio force_audio;
>  	bool limited_color_range;
>  	bool color_range_auto;

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc.
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (11 preceding siblings ...)
  2016-07-28 14:50 ` [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook ville.syrjala
@ 2016-07-28 15:39 ` Patchwork
  2016-07-29 14:27 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3) Patchwork
  2016-08-04 13:08 ` [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc Ville Syrjälä
  14 siblings, 0 replies; 54+ messages in thread
From: Patchwork @ 2016-07-28 15:39 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Move DP link retraining to hotplug work etc.
URL   : https://patchwork.freedesktop.org/series/10354/
State : failure

== Summary ==

Series 10354v1 drm/i915: Move DP link retraining to hotplug work etc.
http://patchwork.freedesktop.org/api/1.0/series/10354/revisions/1/mbox

Test drv_module_reload_basic:
                skip       -> PASS       (ro-ivb-i7-3770)
                skip       -> PASS       (ro-skl3-i5-6260u)
Test kms_cursor_legacy:
        Subgroup basic-cursor-vs-flip-legacy:
                fail       -> PASS       (ro-ilk1-i5-650)
        Subgroup basic-flip-vs-cursor-legacy:
                pass       -> FAIL       (fi-hsw-i7-4770k)
                pass       -> FAIL       (ro-bdw-i5-5250u)
        Subgroup basic-flip-vs-cursor-varying-size:
                fail       -> PASS       (ro-snb-i7-2620M)
                pass       -> FAIL       (ro-bdw-i5-5250u)
Test kms_flip:
        Subgroup basic-flip-vs-wf_vblank:
                fail       -> PASS       (ro-byt-n2820)

fi-hsw-i7-4770k  total:239  pass:216  dwarn:0   dfail:0   fail:1   skip:22 
fi-kbl-qkkr      total:239  pass:181  dwarn:28  dfail:0   fail:3   skip:27 
fi-skl-i5-6260u  total:239  pass:223  dwarn:0   dfail:0   fail:2   skip:14 
fi-skl-i7-6700k  total:239  pass:207  dwarn:0   dfail:0   fail:4   skip:28 
fi-snb-i7-2600   total:239  pass:197  dwarn:0   dfail:0   fail:0   skip:42 
ro-bdw-i5-5250u  total:239  pass:217  dwarn:4   dfail:0   fail:2   skip:16 
ro-bdw-i7-5557U  total:239  pass:221  dwarn:1   dfail:0   fail:1   skip:16 
ro-bdw-i7-5600u  total:239  pass:206  dwarn:0   dfail:0   fail:1   skip:32 
ro-bsw-n3050     total:239  pass:193  dwarn:0   dfail:0   fail:4   skip:42 
ro-byt-n2820     total:239  pass:196  dwarn:0   dfail:0   fail:3   skip:40 
ro-hsw-i3-4010u  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
ro-hsw-i7-4770r  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
ro-ilk-i7-620lm  total:239  pass:172  dwarn:1   dfail:0   fail:1   skip:65 
ro-ilk1-i5-650   total:234  pass:173  dwarn:0   dfail:0   fail:1   skip:60 
ro-ivb-i7-3770   total:239  pass:204  dwarn:0   dfail:0   fail:0   skip:35 
ro-ivb2-i7-3770  total:239  pass:208  dwarn:0   dfail:0   fail:0   skip:31 
ro-skl3-i5-6260u total:239  pass:221  dwarn:0   dfail:0   fail:4   skip:14 
ro-snb-i7-2620M  total:239  pass:197  dwarn:0   dfail:0   fail:1   skip:41 

Results at /archive/results/CI_IGT_test/RO_Patchwork_1633/

cb7629d drm-intel-nightly: 2016y-07m-28d-11h-02m-33s UTC integration manifest
ba9e503 drm/i915: Add encoder .sync_state() hook
d5c4353 drm/i915: Don't try to ack sink irqs when there are none
b508c1c drm/i915: Allow rate_to_index() to return non-exact matches
08b7db9 drm/i915: Remove useless rate_to_index() usage
5550271 drm/i915: Skip dpcd/edid read unless there was a long hpd
d267845 drm/i915: Move DP link retraining into intel_dp_detect()
4cfc2f2 drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
67bc562 drm/i915: Track active streams also for DP SST
cd47dbf drm/i915: Reject mixing MST and SST/HDMI on the same digital port
6123fa2 drm/i915: Avoid mixing up SST and MST in DDI setup
b2addee drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
8371771 drm/i915: Ignore initial lid state for eDP

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd
  2016-07-28 15:38   ` Chris Wilson
@ 2016-07-28 15:44     ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-28 15:44 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx, Ander Conselvan de Oliveira

On Thu, Jul 28, 2016 at 04:38:55PM +0100, Chris Wilson wrote:
> On Thu, Jul 28, 2016 at 05:50:44PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Supposedly nothing should have change in the DPCD/EDID deparment unless
> > there was a long HPD. Let's skip the work in ->detect() in that case.
> > We'll still want to do the link status check thouhg.
> > 
> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > Cc: Jim Bride <jim.bride@linux.intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c  | 19 +++++++++++++++----
> >  drivers/gpu/drm/i915/intel_drv.h |  2 +-
> >  2 files changed, 16 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 675b83f57a07..d1dd351682d2 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -4315,12 +4315,15 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  {
> >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> > -	enum drm_connector_status status;
> > +	enum drm_connector_status status = connector->status;
> >  
> >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> >  		      connector->base.id, connector->name);
> >  
> > -	status = intel_dp_long_pulse(intel_connector);
> > +	if (intel_dp->long_hpd_pending) {
> 
> Set from a worker unlocked, consumed unlocked. At the very least you
> want a WRITE_ONCE() to document this should be unset before
> intel_dp_long_pulse(), if (cmpxchg(long_hpd_pending, 1, 0) {} and a
> smp_store_mb() when setting for belt-and-braces approach.

Yeah, I guess we should do something like that. There is other junk
also getting set/checked unlocked in this work as well, and I
haven't had the energy to figure it all out yet.

> 
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 7fef18288aa2..20cf7ad26357 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -854,7 +854,7 @@ struct intel_dp {
> >  	uint8_t sink_count;
> >  	bool link_mst;
> >  	bool has_audio;
> > -	bool detect_done;
> 
> Unrelated cleanup?

That one should be part of the previous patch, I think.

> 
> > +	bool long_hpd_pending;
> >  	enum hdmi_force_audio force_audio;
> >  	bool limited_color_range;
> >  	bool color_range_auto;
> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 01/12] drm/i915: Ignore initial lid state for eDP
  2016-07-28 14:50 ` [PATCH 01/12] drm/i915: Ignore initial lid state for eDP ville.syrjala
@ 2016-07-28 15:47   ` Chris Wilson
  2016-07-28 16:01     ` Ville Syrjälä
  0 siblings, 1 reply; 54+ messages in thread
From: Chris Wilson @ 2016-07-28 15:47 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:37PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Currently we try to check the lid status to see whether eDP is connected
> or not. However we ignore the result anyway, and we have no lid notifier
> to fire off uevents, so let's just ignore the lid stuff for eDP
> entirely.

You mean the OpRegion no longer contains lid_state? I don't see it being
disabled... The lid notifier is from acpi/button.c. I haven't looked at
why the result would be ignored, but you haven't convinced me why eDP is
special.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 01/12] drm/i915: Ignore initial lid state for eDP
  2016-07-28 15:47   ` Chris Wilson
@ 2016-07-28 16:01     ` Ville Syrjälä
  2016-07-28 16:36       ` Chris Wilson
  0 siblings, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-28 16:01 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Thu, Jul 28, 2016 at 04:47:07PM +0100, Chris Wilson wrote:
> On Thu, Jul 28, 2016 at 05:50:37PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Currently we try to check the lid status to see whether eDP is connected
> > or not. However we ignore the result anyway, and we have no lid notifier
> > to fire off uevents, so let's just ignore the lid stuff for eDP
> > entirely.
> 
> You mean the OpRegion no longer contains lid_state? I don't see it being
> disabled... The lid notifier is from acpi/button.c. I haven't looked at
> why the result would be ignored, but you haven't convinced me why eDP is
> special.

We don't register a lid notifier for eDP. So if the initial detect would
happen with lid closed we'd mark eDP as disconnected, and when the lid
gets opened we won't even notice, and thus the connector never becomes
connected.

IIRC on my ILK the lid state in OpRegion didn't work anyway. But I
should probably double check.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 01/12] drm/i915: Ignore initial lid state for eDP
  2016-07-28 16:01     ` Ville Syrjälä
@ 2016-07-28 16:36       ` Chris Wilson
  2016-07-28 16:48         ` Ville Syrjälä
  0 siblings, 1 reply; 54+ messages in thread
From: Chris Wilson @ 2016-07-28 16:36 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 07:01:29PM +0300, Ville Syrjälä wrote:
> On Thu, Jul 28, 2016 at 04:47:07PM +0100, Chris Wilson wrote:
> > On Thu, Jul 28, 2016 at 05:50:37PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Currently we try to check the lid status to see whether eDP is connected
> > > or not. However we ignore the result anyway, and we have no lid notifier
> > > to fire off uevents, so let's just ignore the lid stuff for eDP
> > > entirely.
> > 
> > You mean the OpRegion no longer contains lid_state? I don't see it being
> > disabled... The lid notifier is from acpi/button.c. I haven't looked at
> > why the result would be ignored, but you haven't convinced me why eDP is
> > special.
> 
> We don't register a lid notifier for eDP. So if the initial detect would
> happen with lid closed we'd mark eDP as disconnected, and when the lid
> gets opened we won't even notice, and thus the connector never becomes
> connected.

That was meant to be part of the intel_panel so that we have consistent
behaviour on any laptop. I would still rather we have consistent
behaviour, but eDP has been different for so long that any change now is
going to be painful.
 
> IIRC on my ILK the lid state in OpRegion didn't work anyway. But I
> should probably double check.

Yup, the lid button was unreliable as every other piece of hw. Looking
at intel_lid_notify(), would it not be easier just to send the hotplug
uevent.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 01/12] drm/i915: Ignore initial lid state for eDP
  2016-07-28 16:36       ` Chris Wilson
@ 2016-07-28 16:48         ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-28 16:48 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Thu, Jul 28, 2016 at 05:36:27PM +0100, Chris Wilson wrote:
> On Thu, Jul 28, 2016 at 07:01:29PM +0300, Ville Syrjälä wrote:
> > On Thu, Jul 28, 2016 at 04:47:07PM +0100, Chris Wilson wrote:
> > > On Thu, Jul 28, 2016 at 05:50:37PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > Currently we try to check the lid status to see whether eDP is connected
> > > > or not. However we ignore the result anyway, and we have no lid notifier
> > > > to fire off uevents, so let's just ignore the lid stuff for eDP
> > > > entirely.
> > > 
> > > You mean the OpRegion no longer contains lid_state? I don't see it being
> > > disabled... The lid notifier is from acpi/button.c. I haven't looked at
> > > why the result would be ignored, but you haven't convinced me why eDP is
> > > special.
> > 
> > We don't register a lid notifier for eDP. So if the initial detect would
> > happen with lid closed we'd mark eDP as disconnected, and when the lid
> > gets opened we won't even notice, and thus the connector never becomes
> > connected.
> 
> That was meant to be part of the intel_panel so that we have consistent
> behaviour on any laptop. I would still rather we have consistent
> behaviour, but eDP has been different for so long that any change now is
> going to be painful.
>  
> > IIRC on my ILK the lid state in OpRegion didn't work anyway. But I
> > should probably double check.
> 
> Yup, the lid button was unreliable as every other piece of hw. Looking
> at intel_lid_notify(), would it not be easier just to send the hotplug
> uevent.

I thought the main point of the lid notifier was to restore any state
trampled by the VBIOS. I've been hoping that I'd find some magic thing
to get the VBIOS to not do that. IIRC there are some semi-interesting
looking things in OpRegion that might just do it. But to know for sure
I'd first have to get my hands on a machine that suffers from this
affliction.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
  2016-07-28 14:50 ` [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP ville.syrjala
@ 2016-07-28 17:30   ` Chris Wilson
  2016-07-28 17:45     ` Ville Syrjälä
  2016-07-29 13:52   ` [PATCH v3 " ville.syrjala
  1 sibling, 1 reply; 54+ messages in thread
From: Chris Wilson @ 2016-07-28 17:30 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:38PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Currently we re-read a bunch of static eDP panel caps from the DPCD
> over and over again. Let's do it only once to save some time and effort.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

>  static bool
>  intel_dp_get_dpcd(struct intel_dp *intel_dp)
>  {
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_device *dev = dig_port->base.base.dev;
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> +	bool init_edp_dpcd = is_edp(intel_dp) &&
> +		intel_dp->dpcd[DP_DPCD_REV] == 0;
>  
>  	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
>  			     sizeof(intel_dp->dpcd)) < 0)

> +	if (init_edp_dpcd)
> +		intel_edp_get_dpcd(intel_dp);

I have to admit it took me a few passes to realise how this achieves
init once.

	bool intel_dp_dpcd_is_unset(intel_dp)
	{
		return intel_dp->dpcd[DP_DPCD_REV] == 0;
	}

Not really sure how else to make it clear to the causal reader that test
is only true on the first call.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
  2016-07-28 17:30   ` Chris Wilson
@ 2016-07-28 17:45     ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-28 17:45 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Thu, Jul 28, 2016 at 06:30:47PM +0100, Chris Wilson wrote:
> On Thu, Jul 28, 2016 at 05:50:38PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Currently we re-read a bunch of static eDP panel caps from the DPCD
> > over and over again. Let's do it only once to save some time and effort.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> 
> >  static bool
> >  intel_dp_get_dpcd(struct intel_dp *intel_dp)
> >  {
> > -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> > -	struct drm_device *dev = dig_port->base.base.dev;
> > -	struct drm_i915_private *dev_priv = to_i915(dev);
> > +	bool init_edp_dpcd = is_edp(intel_dp) &&
> > +		intel_dp->dpcd[DP_DPCD_REV] == 0;
> >  
> >  	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
> >  			     sizeof(intel_dp->dpcd)) < 0)
> 
> > +	if (init_edp_dpcd)
> > +		intel_edp_get_dpcd(intel_dp);
> 
> I have to admit it took me a few passes to realise how this achieves
> init once.
> 
> 	bool intel_dp_dpcd_is_unset(intel_dp)
> 	{
> 		return intel_dp->dpcd[DP_DPCD_REV] == 0;
> 	}
> 
> Not really sure how else to make it clear to the causal reader that test
> is only true on the first call.

First I thought I'd just call the eDP specific function from the
connector init, but then I realized it needs to happen after reading the
regular DPCD stuff, but before printing out the rates/etc. So in the end
I just left it where it was and added the bool. I suppose it should be
possible to refactor the thing somehow to make it less confusing.

I guess I can give it one more try, and if I should fail, I'll suck in
your intel_dp_dpcd_is_unset() at least...

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-28 14:50 ` [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect() ville.syrjala
@ 2016-07-28 19:48   ` Manasi Navare
  2016-07-28 20:15     ` Ville Syrjälä
  2016-07-29 20:37   ` Jim Bride
  1 sibling, 1 reply; 54+ messages in thread
From: Manasi Navare @ 2016-07-28 19:48 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> DP link retraining needs to grab some modeset locks to not race with
> modesets, so we can't really do it safely from the hpd_pulse, lest we
> risk deadlocking due to MST sideband stuff.
> 
> Move the link retraining to happen from the hotplug work instead.
> Doing at the end of intel_dp_detect() seems like a good place in case
> the sink already got disconnected, in which case retraining is
> pointless.
> 
> To determine if we need to schedule the hotplug work, we'll just check
> the sink lane status without locks from hpd_pulse. A little racy
> still eg. due to useing intel_dp->lane_count, but no less racy than
> what we already had. We'll repeat the check in from intel_dp_detect()
> with proper locking, where we'll also check if the link as actually
> active or not.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
>  1 file changed, 66 insertions(+), 88 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4a4184c21989..675b83f57a07 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
>  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
>  go_again:
>  		if (bret == true) {
> -
> -			/* check link status - esi[10] = 0x200c */
> -			if (intel_dp->active_streams &&
> -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> -				intel_dp_start_link_train(intel_dp);
> -				intel_dp_stop_link_train(intel_dp);
> -			}
> -
>  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
>  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
>  
> @@ -3886,34 +3877,42 @@ go_again:
>  	return -EINVAL;
>  }
>  
> -static void
> -intel_dp_check_link_status(struct intel_dp *intel_dp)
> +static bool
> +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
>  {
> -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	u8 link_status[DP_LINK_STATUS_SIZE];
>  
> -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> +	if (intel_dp->active_streams == 0)
> +		return false;
> +
> +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> +		return true;
>  
>  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
>  		DRM_ERROR("Failed to get link status\n");
> -		return;
> +		return false;
>  	}
>  
> -	if (!intel_encoder->base.crtc)
> -		return;
> +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);

According to the DP spec, we should also check for the clock recovery bit in DPCD
We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)

> +}
>  
> -	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
> -		return;
> +static void
> +intel_dp_link_retrain(struct intel_dp *intel_dp)
> +{
> +	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +
> +	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
>  
> -	/* if link training is requested we should perform it always */
> -	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
> -	    (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {

> +	if (intel_dp_link_needs_retrain(intel_dp)) {
>  		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
> -			      intel_encoder->base.name);
> +			      encoder->base.name);
> +
>  		intel_dp_start_link_train(intel_dp);
>  		intel_dp_stop_link_train(intel_dp);
>  	}
> +
> +	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>  }
>  
>  /*
> @@ -3932,7 +3931,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
>  static bool
>  intel_dp_short_pulse(struct intel_dp *intel_dp)
>  {
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	u8 sink_irq_vector;
>  	u8 old_sink_count = intel_dp->sink_count;
>  	bool ret;
> @@ -3972,10 +3970,6 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
>  			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
>  	}
>  
> -	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -	intel_dp_check_link_status(intel_dp);
> -	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -
>  	return true;
>  }
>  
> @@ -3986,6 +3980,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
>  	uint8_t *dpcd = intel_dp->dpcd;
>  	uint8_t type;
>  
> +	WARN_ON(is_edp(intel_dp));
> +
>  	if (!intel_dp_get_dpcd(intel_dp))
>  		return connector_status_disconnected;
>  
> @@ -4218,7 +4214,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
>  	intel_dp->has_audio = false;
>  }
>  
> -static void
> +static enum drm_connector_status
>  intel_dp_long_pulse(struct intel_connector *intel_connector)
>  {
>  	struct drm_connector *connector = &intel_connector->base;
> @@ -4273,18 +4269,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  		 */
>  		status = connector_status_disconnected;
>  		goto out;
> -	} else if (connector->status == connector_status_connected) {
> -		/*
> -		 * If display was connected already and is still connected
> -		 * check links status, there has been known issues of
> -		 * link loss triggerring long pulse!!!!
> -		 */
> -		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -		intel_dp_check_link_status(intel_dp);
> -		drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -		goto out;
>  	}
>  
> +	/* connected->connected, nothing to do */
> +	if (connector->status == connector_status_connected)
> +		goto out;
> +
>  	/*
>  	 * Clearing NACK and defer counts to get their exact values
>  	 * while reading EDID which are required by Compliance tests
> @@ -4296,7 +4286,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	intel_dp_set_edid(intel_dp);
>  
>  	status = connector_status_connected;
> -	intel_dp->detect_done = true;
>  
>  	/* Try to read the source of the interrupt */
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
> @@ -4313,43 +4302,30 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	}
>  
>  out:
> -	if ((status != connector_status_connected) &&
> -	    (intel_dp->is_mst == false))
> +	if (status != connector_status_connected)
>  		intel_dp_unset_edid(intel_dp);
>  
>  	intel_display_power_put(to_i915(dev), power_domain);
> -	return;
> +
> +	return status;
>  }
>  
>  static enum drm_connector_status
>  intel_dp_detect(struct drm_connector *connector, bool force)
>  {
>  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
> +	enum drm_connector_status status;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
>  
> -	if (intel_dp->is_mst) {
> -		/* MST devices are disconnected from a monitor POV */
> -		intel_dp_unset_edid(intel_dp);
> -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> -			intel_encoder->type = INTEL_OUTPUT_DP;
> -		return connector_status_disconnected;
> -	}
> -
> -	/* If full detect is not performed yet, do a full detect */
> -	if (!intel_dp->detect_done)
> -		intel_dp_long_pulse(intel_dp->attached_connector);
> +	status = intel_dp_long_pulse(intel_connector);
>  
> -	intel_dp->detect_done = false;
> +	if (status == connector_status_connected || intel_dp->is_mst)

Whya re we not checking for (!intel_encoder->crtc.base) before retraining?
I had seen issues with connected boot case when connector status is connected and if it
tries to retrain it fails with retries because there is no active pipe. In that
case it should not attempt to retrain.


> +		intel_dp_link_retrain(intel_dp);
>  
> -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> -		return connector_status_connected;
> -	else
> -		return connector_status_disconnected;
> +	return status;
>  }
>  
>  static void
> @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
>  		      port_name(intel_dig_port->port),
>  		      long_hpd ? "long" : "short");
>  
> +	if (long_hpd)
> +		return IRQ_NONE;
> +
>  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
>  	intel_display_power_get(dev_priv, power_domain);
>  
> -	if (long_hpd) {
> -		intel_dp_long_pulse(intel_dp->attached_connector);
> -		if (intel_dp->is_mst)
> -			ret = IRQ_HANDLED;
> -		goto put_power;
> -
> -	} else {
> -		if (intel_dp->is_mst) {
> -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> -				/*
> -				 * If we were in MST mode, and device is not
> -				 * there, get out of MST mode
> -				 */
> -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> -				intel_dp->is_mst = false;
> -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> -								intel_dp->is_mst);
> -				goto put_power;
> -			}
> -		}
> -
> -		if (!intel_dp->is_mst) {
> -			if (!intel_dp_short_pulse(intel_dp)) {
> -				intel_dp_long_pulse(intel_dp->attached_connector);
> -				goto put_power;
> -			}
> +	if (intel_dp->is_mst) {
> +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> +			/*
> +			 * If we were in MST mode, and device is not
> +			 * there, get out of MST mode
> +			 */
> +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> +			intel_dp->is_mst = false;
> +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> +							intel_dp->is_mst);
> +			goto put_power;
>  		}
> +	} else {
> +		if (!intel_dp_short_pulse(intel_dp))
> +			goto put_power;
>  	}
>  
> +	/*
> +	 * Link retraining happens from the hotplug work,
> +	 * check if we might need to schdule it.
> +	 *
> +	 * There has been known issues of link loss
> +	 * triggerring long pulse, so let's check both
> +	 * for short and long pulse.
> +	 */
> +	if (intel_dp_link_needs_retrain(intel_dp))
> +		goto put_power;
> +
>  	ret = IRQ_HANDLED;
>  
>  put_power:
> -- 
> 2.7.4
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-28 19:48   ` Manasi Navare
@ 2016-07-28 20:15     ` Ville Syrjälä
  2016-07-29  0:36       ` Manasi Navare
  0 siblings, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-28 20:15 UTC (permalink / raw)
  To: Manasi Navare; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > DP link retraining needs to grab some modeset locks to not race with
> > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > risk deadlocking due to MST sideband stuff.
> > 
> > Move the link retraining to happen from the hotplug work instead.
> > Doing at the end of intel_dp_detect() seems like a good place in case
> > the sink already got disconnected, in which case retraining is
> > pointless.
> > 
> > To determine if we need to schedule the hotplug work, we'll just check
> > the sink lane status without locks from hpd_pulse. A little racy
> > still eg. due to useing intel_dp->lane_count, but no less racy than
> > what we already had. We'll repeat the check in from intel_dp_detect()
> > with proper locking, where we'll also check if the link as actually
> > active or not.
> > 
> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > Cc: Jim Bride <jim.bride@linux.intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> >  1 file changed, 66 insertions(+), 88 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 4a4184c21989..675b83f57a07 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> >  go_again:
> >  		if (bret == true) {
> > -
> > -			/* check link status - esi[10] = 0x200c */
> > -			if (intel_dp->active_streams &&
> > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > -				intel_dp_start_link_train(intel_dp);
> > -				intel_dp_stop_link_train(intel_dp);
> > -			}
> > -
> >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> >  
> > @@ -3886,34 +3877,42 @@ go_again:
> >  	return -EINVAL;
> >  }
> >  
> > -static void
> > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > +static bool
> > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> >  {
> > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> >  	u8 link_status[DP_LINK_STATUS_SIZE];
> >  
> > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > +	if (intel_dp->active_streams == 0)
> > +		return false;
> > +
> > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > +		return true;
> >  
> >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> >  		DRM_ERROR("Failed to get link status\n");
> > -		return;
> > +		return false;
> >  	}
> >  
> > -	if (!intel_encoder->base.crtc)
> > -		return;
> > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> 
> According to the DP spec, we should also check for the clock recovery bit in DPCD
> We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)

I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
CR_DONE, EQ_DONE, and SYMBOL_LOCKED.

Anyways, while I was looking at the short pulse handling a bit more, I came
to the conclusion that we should rewrite it a bit.

The CTS docs seem to say that we're expected to read DPCD 0x200-0x205 on 
short pulse, and use that information to determine what we should do.
Currently we don't do that.

So I was thunking that we'd adjust the link_status stuff to read 0x200-0x207
instead of 0x202-0x207, like so:
-#define DP_LINK_STATUS_SIZE       6
+#define DP_LINK_STATUS_SIZE       8

 static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
 {
-       return link_status[r - DP_LANE0_1_STATUS];
+       return link_status[r - DP_SINK_COUNT];
 }

And then we'd use something like this as our short pulse handler:

static bool
intel_dp_short_pulse(struct intel_dp *intel_dp)
{
        u8 link_status[DP_LINK_STATUS_SIZE], tmp;

        /*                                                                                                             
         * Clearing compliance test variables to allow capturing                                                       
         * of values for next automated test request.                                                                  
         */
        intel_dp->compliance_test_active = 0;
        intel_dp->compliance_test_type = 0;
        intel_dp->compliance_test_data = 0;

        if (!intel_dp_get_link_status(intel_dp, link_status))
                return false;

        tmp = drm_dp_link_status(link_status, DP_DEVICE_SERVICE_IRQ_VECTOR);
        if (tmp)
                drm_dp_dpcd_writeb(&intel_dp->aux,
                                   DP_DEVICE_SERVICE_IRQ_VECTOR,
                                   tmp);

        if (tmp & DP_AUTOMATED_TEST_REQUEST)
                DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
        if (tmp & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
                DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");

        tmp = drm_dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
        if (tmp & DP_DOWNSTREAM_PORT_STATUS_CHANGED)
                return false;

        tmp = drm_dp_link_status(link_status, DP_SINK_COUNT);
        if (DP_GET_SINK_COUNT(tmp) != intel_dp->sink_count)
                return false;

        if (intel_dp->active_streams != 0 &&
            !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))
                return false;

        return true;
}

and obviously fill in whatever else sink irq handling we need.

Thoughts? Does that look sane?

<snip>
> >  
> >  static enum drm_connector_status
> >  intel_dp_detect(struct drm_connector *connector, bool force)
> >  {
> >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> > -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> > -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> > +	enum drm_connector_status status;
> >  
> >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> >  		      connector->base.id, connector->name);
> >  
> > -	if (intel_dp->is_mst) {
> > -		/* MST devices are disconnected from a monitor POV */
> > -		intel_dp_unset_edid(intel_dp);
> > -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> > -			intel_encoder->type = INTEL_OUTPUT_DP;
> > -		return connector_status_disconnected;
> > -	}
> > -
> > -	/* If full detect is not performed yet, do a full detect */
> > -	if (!intel_dp->detect_done)
> > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > +	status = intel_dp_long_pulse(intel_connector);
> >  
> > -	intel_dp->detect_done = false;
> > +	if (status == connector_status_connected || intel_dp->is_mst)
> 
> Whya re we not checking for (!intel_encoder->crtc.base) before retraining?
> I had seen issues with connected boot case when connector status is connected and if it
> tries to retrain it fails with retries because there is no active pipe. In that
> case it should not attempt to retrain.

I changed it to use intel_dp->active_streams instead. That'll work for MST
as well as SST. Checking for the crtc would only cover SST.

> 
> 
> > +		intel_dp_link_retrain(intel_dp);
> >  
> > -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> > -		return connector_status_connected;
> > -	else
> > -		return connector_status_disconnected;
> > +	return status;
> >  }
> >  
> >  static void
> > @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
> >  		      port_name(intel_dig_port->port),
> >  		      long_hpd ? "long" : "short");
> >  
> > +	if (long_hpd)
> > +		return IRQ_NONE;
> > +
> >  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> >  	intel_display_power_get(dev_priv, power_domain);
> >  
> > -	if (long_hpd) {
> > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > -		if (intel_dp->is_mst)
> > -			ret = IRQ_HANDLED;
> > -		goto put_power;
> > -
> > -	} else {
> > -		if (intel_dp->is_mst) {
> > -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > -				/*
> > -				 * If we were in MST mode, and device is not
> > -				 * there, get out of MST mode
> > -				 */
> > -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > -				intel_dp->is_mst = false;
> > -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > -								intel_dp->is_mst);
> > -				goto put_power;
> > -			}
> > -		}
> > -
> > -		if (!intel_dp->is_mst) {
> > -			if (!intel_dp_short_pulse(intel_dp)) {
> > -				intel_dp_long_pulse(intel_dp->attached_connector);
> > -				goto put_power;
> > -			}
> > +	if (intel_dp->is_mst) {
> > +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > +			/*
> > +			 * If we were in MST mode, and device is not
> > +			 * there, get out of MST mode
> > +			 */
> > +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > +			intel_dp->is_mst = false;
> > +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > +							intel_dp->is_mst);
> > +			goto put_power;
> >  		}
> > +	} else {
> > +		if (!intel_dp_short_pulse(intel_dp))
> > +			goto put_power;
> >  	}
> >  
> > +	/*
> > +	 * Link retraining happens from the hotplug work,
> > +	 * check if we might need to schdule it.
> > +	 *
> > +	 * There has been known issues of link loss
> > +	 * triggerring long pulse, so let's check both
> > +	 * for short and long pulse.
> > +	 */
> > +	if (intel_dp_link_needs_retrain(intel_dp))
> > +		goto put_power;
> > +
> >  	ret = IRQ_HANDLED;
> >  
> >  put_power:
> > -- 
> > 2.7.4
> > 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-28 20:15     ` Ville Syrjälä
@ 2016-07-29  0:36       ` Manasi Navare
  2016-07-29  9:52         ` Ville Syrjälä
  2016-07-29 21:45         ` Manasi Navare
  0 siblings, 2 replies; 54+ messages in thread
From: Manasi Navare @ 2016-07-29  0:36 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 11:15:22PM +0300, Ville Syrjälä wrote:
> On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> > On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > DP link retraining needs to grab some modeset locks to not race with
> > > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > > risk deadlocking due to MST sideband stuff.
> > > 
> > > Move the link retraining to happen from the hotplug work instead.
> > > Doing at the end of intel_dp_detect() seems like a good place in case
> > > the sink already got disconnected, in which case retraining is
> > > pointless.
> > > 
> > > To determine if we need to schedule the hotplug work, we'll just check
> > > the sink lane status without locks from hpd_pulse. A little racy
> > > still eg. due to useing intel_dp->lane_count, but no less racy than
> > > what we already had. We'll repeat the check in from intel_dp_detect()
> > > with proper locking, where we'll also check if the link as actually
> > > active or not.
> > > 
> > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> > >  1 file changed, 66 insertions(+), 88 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 4a4184c21989..675b83f57a07 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> > >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> > >  go_again:
> > >  		if (bret == true) {
> > > -
> > > -			/* check link status - esi[10] = 0x200c */
> > > -			if (intel_dp->active_streams &&
> > > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > -				intel_dp_start_link_train(intel_dp);
> > > -				intel_dp_stop_link_train(intel_dp);
> > > -			}
> > > -
> > >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> > >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> > >  
> > > @@ -3886,34 +3877,42 @@ go_again:
> > >  	return -EINVAL;
> > >  }
> > >  
> > > -static void
> > > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > > +static bool
> > > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> > >  {
> > > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > >  	u8 link_status[DP_LINK_STATUS_SIZE];
> > >  
> > > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > > +	if (intel_dp->active_streams == 0)
> > > +		return false;
> > > +
> > > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > > +		return true;
> > >  
> > >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> > >  		DRM_ERROR("Failed to get link status\n");
> > > -		return;
> > > +		return false;
> > >  	}
> > >  
> > > -	if (!intel_encoder->base.crtc)
> > > -		return;
> > > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> > 
> > According to the DP spec, we should also check for the clock recovery bit in DPCD
> > We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)
> 
> I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
> CR_DONE, EQ_DONE, and SYMBOL_LOCKED.

It only checks for EQ_DONE and INTERLANE_ALIGN_DONE.
drm_dp_clock_recovery_ok() checks for DP_LANE_CR_DONE bit.
> 
> Anyways, while I was looking at the short pulse handling a bit more, I came
> to the conclusion that we should rewrite it a bit.
> 
> The CTS docs seem to say that we're expected to read DPCD 0x200-0x205 on 
> short pulse, and use that information to determine what we should do.
> Currently we don't do that.
> 
> So I was thunking that we'd adjust the link_status stuff to read 0x200-0x207
> instead of 0x202-0x207, like so:
> -#define DP_LINK_STATUS_SIZE       6
> +#define DP_LINK_STATUS_SIZE       8
> 
>  static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
>  {
> -       return link_status[r - DP_LANE0_1_STATUS];
> +       return link_status[r - DP_SINK_COUNT];
>  }
> 
> And then we'd use something like this as our short pulse handler:
> 
> static bool
> intel_dp_short_pulse(struct intel_dp *intel_dp)
> {
>         u8 link_status[DP_LINK_STATUS_SIZE], tmp;
> 
>         /*                                                                                                             
>          * Clearing compliance test variables to allow capturing                                                       
>          * of values for next automated test request.                                                                  
>          */
>         intel_dp->compliance_test_active = 0;
>         intel_dp->compliance_test_type = 0;
>         intel_dp->compliance_test_data = 0;
> 
>         if (!intel_dp_get_link_status(intel_dp, link_status))
>                 return false;
> 
>         tmp = drm_dp_link_status(link_status, DP_DEVICE_SERVICE_IRQ_VECTOR);
>         if (tmp)
>                 drm_dp_dpcd_writeb(&intel_dp->aux,
>                                    DP_DEVICE_SERVICE_IRQ_VECTOR,
>                                    tmp);
> 
>         if (tmp & DP_AUTOMATED_TEST_REQUEST)
>                 DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
>         if (tmp & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
>                 DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
> 
>         tmp = drm_dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
>         if (tmp & DP_DOWNSTREAM_PORT_STATUS_CHANGED)
>                 return false;
> 
>         tmp = drm_dp_link_status(link_status, DP_SINK_COUNT);
>         if (DP_GET_SINK_COUNT(tmp) != intel_dp->sink_count)
>                 return false;
> 
>         if (intel_dp->active_streams != 0 &&
>             !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))
>                 return false;
> 
>         return true;
> }
> 
> and obviously fill in whatever else sink irq handling we need.
> 
> Thoughts? Does that look sane?

Yes all the Link maintenance tests in CTS spec expect DPCD registers
0200h-0205h to be read on loss of symbol lock or loss of clock recovery.
So I think it makes sense to read 0200-0205h.

> 
> <snip>
> > >  
> > >  static enum drm_connector_status
> > >  intel_dp_detect(struct drm_connector *connector, bool force)
> > >  {
> > >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> > > -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> > > -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> > >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> > > +	enum drm_connector_status status;
> > >  
> > >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> > >  		      connector->base.id, connector->name);
> > >  
> > > -	if (intel_dp->is_mst) {
> > > -		/* MST devices are disconnected from a monitor POV */
> > > -		intel_dp_unset_edid(intel_dp);
> > > -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> > > -			intel_encoder->type = INTEL_OUTPUT_DP;
> > > -		return connector_status_disconnected;
> > > -	}
> > > -
> > > -	/* If full detect is not performed yet, do a full detect */
> > > -	if (!intel_dp->detect_done)
> > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > +	status = intel_dp_long_pulse(intel_connector);
> > >  
> > > -	intel_dp->detect_done = false;
> > > +	if (status == connector_status_connected || intel_dp->is_mst)
> > 
> > Whya re we not checking for (!intel_encoder->crtc.base) before retraining?
> > I had seen issues with connected boot case when connector status is connected and if it
> > tries to retrain it fails with retries because there is no active pipe. In that
> > case it should not attempt to retrain.
> 
> I changed it to use intel_dp->active_streams instead. That'll work for MST
> as well as SST. Checking for the crtc would only cover SST.
> 
> > 
> > 
> > > +		intel_dp_link_retrain(intel_dp);
> > >  
> > > -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> > > -		return connector_status_connected;
> > > -	else
> > > -		return connector_status_disconnected;
> > > +	return status;
> > >  }
> > >  
> > >  static void
> > > @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
> > >  		      port_name(intel_dig_port->port),
> > >  		      long_hpd ? "long" : "short");
> > >  
> > > +	if (long_hpd)
> > > +		return IRQ_NONE;
> > > +
> > >  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> > >  	intel_display_power_get(dev_priv, power_domain);
> > >  
> > > -	if (long_hpd) {
> > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > -		if (intel_dp->is_mst)
> > > -			ret = IRQ_HANDLED;
> > > -		goto put_power;
> > > -
> > > -	} else {
> > > -		if (intel_dp->is_mst) {
> > > -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > -				/*
> > > -				 * If we were in MST mode, and device is not
> > > -				 * there, get out of MST mode
> > > -				 */
> > > -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > -				intel_dp->is_mst = false;
> > > -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > -								intel_dp->is_mst);
> > > -				goto put_power;
> > > -			}
> > > -		}
> > > -
> > > -		if (!intel_dp->is_mst) {
> > > -			if (!intel_dp_short_pulse(intel_dp)) {
> > > -				intel_dp_long_pulse(intel_dp->attached_connector);
> > > -				goto put_power;
> > > -			}
> > > +	if (intel_dp->is_mst) {
> > > +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > +			/*
> > > +			 * If we were in MST mode, and device is not
> > > +			 * there, get out of MST mode
> > > +			 */
> > > +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > +			intel_dp->is_mst = false;
> > > +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > +							intel_dp->is_mst);
> > > +			goto put_power;
> > >  		}
> > > +	} else {
> > > +		if (!intel_dp_short_pulse(intel_dp))
> > > +			goto put_power;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Link retraining happens from the hotplug work,
> > > +	 * check if we might need to schdule it.
> > > +	 *
> > > +	 * There has been known issues of link loss
> > > +	 * triggerring long pulse, so let's check both
> > > +	 * for short and long pulse.
> > > +	 */
> > > +	if (intel_dp_link_needs_retrain(intel_dp))
> > > +		goto put_power;
> > > +
> > >  	ret = IRQ_HANDLED;
> > >  
> > >  put_power:
> > > -- 
> > > 2.7.4
> > > 
> 
> -- 
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup
  2016-07-28 14:50 ` [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup ville.syrjala
@ 2016-07-29  9:16   ` Daniel Vetter
  2016-07-29  9:55     ` Ville Syrjälä
  2016-08-01  9:24   ` Maarten Lankhorst
  1 sibling, 1 reply; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:16 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:39PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The MST vs. SST selection should depend purely on the choice of the
> connector/encoder. So don't try to determine the correct DDI mode
> based on the intel_dp->is_mst, which simply tells us whether the sink
> is in MST mode or not. Instead derive the information from the encoder
> type. Since the link training code deals in non-fake encoders, we'll
> also need to keep a second copy of that information around, which we'll
> now designate as 'link_mst'.
> 
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Hm, I think it'd be nice if we could shovel all this stuff into the crtc
state I think, instead of noodling it out of somewhere else. But since we
always update it in pre_enable hooks it should be all fine even with
TEST_ONLY atomic.

I digress, change looks good.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 21 +++------------------
>  drivers/gpu/drm/i915/intel_dp.c  |  1 +
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  3 files changed, 5 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index dd1d6fe12297..3b3a0a808477 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1111,7 +1111,6 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
>  {
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
> -	struct drm_encoder *encoder = &intel_encoder->base;
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	enum pipe pipe = intel_crtc->pipe;
> @@ -1177,29 +1176,15 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
>  			temp |= TRANS_DDI_MODE_SELECT_HDMI;
>  		else
>  			temp |= TRANS_DDI_MODE_SELECT_DVI;
> -
>  	} else if (type == INTEL_OUTPUT_ANALOG) {
>  		temp |= TRANS_DDI_MODE_SELECT_FDI;
>  		temp |= (intel_crtc->config->fdi_lanes - 1) << 1;
> -
>  	} else if (type == INTEL_OUTPUT_DP ||
>  		   type == INTEL_OUTPUT_EDP) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		if (intel_dp->is_mst) {
> -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> -		} else
> -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> -
> +		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
>  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
>  	} else if (type == INTEL_OUTPUT_DP_MST) {
> -		struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
> -
> -		if (intel_dp->is_mst) {
> -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> -		} else
> -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> -
> +		temp |= TRANS_DDI_MODE_SELECT_DP_MST;
>  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
>  	} else {
>  		WARN(1, "Invalid encoder type %d for pipe %c\n",
> @@ -2105,7 +2090,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
>  
>  	val = DP_TP_CTL_ENABLE |
>  	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
> -	if (intel_dp->is_mst)
> +	if (intel_dp->link_mst)
>  		val |= DP_TP_CTL_MODE_MST;
>  	else {
>  		val |= DP_TP_CTL_MODE_SST;
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 8c38e3483989..0096c651c21f 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1651,6 +1651,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
>  {
>  	intel_dp->link_rate = pipe_config->port_clock;
>  	intel_dp->lane_count = pipe_config->lane_count;
> +	intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
>  }
>  
>  static void intel_dp_prepare(struct intel_encoder *encoder)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e74d851868c5..70d7f33d6747 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -852,6 +852,7 @@ struct intel_dp {
>  	int link_rate;
>  	uint8_t lane_count;
>  	uint8_t sink_count;
> +	bool link_mst;
>  	bool has_audio;
>  	bool detect_done;
>  	enum hdmi_force_audio force_audio;
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  2016-07-28 14:50 ` [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port ville.syrjala
@ 2016-07-29  9:19   ` Daniel Vetter
  2016-07-29 11:28     ` Ville Syrjälä
  2016-08-01  9:28   ` Maarten Lankhorst
  1 sibling, 1 reply; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:19 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:40PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We can't mix MST with SST/HDMI on the same physical port, so we'll need
> to reject such configurations in check_digital_port_conflicts(). Nothing
> else will prevent this as MST has its fake encoders and its own connectors
> so the cloning checks won't catch this.
> 
> The same digital port can be used multiple times, but only if all the
> encoders involved are MST encoders, so we only want to check MST vs.
> SST/HDMI, not MST vs. MST. And SST/HDMI vs. SST/HDMI we already check.
> 
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I'd be awesome if we could have some testcases for this. We can e.g. try
to enable HDMI without it being connected (it'll fall back to dvi mode),
so could use that to try enabling both hdmi and dp or dp mst out of sheer
nastiness. I don't even think we need to check that it gets rejected
correctly, just trying to do such a modeset on a broken kernel should
result in plenty of fireworks in dmesg (state checker for sure will be
unhapy) to make it obvious it's broken. Aka would absolutely love if this
patch gained a Testcase: line. Either way:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c4c1c85366de..a6699c76bef3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12305,6 +12305,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>  	struct drm_device *dev = state->dev;
>  	struct drm_connector *connector;
>  	unsigned int used_ports = 0;
> +	unsigned int used_mst_ports = 0;
>  
>  	/*
>  	 * Walk the connector list instead of the encoder
> @@ -12341,11 +12342,20 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
>  				return false;
>  
>  			used_ports |= port_mask;
> +			break;
> +		case INTEL_OUTPUT_DP_MST:
> +			used_mst_ports |=
> +				1 << enc_to_mst(&encoder->base)->primary->port;
> +			break;
>  		default:
>  			break;
>  		}
>  	}
>  
> +	/* can't mix MST and SST/HDMI on the same port */
> +	if (used_ports & used_mst_ports)
> +		return false;
> +
>  	return true;
>  }
>  
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 05/12] drm/i915: Track active streams also for DP SST
  2016-07-28 14:50 ` [PATCH 05/12] drm/i915: Track active streams also for DP SST ville.syrjala
@ 2016-07-29  9:22   ` Daniel Vetter
  2016-07-29 11:36     ` Ville Syrjälä
  0 siblings, 1 reply; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:22 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:41PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> s/active_mst_links/active_streams/ and use it also for SST. We can then
> use this information in the hpd handling to see if the link is active
> or not, and thus whether we may need to retrain.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Hm, more state not in the state structures, and not cross-checked :( Ben
Skeggs just pinged me on this, and one of the ideas he's now looking into
is a separate state array for mst ports to fully keep track of this. Kinda
like we keep track of the shared dplls.

Again just ideas, code looks correct.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_ddi.c    | 10 ++++++++++
>  drivers/gpu/drm/i915/intel_dp.c     |  8 +++++++-
>  drivers/gpu/drm/i915/intel_dp_mst.c | 16 ++++++++--------
>  drivers/gpu/drm/i915/intel_drv.h    |  2 +-
>  4 files changed, 26 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 3b3a0a808477..bc188ee6e37f 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1616,6 +1616,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
>  
>  		intel_ddi_init_dp_buf_reg(intel_encoder);
>  
> +		WARN_ON(intel_dp->active_streams != 0);
> +		intel_dp->active_streams++;
> +
>  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>  		intel_dp_start_link_train(intel_dp);
>  		if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
> @@ -1733,6 +1736,13 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>  		intel_psr_disable(intel_dp);
>  		intel_edp_backlight_off(intel_dp);
>  	}
> +
> +	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		intel_dp->active_streams--;
> +		WARN_ON(intel_dp->active_streams != 0);
> +	}
>  }
>  
>  bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 0096c651c21f..3a9c5d3b5c66 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2685,6 +2685,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>  				    lane_mask);
>  	}
>  
> +	WARN_ON(intel_dp->active_streams != 0);
> +	intel_dp->active_streams++;
> +
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>  	intel_dp_start_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
> @@ -3344,6 +3347,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
>  
>  	DRM_DEBUG_KMS("\n");
>  
> +	intel_dp->active_streams--;
> +	WARN_ON(intel_dp->active_streams != 0);
> +
>  	if ((IS_GEN7(dev) && port == PORT_A) ||
>  	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
>  		DP &= ~DP_LINK_TRAIN_MASK_CPT;
> @@ -3826,7 +3832,7 @@ go_again:
>  		if (bret == true) {
>  
>  			/* check link status - esi[10] = 0x200c */
> -			if (intel_dp->active_mst_links &&
> +			if (intel_dp->active_streams &&
>  			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
>  				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
>  				intel_dp_start_link_train(intel_dp);
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 68a005d729e9..857cfa6928b3 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -99,7 +99,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
>  	int ret;
>  
> -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
>  
>  	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
>  
> @@ -115,7 +115,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
>  	struct intel_digital_port *intel_dig_port = intel_mst->primary;
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
>  
> -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
>  
>  	/* this can fail */
>  	drm_dp_check_act_status(&intel_dp->mst_mgr);
> @@ -124,10 +124,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
>  
>  	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
>  
> -	intel_dp->active_mst_links--;
> +	intel_dp->active_streams--;
>  
>  	intel_mst->connector = NULL;
> -	if (intel_dp->active_mst_links == 0) {
> +	if (intel_dp->active_streams == 0) {
>  		intel_dig_port->base.post_disable(&intel_dig_port->base);
>  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>  	}
> @@ -165,11 +165,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
>  	 */
>  	found->encoder = encoder;
>  
> -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
>  
>  	intel_mst->connector = found;
>  
> -	if (intel_dp->active_mst_links == 0) {
> +	if (intel_dp->active_streams == 0) {
>  		intel_prepare_ddi_buffer(&intel_dig_port->base);
>  
>  		intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
> @@ -193,7 +193,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
>  	}
>  
>  
> -	intel_dp->active_mst_links++;
> +	intel_dp->active_streams++;
>  	temp = I915_READ(DP_TP_STATUS(port));
>  	I915_WRITE(DP_TP_STATUS(port), temp);
>  
> @@ -210,7 +210,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
>  	enum port port = intel_dig_port->port;
>  	int ret;
>  
> -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
>  
>  	if (intel_wait_for_register(dev_priv,
>  				    DP_TP_STATUS(port),
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 70d7f33d6747..7fef18288aa2 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -894,7 +894,7 @@ struct intel_dp {
>  
>  	bool can_mst; /* this port supports mst */
>  	bool is_mst;
> -	int active_mst_links;
> +	int active_streams; /* number of active streams (for SST and MST both) */
>  	/* connector directly attached - won't be use for modeset in mst world */
>  	struct intel_connector *attached_connector;
>  
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
  2016-07-28 14:50 ` [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails ville.syrjala
@ 2016-07-29  9:29   ` Daniel Vetter
  2016-07-29 11:41     ` Ville Syrjälä
  2016-07-29 13:51   ` [PATCH v2 " ville.syrjala
  1 sibling, 1 reply; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:29 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:42PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> With HSW + Dell UP2414Q (at least) drm_probe_ddc() occasionally fails,
> and then we'll assume that the entire display has been disconnected.
> We don't need the EDID from the main link, so we can simply check if
> the sink is MST capable, and if so treat is as connected.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++--------------
>  1 file changed, 30 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3a9c5d3b5c66..4a4184c21989 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3538,7 +3538,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
>  }
>  
>  static bool
> -intel_dp_probe_mst(struct intel_dp *intel_dp)
> +intel_dp_can_mst(struct intel_dp *intel_dp)
>  {
>  	u8 buf[1];
>  
> @@ -3551,18 +3551,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
>  	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
>  		return false;
>  
> -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
> -		if (buf[0] & DP_MST_CAP) {
> -			DRM_DEBUG_KMS("Sink is MST capable\n");
> -			intel_dp->is_mst = true;
> -		} else {
> -			DRM_DEBUG_KMS("Sink is not MST capable\n");
> -			intel_dp->is_mst = false;
> -		}
> -	}
> +	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1) != 1)
> +		return false;
>  
> -	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
> -	return intel_dp->is_mst;
> +	return buf[0] & DP_MST_CAP;
> +}
> +
> +static void
> +intel_dp_configure_mst(struct intel_dp *intel_dp)
> +{
> +	if (!i915.enable_dp_mst)
> +		return;
> +
> +	if (!intel_dp->can_mst)
> +		return;
> +
> +	intel_dp->is_mst = intel_dp_can_mst(intel_dp);

can_mst (is the hw capable) vs. can_mst (is the sink capable). Needs a
can_sink_mst or something else.

Also this really should be part of the mst helpers imo ...

> +
> +	if (intel_dp->is_mst)
> +		DRM_DEBUG_KMS("Sink is MST capable\n");
> +	else
> +		DRM_DEBUG_KMS("Sink is not MST capable\n");
> +
> +	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> +					intel_dp->is_mst);
>  }
>  
>  static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
> @@ -3993,6 +4005,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
>  	if (drm_probe_ddc(&intel_dp->aux.ddc))
>  		return connector_status_connected;
>  
> +	if (intel_dp_can_mst(intel_dp))
> +		return connector_status_connected;

Shouldn't we instead just outright not poke the ddc when there's an mst
branch connected? The dp mst helpers will read the ddc for the final leaf
ports, anything intermediate is kinda bonghits anyway. So

  	if (!intel_dp_can_mst() && drm_probe_ddc(&intel_dp->aux.ddc))
  		return connector_status_connected;

I think with that it makes a lot more sense and is

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

And again, this so should be all shared in dp helpers somehow.
-Daniel

> +
>  	/* Well we tried, say unknown for unreliable port types */
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
>  		type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
> @@ -4213,7 +4228,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	struct drm_device *dev = connector->dev;
>  	enum drm_connector_status status;
>  	enum intel_display_power_domain power_domain;
> -	bool ret;
>  	u8 sink_irq_vector;
>  
>  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> @@ -4249,8 +4263,9 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  
>  	intel_dp_probe_oui(intel_dp);
>  
> -	ret = intel_dp_probe_mst(intel_dp);
> -	if (ret) {
> +	intel_dp_configure_mst(intel_dp);
> +
> +	if (intel_dp->is_mst) {
>  		/*
>  		 * If we are in MST mode then this connector
>  		 * won't appear connected or have anything
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage
  2016-07-28 14:50 ` [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage ville.syrjala
@ 2016-07-29  9:33   ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:33 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:45PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> No need to iterate the rates array in intel_dp_max_link_rate(). We know
> the max rate will be the last entry, and we already know the size.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Yeah, that's some rather convoluted logic.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d1dd351682d2..40cae6202160 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1447,7 +1447,7 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
>  	if (WARN_ON(len <= 0))
>  		return 162000;
>  
> -	return rates[rate_to_index(0, rates) - 1];
> +	return rates[len - 1];
>  }
>  
>  int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches
  2016-07-28 14:50 ` [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches ville.syrjala
@ 2016-07-29  9:35   ` Daniel Vetter
  2016-07-29 11:43     ` Ville Syrjälä
  0 siblings, 1 reply; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:35 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:46PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Let's make rate_to_index() return the highest rate available that's
> less than or equal to the rate requested by the caller. The function
> can then be used to filter out rates higher than a certain maximum
> rate.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Not sure what this will be used for, couldn't figure it out looking at
later patches?
-Daneil

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 40cae6202160..08d95352ffd6 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1431,10 +1431,13 @@ static int rate_to_index(int find, const int *rates)
>  	int i = 0;
>  
>  	for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
> -		if (find == rates[i])
> +		if (find < rates[i])
>  			break;
>  
> -	return i;
> +	if (WARN_ON(i == 0))
> +		return 0;
> +
> +	return i - 1;
>  }
>  
>  int
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none
  2016-07-28 14:50 ` [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none ville.syrjala
@ 2016-07-29  9:38   ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:38 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:47PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> My ASUS PB278 at least doesn't seem to appreciate when you try to
> ack sink irqs when there are none. Results in thus sort of dmesg spam
> [drm:drm_dp_dpcd_access] too many retries, giving up
> 
> Let's skip the ack if there are no pending irqs. I have no clue why we
> do this in two places. One of them likely should just go away. Oh, and
> MST has its own sink irq handler too...
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Yeah it's a mess still :( Change itself makes sense.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 08d95352ffd6..7551d92a3cfb 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3934,7 +3934,7 @@ intel_dp_link_retrain(struct intel_dp *intel_dp)
>  static bool
>  intel_dp_short_pulse(struct intel_dp *intel_dp)
>  {
> -	u8 sink_irq_vector;
> +	u8 sink_irq_vector = 0;
>  	u8 old_sink_count = intel_dp->sink_count;
>  	bool ret;
>  
> @@ -3961,7 +3961,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
>  
>  	/* Try to read the source of the interrupt */
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
> -	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
> +	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector) &&
> +	    sink_irq_vector != 0) {
>  		/* Clear interrupt source */
>  		drm_dp_dpcd_writeb(&intel_dp->aux,
>  				   DP_DEVICE_SERVICE_IRQ_VECTOR,
> @@ -4227,7 +4228,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	struct drm_device *dev = connector->dev;
>  	enum drm_connector_status status;
>  	enum intel_display_power_domain power_domain;
> -	u8 sink_irq_vector;
> +	u8 sink_irq_vector = 0;
>  
>  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
>  	intel_display_power_get(to_i915(dev), power_domain);
> @@ -4292,7 +4293,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  
>  	/* Try to read the source of the interrupt */
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
> -	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
> +	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector) &&
> +	    sink_irq_vector != 0) {
>  		/* Clear interrupt source */
>  		drm_dp_dpcd_writeb(&intel_dp->aux,
>  				   DP_DEVICE_SERVICE_IRQ_VECTOR,
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook
  2016-07-28 14:50 ` [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook ville.syrjala
@ 2016-07-29  9:42   ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-07-29  9:42 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Jul 28, 2016 at 05:50:48PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We cache a bunch of state under the encoders (eg. link freq and
> lane count for DP). We need to refresh that cached state on
> init/resume during hardware readout. Since we have already read out
> most interesting details into the pipe config, let's add a new
> optional encoder hook that can move the information from the pipe
> config into the encoder.
> 
> We can't really use the pipe config directly since this cached
> information is used during link retraining, which doesn't have
> access to a pipe config (mainly due to MST). Redoing MST in a way where
> the actual link would be part of the modeset with its own pipe config
> could be an alternative solution, but that would be a much more massive
> undertaking. For now, let's at least try to keep the two pieces of
> state in sync.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I really don't like that we have state stored in non-state structure
places. Especially with upfront link training at hpd time it probably
makes sense to figure this all out at compute_config time, and then store
it in the crtc state. Ok probably it needs to be somewhere else, not
attached to crtc, so maybe an array of port states. And cross-checking
would be real great for this too ...
-Daniel


> ---
>  drivers/gpu/drm/i915/intel_ddi.c     |  4 ++++
>  drivers/gpu/drm/i915/intel_display.c |  4 ++++
>  drivers/gpu/drm/i915/intel_dp.c      | 18 ++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  7 +++++++
>  4 files changed, 33 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index bc188ee6e37f..2b679f72eba4 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2314,6 +2314,9 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port)
>  	return connector;
>  }
>  
> +void intel_dp_sync_state(struct intel_encoder *encoder,
> +			 const struct intel_crtc_state *pipe_config);
> +
>  void intel_ddi_init(struct drm_device *dev, enum port port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> @@ -2377,6 +2380,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
>  	intel_encoder->post_disable = intel_ddi_post_disable;
>  	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
>  	intel_encoder->get_config = intel_ddi_get_config;
> +	intel_encoder->sync_state = intel_dp_sync_state;
>  	intel_encoder->suspend = intel_dp_encoder_suspend;
>  
>  	intel_dig_port->port = port;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a6699c76bef3..dffcc814c178 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -16031,8 +16031,12 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  			encoder->base.crtc = &crtc->base;
>  			crtc->config->output_types |= 1 << encoder->type;
>  			encoder->get_config(encoder, crtc->config);
> +			if (encoder->sync_state)
> +				encoder->sync_state(encoder, crtc->config);
>  		} else {
>  			encoder->base.crtc = NULL;
> +			if (encoder->sync_state)
> +				encoder->sync_state(encoder, NULL);
>  		}
>  
>  		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 7551d92a3cfb..44567dd68257 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2482,6 +2482,23 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
>  	}
>  }
>  
> +void intel_dp_sync_state(struct intel_encoder *encoder,
> +			 const struct intel_crtc_state *pipe_config)
> +{
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +
> +	if (pipe_config) {
> +		/* FIXME MST */
> +		intel_dp->active_streams = 1;
> +		intel_dp->link_rate = pipe_config->port_clock;
> +		intel_dp->lane_count = pipe_config->lane_count;
> +	} else {
> +		intel_dp->active_streams = 0;
> +		intel_dp->link_rate = 0;
> +		intel_dp->lane_count = 0;
> +	}
> +}
> +
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -5675,6 +5692,7 @@ bool intel_dp_init(struct drm_device *dev,
>  	intel_encoder->disable = intel_disable_dp;
>  	intel_encoder->get_hw_state = intel_dp_get_hw_state;
>  	intel_encoder->get_config = intel_dp_get_config;
> +	intel_encoder->sync_state = intel_dp_sync_state;
>  	intel_encoder->suspend = intel_dp_encoder_suspend;
>  	if (IS_CHERRYVIEW(dev)) {
>  		intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 20cf7ad26357..49c75caa4150 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -213,6 +213,13 @@ struct intel_encoder {
>  	void (*get_config)(struct intel_encoder *,
>  			   struct intel_crtc_state *pipe_config);
>  	/*
> +	 * Used during init/resume to sync any cached state
> +	 * stored outside the pipe config (eg. active DP link
> +	 * parameters).
> +	 */
> +	void (*sync_state)(struct intel_encoder *,
> +			   const struct intel_crtc_state *);
> +	/*
>  	 * Called during system suspend after all pending requests for the
>  	 * encoder are flushed (for example for DP AUX transactions) and
>  	 * device interrupts are disabled.
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-29  0:36       ` Manasi Navare
@ 2016-07-29  9:52         ` Ville Syrjälä
  2016-07-29 21:42           ` Manasi Navare
  2016-07-29 21:45         ` Manasi Navare
  1 sibling, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29  9:52 UTC (permalink / raw)
  To: Manasi Navare; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:36:14PM -0700, Manasi Navare wrote:
> On Thu, Jul 28, 2016 at 11:15:22PM +0300, Ville Syrjälä wrote:
> > On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> > > On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > DP link retraining needs to grab some modeset locks to not race with
> > > > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > > > risk deadlocking due to MST sideband stuff.
> > > > 
> > > > Move the link retraining to happen from the hotplug work instead.
> > > > Doing at the end of intel_dp_detect() seems like a good place in case
> > > > the sink already got disconnected, in which case retraining is
> > > > pointless.
> > > > 
> > > > To determine if we need to schedule the hotplug work, we'll just check
> > > > the sink lane status without locks from hpd_pulse. A little racy
> > > > still eg. due to useing intel_dp->lane_count, but no less racy than
> > > > what we already had. We'll repeat the check in from intel_dp_detect()
> > > > with proper locking, where we'll also check if the link as actually
> > > > active or not.
> > > > 
> > > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> > > >  1 file changed, 66 insertions(+), 88 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > index 4a4184c21989..675b83f57a07 100644
> > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> > > >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> > > >  go_again:
> > > >  		if (bret == true) {
> > > > -
> > > > -			/* check link status - esi[10] = 0x200c */
> > > > -			if (intel_dp->active_streams &&
> > > > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > > -				intel_dp_start_link_train(intel_dp);
> > > > -				intel_dp_stop_link_train(intel_dp);
> > > > -			}
> > > > -
> > > >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> > > >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> > > >  
> > > > @@ -3886,34 +3877,42 @@ go_again:
> > > >  	return -EINVAL;
> > > >  }
> > > >  
> > > > -static void
> > > > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > > > +static bool
> > > > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> > > >  {
> > > > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > > > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > > >  	u8 link_status[DP_LINK_STATUS_SIZE];
> > > >  
> > > > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > > > +	if (intel_dp->active_streams == 0)
> > > > +		return false;
> > > > +
> > > > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > > > +		return true;
> > > >  
> > > >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> > > >  		DRM_ERROR("Failed to get link status\n");
> > > > -		return;
> > > > +		return false;
> > > >  	}
> > > >  
> > > > -	if (!intel_encoder->base.crtc)
> > > > -		return;
> > > > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> > > 
> > > According to the DP spec, we should also check for the clock recovery bit in DPCD
> > > We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)
> > 
> > I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
> > CR_DONE, EQ_DONE, and SYMBOL_LOCKED.
> 
> It only checks for EQ_DONE and INTERLANE_ALIGN_DONE.

It checks DP_CHANNEL_EQ_BITS which is

#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE |           \
                            DP_LANE_CHANNEL_EQ_DONE |   \
                            DP_LANE_SYMBOL_LOCKED)

> drm_dp_clock_recovery_ok() checks for DP_LANE_CR_DONE bit.
> > 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup
  2016-07-29  9:16   ` Daniel Vetter
@ 2016-07-29  9:55     ` Ville Syrjälä
  2016-08-02 14:20       ` Daniel Vetter
  0 siblings, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29  9:55 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Fri, Jul 29, 2016 at 11:16:19AM +0200, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 05:50:39PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > The MST vs. SST selection should depend purely on the choice of the
> > connector/encoder. So don't try to determine the correct DDI mode
> > based on the intel_dp->is_mst, which simply tells us whether the sink
> > is in MST mode or not. Instead derive the information from the encoder
> > type. Since the link training code deals in non-fake encoders, we'll
> > also need to keep a second copy of that information around, which we'll
> > now designate as 'link_mst'.
> > 
> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Hm, I think it'd be nice if we could shovel all this stuff into the crtc
> state I think, instead of noodling it out of somewhere else.

You mean stuffing a pre-computed (partial?) register value in the
crtc state? That could work too.

> But since we
> always update it in pre_enable hooks it should be all fine even with
> TEST_ONLY atomic.
> 
> I digress, change looks good.
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c | 21 +++------------------
> >  drivers/gpu/drm/i915/intel_dp.c  |  1 +
> >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> >  3 files changed, 5 insertions(+), 18 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index dd1d6fe12297..3b3a0a808477 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1111,7 +1111,6 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
> >  {
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >  	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
> > -	struct drm_encoder *encoder = &intel_encoder->base;
> >  	struct drm_device *dev = crtc->dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	enum pipe pipe = intel_crtc->pipe;
> > @@ -1177,29 +1176,15 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
> >  			temp |= TRANS_DDI_MODE_SELECT_HDMI;
> >  		else
> >  			temp |= TRANS_DDI_MODE_SELECT_DVI;
> > -
> >  	} else if (type == INTEL_OUTPUT_ANALOG) {
> >  		temp |= TRANS_DDI_MODE_SELECT_FDI;
> >  		temp |= (intel_crtc->config->fdi_lanes - 1) << 1;
> > -
> >  	} else if (type == INTEL_OUTPUT_DP ||
> >  		   type == INTEL_OUTPUT_EDP) {
> > -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > -
> > -		if (intel_dp->is_mst) {
> > -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> > -		} else
> > -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> > -
> > +		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> >  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
> >  	} else if (type == INTEL_OUTPUT_DP_MST) {
> > -		struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
> > -
> > -		if (intel_dp->is_mst) {
> > -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> > -		} else
> > -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> > -
> > +		temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> >  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
> >  	} else {
> >  		WARN(1, "Invalid encoder type %d for pipe %c\n",
> > @@ -2105,7 +2090,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> >  
> >  	val = DP_TP_CTL_ENABLE |
> >  	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
> > -	if (intel_dp->is_mst)
> > +	if (intel_dp->link_mst)
> >  		val |= DP_TP_CTL_MODE_MST;
> >  	else {
> >  		val |= DP_TP_CTL_MODE_SST;
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 8c38e3483989..0096c651c21f 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1651,6 +1651,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
> >  {
> >  	intel_dp->link_rate = pipe_config->port_clock;
> >  	intel_dp->lane_count = pipe_config->lane_count;
> > +	intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
> >  }
> >  
> >  static void intel_dp_prepare(struct intel_encoder *encoder)
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index e74d851868c5..70d7f33d6747 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -852,6 +852,7 @@ struct intel_dp {
> >  	int link_rate;
> >  	uint8_t lane_count;
> >  	uint8_t sink_count;
> > +	bool link_mst;
> >  	bool has_audio;
> >  	bool detect_done;
> >  	enum hdmi_force_audio force_audio;
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  2016-07-29  9:19   ` Daniel Vetter
@ 2016-07-29 11:28     ` Ville Syrjälä
  2016-08-02 14:22       ` Daniel Vetter
  0 siblings, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29 11:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Fri, Jul 29, 2016 at 11:19:18AM +0200, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 05:50:40PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > We can't mix MST with SST/HDMI on the same physical port, so we'll need
> > to reject such configurations in check_digital_port_conflicts(). Nothing
> > else will prevent this as MST has its fake encoders and its own connectors
> > so the cloning checks won't catch this.
> > 
> > The same digital port can be used multiple times, but only if all the
> > encoders involved are MST encoders, so we only want to check MST vs.
> > SST/HDMI, not MST vs. MST. And SST/HDMI vs. SST/HDMI we already check.
> > 
> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> I'd be awesome if we could have some testcases for this. We can e.g. try
> to enable HDMI without it being connected (it'll fall back to dvi mode),
> so could use that to try enabling both hdmi and dp or dp mst out of sheer
> nastiness. I don't even think we need to check that it gets rejected
> correctly, just trying to do such a modeset on a broken kernel should
> result in plenty of fireworks in dmesg (state checker for sure will be
> unhapy) to make it obvious it's broken. Aka would absolutely love if this
> patch gained a Testcase: line. Either way:

What I've occasionally used for testing is kms_setmode with a patch to
ignore all errors from setcrtc so that it doesn't abort midway. IIRC
last time I did that on eg. HSW there were plenty of state checker
complaints. In its default state kms_setmode has a bit of a problem
because it doesn't know about conflicting connectors, nor does it know
if we're supposed to have one encoder per connector or pair of
connectors (DDI vs. !DDI). And also IIRC encoder/connector stealing
will wreac some extra havoc here. Not sure if there's a good way to
try and fix it so that by default kms_setmode would really test
what's it's pretending to test on all platforms.

I guess we could at least promote my hack to a proper command line
option, so that we can try to feed as many combinations to the kernel
as possible.

> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index c4c1c85366de..a6699c76bef3 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -12305,6 +12305,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> >  	struct drm_device *dev = state->dev;
> >  	struct drm_connector *connector;
> >  	unsigned int used_ports = 0;
> > +	unsigned int used_mst_ports = 0;
> >  
> >  	/*
> >  	 * Walk the connector list instead of the encoder
> > @@ -12341,11 +12342,20 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> >  				return false;
> >  
> >  			used_ports |= port_mask;
> > +			break;
> > +		case INTEL_OUTPUT_DP_MST:
> > +			used_mst_ports |=
> > +				1 << enc_to_mst(&encoder->base)->primary->port;
> > +			break;
> >  		default:
> >  			break;
> >  		}
> >  	}
> >  
> > +	/* can't mix MST and SST/HDMI on the same port */
> > +	if (used_ports & used_mst_ports)
> > +		return false;
> > +
> >  	return true;
> >  }
> >  
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 05/12] drm/i915: Track active streams also for DP SST
  2016-07-29  9:22   ` Daniel Vetter
@ 2016-07-29 11:36     ` Ville Syrjälä
  2016-07-29 18:36       ` Jim Bride
  0 siblings, 1 reply; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29 11:36 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 11:22:32AM +0200, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 05:50:41PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > s/active_mst_links/active_streams/ and use it also for SST. We can then
> > use this information in the hpd handling to see if the link is active
> > or not, and thus whether we may need to retrain.
> > 
> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > Cc: Jim Bride <jim.bride@linux.intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Hm, more state not in the state structures, and not cross-checked :( Ben
> Skeggs just pinged me on this, and one of the ideas he's now looking into
> is a separate state array for mst ports to fully keep track of this. Kinda
> like we keep track of the shared dplls.

Yeah it's a bit a mess. The other option I've outlined before might be a
fake crtc to drive the primary, and then use atomic enable/disable it at
the right time depending the state the of the actual MST streams.

Speaking of atomic/mst, I'm not sure our link retraining is really good
enough for MST. IIRC I saw a note in the spec that the payloads and
whatnot might get deallocated by the sink/hub if the link drops. I think
I have to re-read the spec a few times to make sure, but if that's the
case then we'd have to pimp up the link retraining to be MST aware. But,
I had an alternative idea recently; What if we just force a modeset on
all the pipes on that port? IIRC the spec even says that for link
retraining we should really be doing more or less the full modeset
sequence. It should also get rid of the FIFO underruns we now get every
time we retrain the link. Any thoughts?

> 
> Again just ideas, code looks correct.
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c    | 10 ++++++++++
> >  drivers/gpu/drm/i915/intel_dp.c     |  8 +++++++-
> >  drivers/gpu/drm/i915/intel_dp_mst.c | 16 ++++++++--------
> >  drivers/gpu/drm/i915/intel_drv.h    |  2 +-
> >  4 files changed, 26 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 3b3a0a808477..bc188ee6e37f 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1616,6 +1616,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
> >  
> >  		intel_ddi_init_dp_buf_reg(intel_encoder);
> >  
> > +		WARN_ON(intel_dp->active_streams != 0);
> > +		intel_dp->active_streams++;
> > +
> >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> >  		intel_dp_start_link_train(intel_dp);
> >  		if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
> > @@ -1733,6 +1736,13 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
> >  		intel_psr_disable(intel_dp);
> >  		intel_edp_backlight_off(intel_dp);
> >  	}
> > +
> > +	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> > +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > +
> > +		intel_dp->active_streams--;
> > +		WARN_ON(intel_dp->active_streams != 0);
> > +	}
> >  }
> >  
> >  bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 0096c651c21f..3a9c5d3b5c66 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2685,6 +2685,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> >  				    lane_mask);
> >  	}
> >  
> > +	WARN_ON(intel_dp->active_streams != 0);
> > +	intel_dp->active_streams++;
> > +
> >  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> >  	intel_dp_start_link_train(intel_dp);
> >  	intel_dp_stop_link_train(intel_dp);
> > @@ -3344,6 +3347,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
> >  
> >  	DRM_DEBUG_KMS("\n");
> >  
> > +	intel_dp->active_streams--;
> > +	WARN_ON(intel_dp->active_streams != 0);
> > +
> >  	if ((IS_GEN7(dev) && port == PORT_A) ||
> >  	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
> >  		DP &= ~DP_LINK_TRAIN_MASK_CPT;
> > @@ -3826,7 +3832,7 @@ go_again:
> >  		if (bret == true) {
> >  
> >  			/* check link status - esi[10] = 0x200c */
> > -			if (intel_dp->active_mst_links &&
> > +			if (intel_dp->active_streams &&
> >  			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> >  				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> >  				intel_dp_start_link_train(intel_dp);
> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> > index 68a005d729e9..857cfa6928b3 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > @@ -99,7 +99,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
> >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> >  	int ret;
> >  
> > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> >  
> >  	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
> >  
> > @@ -115,7 +115,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> >  	struct intel_digital_port *intel_dig_port = intel_mst->primary;
> >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> >  
> > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> >  
> >  	/* this can fail */
> >  	drm_dp_check_act_status(&intel_dp->mst_mgr);
> > @@ -124,10 +124,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> >  
> >  	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
> >  
> > -	intel_dp->active_mst_links--;
> > +	intel_dp->active_streams--;
> >  
> >  	intel_mst->connector = NULL;
> > -	if (intel_dp->active_mst_links == 0) {
> > +	if (intel_dp->active_streams == 0) {
> >  		intel_dig_port->base.post_disable(&intel_dig_port->base);
> >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
> >  	}
> > @@ -165,11 +165,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> >  	 */
> >  	found->encoder = encoder;
> >  
> > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> >  
> >  	intel_mst->connector = found;
> >  
> > -	if (intel_dp->active_mst_links == 0) {
> > +	if (intel_dp->active_streams == 0) {
> >  		intel_prepare_ddi_buffer(&intel_dig_port->base);
> >  
> >  		intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
> > @@ -193,7 +193,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> >  	}
> >  
> >  
> > -	intel_dp->active_mst_links++;
> > +	intel_dp->active_streams++;
> >  	temp = I915_READ(DP_TP_STATUS(port));
> >  	I915_WRITE(DP_TP_STATUS(port), temp);
> >  
> > @@ -210,7 +210,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
> >  	enum port port = intel_dig_port->port;
> >  	int ret;
> >  
> > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> >  
> >  	if (intel_wait_for_register(dev_priv,
> >  				    DP_TP_STATUS(port),
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 70d7f33d6747..7fef18288aa2 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -894,7 +894,7 @@ struct intel_dp {
> >  
> >  	bool can_mst; /* this port supports mst */
> >  	bool is_mst;
> > -	int active_mst_links;
> > +	int active_streams; /* number of active streams (for SST and MST both) */
> >  	/* connector directly attached - won't be use for modeset in mst world */
> >  	struct intel_connector *attached_connector;
> >  
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
  2016-07-29  9:29   ` Daniel Vetter
@ 2016-07-29 11:41     ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29 11:41 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 11:29:56AM +0200, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 05:50:42PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > With HSW + Dell UP2414Q (at least) drm_probe_ddc() occasionally fails,
> > and then we'll assume that the entire display has been disconnected.
> > We don't need the EDID from the main link, so we can simply check if
> > the sink is MST capable, and if so treat is as connected.
> > 
> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > Cc: Jim Bride <jim.bride@linux.intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++--------------
> >  1 file changed, 30 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 3a9c5d3b5c66..4a4184c21989 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3538,7 +3538,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
> >  }
> >  
> >  static bool
> > -intel_dp_probe_mst(struct intel_dp *intel_dp)
> > +intel_dp_can_mst(struct intel_dp *intel_dp)
> >  {
> >  	u8 buf[1];
> >  
> > @@ -3551,18 +3551,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
> >  	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
> >  		return false;
> >  
> > -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
> > -		if (buf[0] & DP_MST_CAP) {
> > -			DRM_DEBUG_KMS("Sink is MST capable\n");
> > -			intel_dp->is_mst = true;
> > -		} else {
> > -			DRM_DEBUG_KMS("Sink is not MST capable\n");
> > -			intel_dp->is_mst = false;
> > -		}
> > -	}
> > +	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1) != 1)
> > +		return false;
> >  
> > -	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
> > -	return intel_dp->is_mst;
> > +	return buf[0] & DP_MST_CAP;
> > +}
> > +
> > +static void
> > +intel_dp_configure_mst(struct intel_dp *intel_dp)
> > +{
> > +	if (!i915.enable_dp_mst)
> > +		return;
> > +
> > +	if (!intel_dp->can_mst)
> > +		return;
> > +
> > +	intel_dp->is_mst = intel_dp_can_mst(intel_dp);
> 
> can_mst (is the hw capable) vs. can_mst (is the sink capable). Needs a
> can_sink_mst or something else.
> 
> Also this really should be part of the mst helpers imo ...
> 
> > +
> > +	if (intel_dp->is_mst)
> > +		DRM_DEBUG_KMS("Sink is MST capable\n");
> > +	else
> > +		DRM_DEBUG_KMS("Sink is not MST capable\n");
> > +
> > +	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > +					intel_dp->is_mst);
> >  }
> >  
> >  static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
> > @@ -3993,6 +4005,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
> >  	if (drm_probe_ddc(&intel_dp->aux.ddc))
> >  		return connector_status_connected;
> >  
> > +	if (intel_dp_can_mst(intel_dp))
> > +		return connector_status_connected;
> 
> Shouldn't we instead just outright not poke the ddc when there's an mst
> branch connected?

I suppose. We won't read the EDID anyway. Not really sure why this
display has problems with DDC sometimes, but then again it has a lot of
other problems too, the biggest of which is that it refuses to do the
payload allocation if I reboot the machine with display already on. I
have to turn it off and on again after rebooting to get it back into a
working state.

> The dp mst helpers will read the ddc for the final leaf
> ports, anything intermediate is kinda bonghits anyway. So
> 
>   	if (!intel_dp_can_mst() && drm_probe_ddc(&intel_dp->aux.ddc))
>   		return connector_status_connected;
> 
> I think with that it makes a lot more sense and is
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> And again, this so should be all shared in dp helpers somehow.

Yeah, we should try to unify all of the probe and long/short pulse
handling across drivers.

> -Daniel
> 
> > +
> >  	/* Well we tried, say unknown for unreliable port types */
> >  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
> >  		type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
> > @@ -4213,7 +4228,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
> >  	struct drm_device *dev = connector->dev;
> >  	enum drm_connector_status status;
> >  	enum intel_display_power_domain power_domain;
> > -	bool ret;
> >  	u8 sink_irq_vector;
> >  
> >  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> > @@ -4249,8 +4263,9 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
> >  
> >  	intel_dp_probe_oui(intel_dp);
> >  
> > -	ret = intel_dp_probe_mst(intel_dp);
> > -	if (ret) {
> > +	intel_dp_configure_mst(intel_dp);
> > +
> > +	if (intel_dp->is_mst) {
> >  		/*
> >  		 * If we are in MST mode then this connector
> >  		 * won't appear connected or have anything
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches
  2016-07-29  9:35   ` Daniel Vetter
@ 2016-07-29 11:43     ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-07-29 11:43 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 11:35:27AM +0200, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 05:50:46PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Let's make rate_to_index() return the highest rate available that's
> > less than or equal to the rate requested by the caller. The function
> > can then be used to filter out rates higher than a certain maximum
> > rate.
> > 
> > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > Cc: Jim Bride <jim.bride@linux.intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Not sure what this will be used for, couldn't figure it out looking at
> later patches?

Ah, forgot to mention that part. It seemed like there was a hunk in the
upfront link training patch that could use this, rather than hand
rolling yet another way of looking through the rate array.

> -Daneil
> 
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 40cae6202160..08d95352ffd6 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1431,10 +1431,13 @@ static int rate_to_index(int find, const int *rates)
> >  	int i = 0;
> >  
> >  	for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
> > -		if (find == rates[i])
> > +		if (find < rates[i])
> >  			break;
> >  
> > -	return i;
> > +	if (WARN_ON(i == 0))
> > +		return 0;
> > +
> > +	return i - 1;
> >  }
> >  
> >  int
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v2 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
  2016-07-28 14:50 ` [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails ville.syrjala
  2016-07-29  9:29   ` Daniel Vetter
@ 2016-07-29 13:51   ` ville.syrjala
  1 sibling, 0 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-29 13:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With HSW + Dell UP2414Q (at least) drm_probe_ddc() occasionally fails,
and then we'll assume that the entire display has been disconnected.
We don't need the EDID from the main link, so we can simply check if
the sink is MST capable, and if so treat is as connected.

v2: Skip drm_probe_ddc() entirely for MST (Daniel)

Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 700b717e4d99..b405a2c3ca70 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3545,7 +3545,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 }
 
 static bool
-intel_dp_probe_mst(struct intel_dp *intel_dp)
+intel_dp_can_mst(struct intel_dp *intel_dp)
 {
 	u8 buf[1];
 
@@ -3558,18 +3558,30 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
 		return false;
 
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
-		if (buf[0] & DP_MST_CAP) {
-			DRM_DEBUG_KMS("Sink is MST capable\n");
-			intel_dp->is_mst = true;
-		} else {
-			DRM_DEBUG_KMS("Sink is not MST capable\n");
-			intel_dp->is_mst = false;
-		}
-	}
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1) != 1)
+		return false;
 
-	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
-	return intel_dp->is_mst;
+	return buf[0] & DP_MST_CAP;
+}
+
+static void
+intel_dp_configure_mst(struct intel_dp *intel_dp)
+{
+	if (!i915.enable_dp_mst)
+		return;
+
+	if (!intel_dp->can_mst)
+		return;
+
+	intel_dp->is_mst = intel_dp_can_mst(intel_dp);
+
+	if (intel_dp->is_mst)
+		DRM_DEBUG_KMS("Sink is MST capable\n");
+	else
+		DRM_DEBUG_KMS("Sink is not MST capable\n");
+
+	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+					intel_dp->is_mst);
 }
 
 static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
@@ -3996,6 +4008,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 		connector_status_connected : connector_status_disconnected;
 	}
 
+	if (intel_dp_can_mst(intel_dp))
+		return connector_status_connected;
+
 	/* If no HPD, poke DDC gently */
 	if (drm_probe_ddc(&intel_dp->aux.ddc))
 		return connector_status_connected;
@@ -4220,7 +4235,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	enum intel_display_power_domain power_domain;
-	bool ret;
 	u8 sink_irq_vector;
 
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
@@ -4262,8 +4276,9 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 
 	intel_dp_probe_oui(intel_dp);
 
-	ret = intel_dp_probe_mst(intel_dp);
-	if (ret) {
+	intel_dp_configure_mst(intel_dp);
+
+	if (intel_dp->is_mst) {
 		/*
 		 * If we are in MST mode then this connector
 		 * won't appear connected or have anything
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v3 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
  2016-07-28 14:50 ` [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP ville.syrjala
  2016-07-28 17:30   ` Chris Wilson
@ 2016-07-29 13:52   ` ville.syrjala
  1 sibling, 0 replies; 54+ messages in thread
From: ville.syrjala @ 2016-07-29 13:52 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we re-read a bunch of static eDP panel caps from the DPCD
over and over again. Let's do it only once to save some time and effort.

v2: Make thing less confusing with intel_edp_init_dpcd() (Chris)
    Move no_aux_handshake setup in there as well
v3: Move tps3/rate printout to intel_dp_long_pulse() so that
    we'll still get them on eDP as well

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
---
 drivers/gpu/drm/i915/intel_dp.c | 165 ++++++++++++++++++++++------------------
 1 file changed, 89 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1fe9bb745de5..0d8c3c3fccd7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3395,20 +3395,94 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 }
 
 static bool
-intel_dp_get_dpcd(struct intel_dp *intel_dp)
+intel_dp_read_dpcd(struct intel_dp *intel_dp)
 {
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
 			     sizeof(intel_dp->dpcd)) < 0)
 		return false; /* aux transfer failed */
 
 	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);
 
-	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
-		return false; /* DPCD not present */
+	return intel_dp->dpcd[DP_DPCD_REV] != 0;
+}
+
+static bool
+intel_edp_init_dpcd(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
+
+	/* this function is meant to be called only once */
+	WARN_ON(intel_dp->dpcd[DP_DPCD_REV] != 0);
+
+	if (!intel_dp_read_dpcd(intel_dp))
+		return false;
+
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
+		dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
+			DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
+
+	/* Check if the panel supports PSR */
+	drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
+			 intel_dp->psr_dpcd,
+			 sizeof(intel_dp->psr_dpcd));
+	if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
+		dev_priv->psr.sink_support = true;
+		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
+	}
+
+	if (INTEL_GEN(dev_priv) >= 9 &&
+	    (intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
+		uint8_t frame_sync_cap;
+
+		dev_priv->psr.sink_support = true;
+		drm_dp_dpcd_read(&intel_dp->aux,
+				 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
+				 &frame_sync_cap, 1);
+		dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
+		/* PSR2 needs frame sync as well */
+		dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
+		DRM_DEBUG_KMS("PSR2 %s on sink",
+			      dev_priv->psr.psr2_support ? "supported" : "not supported");
+	}
+
+	/* Read the eDP Display control capabilities registers */
+	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
+	    drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
+			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) ==
+			     sizeof(intel_dp->edp_dpcd)))
+		DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
+			      intel_dp->edp_dpcd);
+
+	/* Intermediate frequency support */
+	if (intel_dp->edp_dpcd[0] >= 0x03) { /* eDp v1.4 or higher */
+		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
+		int i;
+
+		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
+				sink_rates, sizeof(sink_rates));
+
+		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
+			int val = le16_to_cpu(sink_rates[i]);
+
+			if (val == 0)
+				break;
+
+			/* Value read is in kHz while drm clock is saved in deca-kHz */
+			intel_dp->sink_rates[i] = (val * 200) / 10;
+		}
+		intel_dp->num_sink_rates = i;
+	}
+
+	return true;
+}
+
+
+static bool
+intel_dp_get_dpcd(struct intel_dp *intel_dp)
+{
+	if (!intel_dp_read_dpcd(intel_dp))
+		return false;
 
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
@@ -3431,68 +3505,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp) && !intel_dp->sink_count)
 		return false;
 
-	/* Check if the panel supports PSR */
-	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
-	if (is_edp(intel_dp)) {
-		drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
-				 intel_dp->psr_dpcd,
-				 sizeof(intel_dp->psr_dpcd));
-		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
-			dev_priv->psr.sink_support = true;
-			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
-		}
-
-		if (INTEL_INFO(dev)->gen >= 9 &&
-			(intel_dp->psr_dpcd[0] & DP_PSR2_IS_SUPPORTED)) {
-			uint8_t frame_sync_cap;
-
-			dev_priv->psr.sink_support = true;
-			drm_dp_dpcd_read(&intel_dp->aux,
-					 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
-					 &frame_sync_cap, 1);
-			dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
-			/* PSR2 needs frame sync as well */
-			dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
-			DRM_DEBUG_KMS("PSR2 %s on sink",
-				dev_priv->psr.psr2_support ? "supported" : "not supported");
-		}
-
-		/* Read the eDP Display control capabilities registers */
-		memset(intel_dp->edp_dpcd, 0, sizeof(intel_dp->edp_dpcd));
-		if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
-				(drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
-						intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) ==
-								sizeof(intel_dp->edp_dpcd)))
-			DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
-					intel_dp->edp_dpcd);
-	}
-
-	DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
-		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
-		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
-
-	/* Intermediate frequency support */
-	if (is_edp(intel_dp) && (intel_dp->edp_dpcd[0] >= 0x03)) { /* eDp v1.4 or higher */
-		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
-		int i;
-
-		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
-				sink_rates, sizeof(sink_rates));
-
-		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
-			int val = le16_to_cpu(sink_rates[i]);
-
-			if (val == 0)
-				break;
-
-			/* Value read is in kHz while drm clock is saved in deca-kHz */
-			intel_dp->sink_rates[i] = (val * 200) / 10;
-		}
-		intel_dp->num_sink_rates = i;
-	}
-
-	intel_dp_print_rates(intel_dp);
-
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
@@ -4235,6 +4247,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DP;
 
+	DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
+		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
+		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
+
+	intel_dp_print_rates(intel_dp);
+
 	intel_dp_probe_oui(intel_dp);
 
 	ret = intel_dp_probe_mst(intel_dp);
@@ -5396,14 +5414,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	pps_unlock(intel_dp);
 
 	/* Cache DPCD and EDID for edp. */
-	has_dpcd = intel_dp_get_dpcd(intel_dp);
+	has_dpcd = intel_edp_init_dpcd(intel_dp);
 
-	if (has_dpcd) {
-		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
-			dev_priv->no_aux_handshake =
-				intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
-				DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
-	} else {
+	if (!has_dpcd) {
 		/* if this fails, presume the device is a ghost */
 		DRM_INFO("failed to retrieve link info, disabling eDP\n");
 		goto out_vdd_off;
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3)
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (12 preceding siblings ...)
  2016-07-28 15:39 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc Patchwork
@ 2016-07-29 14:27 ` Patchwork
  2016-08-04 12:35   ` Ville Syrjälä
  2016-08-04 13:08 ` [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc Ville Syrjälä
  14 siblings, 1 reply; 54+ messages in thread
From: Patchwork @ 2016-07-29 14:27 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Move DP link retraining to hotplug work etc. (rev3)
URL   : https://patchwork.freedesktop.org/series/10354/
State : failure

== Summary ==

Series 10354v3 drm/i915: Move DP link retraining to hotplug work etc.
http://patchwork.freedesktop.org/api/1.0/series/10354/revisions/3/mbox

Test drv_module_reload_basic:
                skip       -> PASS       (ro-ivb-i7-3770)
                skip       -> PASS       (ro-skl3-i5-6260u)
Test kms_cursor_legacy:
        Subgroup basic-cursor-vs-flip-varying-size:
                pass       -> FAIL       (ro-ilk1-i5-650)
        Subgroup basic-flip-vs-cursor-legacy:
                pass       -> FAIL       (ro-bdw-i5-5250u)
        Subgroup basic-flip-vs-cursor-varying-size:
                fail       -> PASS       (ro-skl3-i5-6260u)
                fail       -> PASS       (ro-snb-i7-2620M)
                pass       -> FAIL       (ro-bdw-i5-5250u)

fi-kbl-qkkr      total:239  pass:180  dwarn:29  dfail:0   fail:3   skip:27 
fi-skl-i5-6260u  total:239  pass:223  dwarn:0   dfail:0   fail:2   skip:14 
fi-snb-i7-2600   total:239  pass:197  dwarn:0   dfail:0   fail:0   skip:42 
ro-bdw-i5-5250u  total:239  pass:217  dwarn:4   dfail:0   fail:2   skip:16 
ro-bdw-i7-5557U  total:239  pass:222  dwarn:0   dfail:0   fail:1   skip:16 
ro-bdw-i7-5600u  total:239  pass:206  dwarn:0   dfail:0   fail:1   skip:32 
ro-bsw-n3050     total:239  pass:193  dwarn:0   dfail:0   fail:4   skip:42 
ro-hsw-i3-4010u  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
ro-hsw-i7-4770r  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
ro-ilk-i7-620lm  total:239  pass:171  dwarn:1   dfail:0   fail:2   skip:65 
ro-ilk1-i5-650   total:234  pass:171  dwarn:0   dfail:0   fail:3   skip:60 
ro-ivb-i7-3770   total:239  pass:204  dwarn:0   dfail:0   fail:0   skip:35 
ro-ivb2-i7-3770  total:239  pass:208  dwarn:0   dfail:0   fail:0   skip:31 
ro-skl3-i5-6260u total:239  pass:222  dwarn:0   dfail:0   fail:3   skip:14 
ro-snb-i7-2620M  total:239  pass:197  dwarn:0   dfail:0   fail:1   skip:41 
fi-hsw-i7-4770k failed to connect after reboot
fi-skl-i7-6700k failed to connect after reboot

Results at /archive/results/CI_IGT_test/RO_Patchwork_1643/

cb7629d drm-intel-nightly: 2016y-07m-28d-11h-02m-33s UTC integration manifest
8bbaa8b drm/i915: Add encoder .sync_state() hook
1b7b5401 drm/i915: Don't try to ack sink irqs when there are none
d2da7a5 drm/i915: Allow rate_to_index() to return non-exact matches
489af04 drm/i915: Remove useless rate_to_index() usage
8a3de80 drm/i915: Skip dpcd/edid read unless there was a long hpd
27363d5 drm/i915: Move DP link retraining into intel_dp_detect()
1c8a5ee drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
4cb73b1 drm/i915: Track active streams also for DP SST
0d76448 drm/i915: Reject mixing MST and SST/HDMI on the same digital port
3c6377c drm/i915: Avoid mixing up SST and MST in DDI setup
1f1993f drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
4512a10 drm/i915: Ignore initial lid state for eDP

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 05/12] drm/i915: Track active streams also for DP SST
  2016-07-29 11:36     ` Ville Syrjälä
@ 2016-07-29 18:36       ` Jim Bride
  2016-08-02 14:28         ` Daniel Vetter
  0 siblings, 1 reply; 54+ messages in thread
From: Jim Bride @ 2016-07-29 18:36 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 02:36:23PM +0300, Ville Syrjälä wrote:
> On Fri, Jul 29, 2016 at 11:22:32AM +0200, Daniel Vetter wrote:
> > On Thu, Jul 28, 2016 at 05:50:41PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > s/active_mst_links/active_streams/ and use it also for SST. We can then
> > > use this information in the hpd handling to see if the link is active
> > > or not, and thus whether we may need to retrain.
> > > 
> > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Hm, more state not in the state structures, and not cross-checked :( Ben
> > Skeggs just pinged me on this, and one of the ideas he's now looking into
> > is a separate state array for mst ports to fully keep track of this. Kinda
> > like we keep track of the shared dplls.
> 
> Yeah it's a bit a mess. The other option I've outlined before might be a
> fake crtc to drive the primary, and then use atomic enable/disable it at
> the right time depending the state the of the actual MST streams.
> 
> Speaking of atomic/mst, I'm not sure our link retraining is really good
> enough for MST. IIRC I saw a note in the spec that the payloads and
> whatnot might get deallocated by the sink/hub if the link drops. I think
> I have to re-read the spec a few times to make sure, but if that's the
> case then we'd have to pimp up the link retraining to be MST aware. But,
> I had an alternative idea recently; What if we just force a modeset on
> all the pipes on that port? IIRC the spec even says that for link
> retraining we should really be doing more or less the full modeset
> sequence. It should also get rid of the FIFO underruns we now get every
> time we retrain the link. Any thoughts?

If we ensure that we train the link at the widest and fastest configuration
possible in the first place (which is how I interpret what the DP spec says
to do for link training) then we shouldn't be in a situation where we need
to retrain the main link unless the link is lost, in which case all of the
pipes & payloads associated with the link will need to be re-configured
anyhow (since there's no guarantee that the link bandwidth will be the same
once the re-training was done.)  This seems like a simpler solution, IMHO.

Jim


> > 
> > Again just ideas, code looks correct.
> > 
> > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > > ---
> > >  drivers/gpu/drm/i915/intel_ddi.c    | 10 ++++++++++
> > >  drivers/gpu/drm/i915/intel_dp.c     |  8 +++++++-
> > >  drivers/gpu/drm/i915/intel_dp_mst.c | 16 ++++++++--------
> > >  drivers/gpu/drm/i915/intel_drv.h    |  2 +-
> > >  4 files changed, 26 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > > index 3b3a0a808477..bc188ee6e37f 100644
> > > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > > @@ -1616,6 +1616,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
> > >  
> > >  		intel_ddi_init_dp_buf_reg(intel_encoder);
> > >  
> > > +		WARN_ON(intel_dp->active_streams != 0);
> > > +		intel_dp->active_streams++;
> > > +
> > >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > >  		intel_dp_start_link_train(intel_dp);
> > >  		if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
> > > @@ -1733,6 +1736,13 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
> > >  		intel_psr_disable(intel_dp);
> > >  		intel_edp_backlight_off(intel_dp);
> > >  	}
> > > +
> > > +	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> > > +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > > +
> > > +		intel_dp->active_streams--;
> > > +		WARN_ON(intel_dp->active_streams != 0);
> > > +	}
> > >  }
> > >  
> > >  bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 0096c651c21f..3a9c5d3b5c66 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -2685,6 +2685,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> > >  				    lane_mask);
> > >  	}
> > >  
> > > +	WARN_ON(intel_dp->active_streams != 0);
> > > +	intel_dp->active_streams++;
> > > +
> > >  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > >  	intel_dp_start_link_train(intel_dp);
> > >  	intel_dp_stop_link_train(intel_dp);
> > > @@ -3344,6 +3347,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
> > >  
> > >  	DRM_DEBUG_KMS("\n");
> > >  
> > > +	intel_dp->active_streams--;
> > > +	WARN_ON(intel_dp->active_streams != 0);
> > > +
> > >  	if ((IS_GEN7(dev) && port == PORT_A) ||
> > >  	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
> > >  		DP &= ~DP_LINK_TRAIN_MASK_CPT;
> > > @@ -3826,7 +3832,7 @@ go_again:
> > >  		if (bret == true) {
> > >  
> > >  			/* check link status - esi[10] = 0x200c */
> > > -			if (intel_dp->active_mst_links &&
> > > +			if (intel_dp->active_streams &&
> > >  			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > >  				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > >  				intel_dp_start_link_train(intel_dp);
> > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > index 68a005d729e9..857cfa6928b3 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > @@ -99,7 +99,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
> > >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> > >  	int ret;
> > >  
> > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > >  
> > >  	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
> > >  
> > > @@ -115,7 +115,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> > >  	struct intel_digital_port *intel_dig_port = intel_mst->primary;
> > >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> > >  
> > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > >  
> > >  	/* this can fail */
> > >  	drm_dp_check_act_status(&intel_dp->mst_mgr);
> > > @@ -124,10 +124,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> > >  
> > >  	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
> > >  
> > > -	intel_dp->active_mst_links--;
> > > +	intel_dp->active_streams--;
> > >  
> > >  	intel_mst->connector = NULL;
> > > -	if (intel_dp->active_mst_links == 0) {
> > > +	if (intel_dp->active_streams == 0) {
> > >  		intel_dig_port->base.post_disable(&intel_dig_port->base);
> > >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
> > >  	}
> > > @@ -165,11 +165,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> > >  	 */
> > >  	found->encoder = encoder;
> > >  
> > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > >  
> > >  	intel_mst->connector = found;
> > >  
> > > -	if (intel_dp->active_mst_links == 0) {
> > > +	if (intel_dp->active_streams == 0) {
> > >  		intel_prepare_ddi_buffer(&intel_dig_port->base);
> > >  
> > >  		intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
> > > @@ -193,7 +193,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> > >  	}
> > >  
> > >  
> > > -	intel_dp->active_mst_links++;
> > > +	intel_dp->active_streams++;
> > >  	temp = I915_READ(DP_TP_STATUS(port));
> > >  	I915_WRITE(DP_TP_STATUS(port), temp);
> > >  
> > > @@ -210,7 +210,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
> > >  	enum port port = intel_dig_port->port;
> > >  	int ret;
> > >  
> > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > >  
> > >  	if (intel_wait_for_register(dev_priv,
> > >  				    DP_TP_STATUS(port),
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index 70d7f33d6747..7fef18288aa2 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -894,7 +894,7 @@ struct intel_dp {
> > >  
> > >  	bool can_mst; /* this port supports mst */
> > >  	bool is_mst;
> > > -	int active_mst_links;
> > > +	int active_streams; /* number of active streams (for SST and MST both) */
> > >  	/* connector directly attached - won't be use for modeset in mst world */
> > >  	struct intel_connector *attached_connector;
> > >  
> > > -- 
> > > 2.7.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-28 14:50 ` [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect() ville.syrjala
  2016-07-28 19:48   ` Manasi Navare
@ 2016-07-29 20:37   ` Jim Bride
  1 sibling, 0 replies; 54+ messages in thread
From: Jim Bride @ 2016-07-29 20:37 UTC (permalink / raw)
  To: ville.syrjala; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> DP link retraining needs to grab some modeset locks to not race with
> modesets, so we can't really do it safely from the hpd_pulse, lest we
> risk deadlocking due to MST sideband stuff.
> 
> Move the link retraining to happen from the hotplug work instead.
> Doing at the end of intel_dp_detect() seems like a good place in case
> the sink already got disconnected, in which case retraining is
> pointless.
> 
> To determine if we need to schedule the hotplug work, we'll just check
> the sink lane status without locks from hpd_pulse. A little racy
> still eg. due to useing intel_dp->lane_count, but no less racy than
> what we already had. We'll repeat the check in from intel_dp_detect()
> with proper locking, where we'll also check if the link as actually
> active or not.
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
>  1 file changed, 66 insertions(+), 88 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4a4184c21989..675b83f57a07 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
>  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
>  go_again:
>  		if (bret == true) {
> -
> -			/* check link status - esi[10] = 0x200c */
> -			if (intel_dp->active_streams &&
> -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> -				intel_dp_start_link_train(intel_dp);
> -				intel_dp_stop_link_train(intel_dp);
> -			}
> -
>  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
>  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
>  
> @@ -3886,34 +3877,42 @@ go_again:
>  	return -EINVAL;
>  }
>  
> -static void
> -intel_dp_check_link_status(struct intel_dp *intel_dp)
> +static bool
> +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
>  {
> -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	u8 link_status[DP_LINK_STATUS_SIZE];
>  
> -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> +	if (intel_dp->active_streams == 0)
> +		return false;
> +
> +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> +		return true;
>  
>  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
>  		DRM_ERROR("Failed to get link status\n");
> -		return;
> +		return false;
>  	}
>  
> -	if (!intel_encoder->base.crtc)
> -		return;
> +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> +}
>  
> -	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
> -		return;
> +static void
> +intel_dp_link_retrain(struct intel_dp *intel_dp)
> +{
> +	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
> +	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +
> +	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
>  
> -	/* if link training is requested we should perform it always */
> -	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
> -	    (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
> +	if (intel_dp_link_needs_retrain(intel_dp)) {
>  		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
> -			      intel_encoder->base.name);
> +			      encoder->base.name);
> +
>  		intel_dp_start_link_train(intel_dp);
>  		intel_dp_stop_link_train(intel_dp);
>  	}
> +
> +	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>  }
>  
>  /*
> @@ -3932,7 +3931,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
>  static bool
>  intel_dp_short_pulse(struct intel_dp *intel_dp)
>  {
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	u8 sink_irq_vector;
>  	u8 old_sink_count = intel_dp->sink_count;
>  	bool ret;
> @@ -3972,10 +3970,6 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
>  			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
>  	}
>  
> -	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -	intel_dp_check_link_status(intel_dp);
> -	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -
>  	return true;
>  }
>  
> @@ -3986,6 +3980,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
>  	uint8_t *dpcd = intel_dp->dpcd;
>  	uint8_t type;
>  
> +	WARN_ON(is_edp(intel_dp));
> +
>  	if (!intel_dp_get_dpcd(intel_dp))
>  		return connector_status_disconnected;
>  
> @@ -4218,7 +4214,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
>  	intel_dp->has_audio = false;
>  }
>  
> -static void
> +static enum drm_connector_status
>  intel_dp_long_pulse(struct intel_connector *intel_connector)
>  {
>  	struct drm_connector *connector = &intel_connector->base;
> @@ -4273,18 +4269,12 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  		 */
>  		status = connector_status_disconnected;
>  		goto out;
> -	} else if (connector->status == connector_status_connected) {
> -		/*
> -		 * If display was connected already and is still connected
> -		 * check links status, there has been known issues of
> -		 * link loss triggerring long pulse!!!!
> -		 */
> -		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -		intel_dp_check_link_status(intel_dp);
> -		drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -		goto out;
>  	}
>  
> +	/* connected->connected, nothing to do */
> +	if (connector->status == connector_status_connected)
> +		goto out;
> +
>  	/*
>  	 * Clearing NACK and defer counts to get their exact values
>  	 * while reading EDID which are required by Compliance tests
> @@ -4296,7 +4286,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	intel_dp_set_edid(intel_dp);
>  
>  	status = connector_status_connected;
> -	intel_dp->detect_done = true;
>  
>  	/* Try to read the source of the interrupt */
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
> @@ -4313,43 +4302,30 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  	}
>  
>  out:
> -	if ((status != connector_status_connected) &&
> -	    (intel_dp->is_mst == false))
> +	if (status != connector_status_connected)
>  		intel_dp_unset_edid(intel_dp);
>  
>  	intel_display_power_put(to_i915(dev), power_domain);
> -	return;
> +
> +	return status;
>  }
>  
>  static enum drm_connector_status
>  intel_dp_detect(struct drm_connector *connector, bool force)
>  {
>  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
> +	enum drm_connector_status status;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
>  
> -	if (intel_dp->is_mst) {
> -		/* MST devices are disconnected from a monitor POV */
> -		intel_dp_unset_edid(intel_dp);
> -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> -			intel_encoder->type = INTEL_OUTPUT_DP;
> -		return connector_status_disconnected;
> -	}
> -
> -	/* If full detect is not performed yet, do a full detect */
> -	if (!intel_dp->detect_done)
> -		intel_dp_long_pulse(intel_dp->attached_connector);
> +	status = intel_dp_long_pulse(intel_connector);
>  
> -	intel_dp->detect_done = false;
> +	if (status == connector_status_connected || intel_dp->is_mst)
> +		intel_dp_link_retrain(intel_dp);
>  
> -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> -		return connector_status_connected;
> -	else
> -		return connector_status_disconnected;
> +	return status;
>  }
>  
>  static void
> @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
>  		      port_name(intel_dig_port->port),
>  		      long_hpd ? "long" : "short");
>  
> +	if (long_hpd)
> +		return IRQ_NONE;
> +
>  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
>  	intel_display_power_get(dev_priv, power_domain);
>  
> -	if (long_hpd) {
> -		intel_dp_long_pulse(intel_dp->attached_connector);
> -		if (intel_dp->is_mst)
> -			ret = IRQ_HANDLED;
> -		goto put_power;
> -
> -	} else {
> -		if (intel_dp->is_mst) {
> -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> -				/*
> -				 * If we were in MST mode, and device is not
> -				 * there, get out of MST mode
> -				 */
> -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> -				intel_dp->is_mst = false;
> -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> -								intel_dp->is_mst);
> -				goto put_power;
> -			}
> -		}
> -
> -		if (!intel_dp->is_mst) {
> -			if (!intel_dp_short_pulse(intel_dp)) {
> -				intel_dp_long_pulse(intel_dp->attached_connector);
> -				goto put_power;
> -			}
> +	if (intel_dp->is_mst) {
> +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> +			/*
> +			 * If we were in MST mode, and device is not
> +			 * there, get out of MST mode
> +			 */
> +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> +			intel_dp->is_mst = false;
> +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> +							intel_dp->is_mst);
> +			goto put_power;
>  		}
> +	} else {
> +		if (!intel_dp_short_pulse(intel_dp))
> +			goto put_power;
>  	}

Don't we need a way for short pulses to be processed on MST connections as
well?  In particular, I'm thinking of DP compliance testing on MST
topologies.

Jim

> +	/*
> +	 * Link retraining happens from the hotplug work,
> +	 * check if we might need to schdule it.
> +	 *
> +	 * There has been known issues of link loss
> +	 * triggerring long pulse, so let's check both
> +	 * for short and long pulse.
> +	 */
> +	if (intel_dp_link_needs_retrain(intel_dp))
> +		goto put_power;
> +
>  	ret = IRQ_HANDLED;
>  
>  put_power:
> -- 
> 2.7.4
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-29  9:52         ` Ville Syrjälä
@ 2016-07-29 21:42           ` Manasi Navare
  0 siblings, 0 replies; 54+ messages in thread
From: Manasi Navare @ 2016-07-29 21:42 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 12:52:55PM +0300, Ville Syrjälä wrote:
> On Thu, Jul 28, 2016 at 05:36:14PM -0700, Manasi Navare wrote:
> > On Thu, Jul 28, 2016 at 11:15:22PM +0300, Ville Syrjälä wrote:
> > > On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> > > > On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > 
> > > > > DP link retraining needs to grab some modeset locks to not race with
> > > > > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > > > > risk deadlocking due to MST sideband stuff.
> > > > > 
> > > > > Move the link retraining to happen from the hotplug work instead.
> > > > > Doing at the end of intel_dp_detect() seems like a good place in case
> > > > > the sink already got disconnected, in which case retraining is
> > > > > pointless.
> > > > > 
> > > > > To determine if we need to schedule the hotplug work, we'll just check
> > > > > the sink lane status without locks from hpd_pulse. A little racy
> > > > > still eg. due to useing intel_dp->lane_count, but no less racy than
> > > > > what we already had. We'll repeat the check in from intel_dp_detect()
> > > > > with proper locking, where we'll also check if the link as actually
> > > > > active or not.
> > > > > 
> > > > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> > > > >  1 file changed, 66 insertions(+), 88 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > > index 4a4184c21989..675b83f57a07 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> > > > >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> > > > >  go_again:
> > > > >  		if (bret == true) {
> > > > > -
> > > > > -			/* check link status - esi[10] = 0x200c */
> > > > > -			if (intel_dp->active_streams &&
> > > > > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > > > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > > > -				intel_dp_start_link_train(intel_dp);
> > > > > -				intel_dp_stop_link_train(intel_dp);
> > > > > -			}
> > > > > -
> > > > >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> > > > >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> > > > >  
> > > > > @@ -3886,34 +3877,42 @@ go_again:
> > > > >  	return -EINVAL;
> > > > >  }
> > > > >  
> > > > > -static void
> > > > > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > > > > +static bool
> > > > > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> > > > >  {
> > > > > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > > > > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > > > >  	u8 link_status[DP_LINK_STATUS_SIZE];
> > > > >  
> > > > > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > > > > +	if (intel_dp->active_streams == 0)
> > > > > +		return false;
> > > > > +
> > > > > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > > > > +		return true;
> > > > >  
> > > > >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> > > > >  		DRM_ERROR("Failed to get link status\n");
> > > > > -		return;
> > > > > +		return false;
> > > > >  	}
> > > > >  
> > > > > -	if (!intel_encoder->base.crtc)
> > > > > -		return;
> > > > > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> > > > 
> > > > According to the DP spec, we should also check for the clock recovery bit in DPCD
> > > > We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)
> > > 
> > > I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
> > > CR_DONE, EQ_DONE, and SYMBOL_LOCKED.
> > 
> > It only checks for EQ_DONE and INTERLANE_ALIGN_DONE.
> 
> It checks DP_CHANNEL_EQ_BITS which is
> 
> #define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE |           \
>                             DP_LANE_CHANNEL_EQ_DONE |   \
>                             DP_LANE_SYMBOL_LOCKED)
>

Ok looks good then.

Manasi 
> > drm_dp_clock_recovery_ok() checks for DP_LANE_CR_DONE bit.
> > > 
> 
> -- 
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-29  0:36       ` Manasi Navare
  2016-07-29  9:52         ` Ville Syrjälä
@ 2016-07-29 21:45         ` Manasi Navare
  2016-08-01 10:03           ` Ville Syrjälä
  1 sibling, 1 reply; 54+ messages in thread
From: Manasi Navare @ 2016-07-29 21:45 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Thu, Jul 28, 2016 at 05:36:14PM -0700, Manasi Navare wrote:
> On Thu, Jul 28, 2016 at 11:15:22PM +0300, Ville Syrjälä wrote:
> > On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> > > On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > DP link retraining needs to grab some modeset locks to not race with
> > > > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > > > risk deadlocking due to MST sideband stuff.
> > > > 
> > > > Move the link retraining to happen from the hotplug work instead.
> > > > Doing at the end of intel_dp_detect() seems like a good place in case
> > > > the sink already got disconnected, in which case retraining is
> > > > pointless.
> > > > 
> > > > To determine if we need to schedule the hotplug work, we'll just check
> > > > the sink lane status without locks from hpd_pulse. A little racy
> > > > still eg. due to useing intel_dp->lane_count, but no less racy than
> > > > what we already had. We'll repeat the check in from intel_dp_detect()
> > > > with proper locking, where we'll also check if the link as actually
> > > > active or not.
> > > > 
> > > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> > > >  1 file changed, 66 insertions(+), 88 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > index 4a4184c21989..675b83f57a07 100644
> > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> > > >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> > > >  go_again:
> > > >  		if (bret == true) {
> > > > -
> > > > -			/* check link status - esi[10] = 0x200c */
> > > > -			if (intel_dp->active_streams &&
> > > > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > > -				intel_dp_start_link_train(intel_dp);
> > > > -				intel_dp_stop_link_train(intel_dp);
> > > > -			}
> > > > -
> > > >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> > > >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> > > >  
> > > > @@ -3886,34 +3877,42 @@ go_again:
> > > >  	return -EINVAL;
> > > >  }
> > > >  
> > > > -static void
> > > > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > > > +static bool
> > > > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> > > >  {
> > > > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > > > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > > >  	u8 link_status[DP_LINK_STATUS_SIZE];
> > > >  
> > > > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > > > +	if (intel_dp->active_streams == 0)
> > > > +		return false;
> > > > +
> > > > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > > > +		return true;
> > > >  
> > > >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> > > >  		DRM_ERROR("Failed to get link status\n");
> > > > -		return;
> > > > +		return false;
> > > >  	}
> > > >  
> > > > -	if (!intel_encoder->base.crtc)
> > > > -		return;
> > > > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> > > 
> > > According to the DP spec, we should also check for the clock recovery bit in DPCD
> > > We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)
> > 
> > I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
> > CR_DONE, EQ_DONE, and SYMBOL_LOCKED.
> 
> It only checks for EQ_DONE and INTERLANE_ALIGN_DONE.
> drm_dp_clock_recovery_ok() checks for DP_LANE_CR_DONE bit.
> > 
> > Anyways, while I was looking at the short pulse handling a bit more, I came
> > to the conclusion that we should rewrite it a bit.
> > 
> > The CTS docs seem to say that we're expected to read DPCD 0x200-0x205 on 
> > short pulse, and use that information to determine what we should do.
> > Currently we don't do that.
> > 
> > So I was thunking that we'd adjust the link_status stuff to read 0x200-0x207
> > instead of 0x202-0x207, like so:
> > -#define DP_LINK_STATUS_SIZE       6
> > +#define DP_LINK_STATUS_SIZE       8
> > 
> >  static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
> >  {
> > -       return link_status[r - DP_LANE0_1_STATUS];
> > +       return link_status[r - DP_SINK_COUNT];
> >  }
> > 
> > And then we'd use something like this as our short pulse handler:
> > 
> > static bool
> > intel_dp_short_pulse(struct intel_dp *intel_dp)
> > {
> >         u8 link_status[DP_LINK_STATUS_SIZE], tmp;
> > 
> >         /*                                                                                                             
> >          * Clearing compliance test variables to allow capturing                                                       
> >          * of values for next automated test request.                                                                  
> >          */
> >         intel_dp->compliance_test_active = 0;
> >         intel_dp->compliance_test_type = 0;
> >         intel_dp->compliance_test_data = 0;
> > 
> >         if (!intel_dp_get_link_status(intel_dp, link_status))
> >                 return false;
> > 
> >         tmp = drm_dp_link_status(link_status, DP_DEVICE_SERVICE_IRQ_VECTOR);
> >         if (tmp)
> >                 drm_dp_dpcd_writeb(&intel_dp->aux,
> >                                    DP_DEVICE_SERVICE_IRQ_VECTOR,
> >                                    tmp);
> > 
> >         if (tmp & DP_AUTOMATED_TEST_REQUEST)
> >                 DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
> >         if (tmp & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
> >                 DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
> > 
> >         tmp = drm_dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
> >         if (tmp & DP_DOWNSTREAM_PORT_STATUS_CHANGED)
> >                 return false;
> > 
> >         tmp = drm_dp_link_status(link_status, DP_SINK_COUNT);
> >         if (DP_GET_SINK_COUNT(tmp) != intel_dp->sink_count)
> >                 return false;
> > 
> >         if (intel_dp->active_streams != 0 &&
> >             !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))
> >                 return false;
> > 
> >         return true;
> > }
> > 
> > and obviously fill in whatever else sink irq handling we need.
> > 
> > Thoughts? Does that look sane?
> 
> Yes all the Link maintenance tests in CTS spec expect DPCD registers
> 0200h-0205h to be read on loss of symbol lock or loss of clock recovery.
> So I think it makes sense to read 0200-0205h.
> 
> > 
> > <snip>
> > > >  
> > > >  static enum drm_connector_status
> > > >  intel_dp_detect(struct drm_connector *connector, bool force)
> > > >  {
> > > >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> > > > -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> > > > -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> > > >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> > > > +	enum drm_connector_status status;
> > > >  
> > > >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> > > >  		      connector->base.id, connector->name);
> > > >  
> > > > -	if (intel_dp->is_mst) {
> > > > -		/* MST devices are disconnected from a monitor POV */
> > > > -		intel_dp_unset_edid(intel_dp);
> > > > -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> > > > -			intel_encoder->type = INTEL_OUTPUT_DP;
> > > > -		return connector_status_disconnected;
> > > > -	}
> > > > -
> > > > -	/* If full detect is not performed yet, do a full detect */
> > > > -	if (!intel_dp->detect_done)
> > > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > > +	status = intel_dp_long_pulse(intel_connector);
> > > >  
> > > > -	intel_dp->detect_done = false;
> > > > +	if (status == connector_status_connected || intel_dp->is_mst)
> > > 
> > > Whya re we not checking for (!intel_encoder->crtc.base) before retraining?
> > > I had seen issues with connected boot case when connector status is connected and if it
> > > tries to retrain it fails with retries because there is no active pipe. In that
> > > case it should not attempt to retrain.
> > 
> > I changed it to use intel_dp->active_streams instead. That'll work for MST
> > as well as SST. Checking for the crtc would only cover SST.
> > 
> > > 
> > > 
> > > > +		intel_dp_link_retrain(intel_dp);
> > > >  
> > > > -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> > > > -		return connector_status_connected;
> > > > -	else
> > > > -		return connector_status_disconnected;
> > > > +	return status;
> > > >  }
> > > >  
> > > >  static void
> > > > @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
> > > >  		      port_name(intel_dig_port->port),
> > > >  		      long_hpd ? "long" : "short");
> > > >  
> > > > +	if (long_hpd)
> > > > +		return IRQ_NONE;
> > > > +
> > > >  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> > > >  	intel_display_power_get(dev_priv, power_domain);
> > > >  
> > > > -	if (long_hpd) {
> > > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > > -		if (intel_dp->is_mst)
> > > > -			ret = IRQ_HANDLED;
> > > > -		goto put_power;
> > > > -
> > > > -	} else {
> > > > -		if (intel_dp->is_mst) {
> > > > -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > > -				/*
> > > > -				 * If we were in MST mode, and device is not
> > > > -				 * there, get out of MST mode
> > > > -				 */
> > > > -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > > -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > > -				intel_dp->is_mst = false;
> > > > -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > > -								intel_dp->is_mst);
> > > > -				goto put_power;
> > > > -			}
> > > > -		}
> > > > -
> > > > -		if (!intel_dp->is_mst) {
> > > > -			if (!intel_dp_short_pulse(intel_dp)) {
> > > > -				intel_dp_long_pulse(intel_dp->attached_connector);
> > > > -				goto put_power;
> > > > -			}
> > > > +	if (intel_dp->is_mst) {
> > > > +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > > +			/*
> > > > +			 * If we were in MST mode, and device is not
> > > > +			 * there, get out of MST mode
> > > > +			 */
> > > > +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > > +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > > +			intel_dp->is_mst = false;
> > > > +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > > +							intel_dp->is_mst);
> > > > +			goto put_power;
> > > >  		}
> > > > +	} else {
> > > > +		if (!intel_dp_short_pulse(intel_dp))
> > > > +			goto put_power;
> > > >  	}
> > > >  
> > > > +	/*
> > > > +	 * Link retraining happens from the hotplug work,
> > > > +	 * check if we might need to schdule it.
> > > > +	 *
> > > > +	 * There has been known issues of link loss
> > > > +	 * triggerring long pulse, so let's check both
> > > > +	 * for short and long pulse.
> > > > +	 */
> > > > +	if (intel_dp_link_needs_retrain(intel_dp))
> > > > +		goto put_power;

What happens in case of link loss triggering long pulse, does this link retraining
also get handled in intel_dp_detect()?

Manasi
> > > > +
> > > >  	ret = IRQ_HANDLED;
> > > >  
> > > >  put_power:
> > > > -- 
> > > > 2.7.4
> > > > 
> > 
> > -- 
> > Ville Syrjälä
> > Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup
  2016-07-28 14:50 ` [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup ville.syrjala
  2016-07-29  9:16   ` Daniel Vetter
@ 2016-08-01  9:24   ` Maarten Lankhorst
  1 sibling, 0 replies; 54+ messages in thread
From: Maarten Lankhorst @ 2016-08-01  9:24 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 28-07-16 om 16:50 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The MST vs. SST selection should depend purely on the choice of the
> connector/encoder. So don't try to determine the correct DDI mode
> based on the intel_dp->is_mst, which simply tells us whether the sink
> is in MST mode or not. Instead derive the information from the encoder
> type. Since the link training code deals in non-fake encoders, we'll
> also need to keep a second copy of that information around, which we'll
> now designate as 'link_mst'.
>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  2016-07-28 14:50 ` [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port ville.syrjala
  2016-07-29  9:19   ` Daniel Vetter
@ 2016-08-01  9:28   ` Maarten Lankhorst
  1 sibling, 0 replies; 54+ messages in thread
From: Maarten Lankhorst @ 2016-08-01  9:28 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

Op 28-07-16 om 16:50 schreef ville.syrjala@linux.intel.com:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We can't mix MST with SST/HDMI on the same physical port, so we'll need
> to reject such configurations in check_digital_port_conflicts(). Nothing
> else will prevent this as MST has its fake encoders and its own connectors
> so the cloning checks won't catch this.
>
> The same digital port can be used multiple times, but only if all the
> encoders involved are MST encoders, so we only want to check MST vs.
> SST/HDMI, not MST vs. MST. And SST/HDMI vs. SST/HDMI we already check.

I guess this is to prevent DP1 and DP1-2 to be both set simultaneously?
I'm not sure kms_setmode would handle this case correctly, but the idea
is correct.

Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect()
  2016-07-29 21:45         ` Manasi Navare
@ 2016-08-01 10:03           ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-08-01 10:03 UTC (permalink / raw)
  To: Manasi Navare; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 02:45:29PM -0700, Manasi Navare wrote:
> On Thu, Jul 28, 2016 at 05:36:14PM -0700, Manasi Navare wrote:
> > On Thu, Jul 28, 2016 at 11:15:22PM +0300, Ville Syrjälä wrote:
> > > On Thu, Jul 28, 2016 at 12:48:53PM -0700, Manasi Navare wrote:
> > > > On Thu, Jul 28, 2016 at 05:50:43PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > 
> > > > > DP link retraining needs to grab some modeset locks to not race with
> > > > > modesets, so we can't really do it safely from the hpd_pulse, lest we
> > > > > risk deadlocking due to MST sideband stuff.
> > > > > 
> > > > > Move the link retraining to happen from the hotplug work instead.
> > > > > Doing at the end of intel_dp_detect() seems like a good place in case
> > > > > the sink already got disconnected, in which case retraining is
> > > > > pointless.
> > > > > 
> > > > > To determine if we need to schedule the hotplug work, we'll just check
> > > > > the sink lane status without locks from hpd_pulse. A little racy
> > > > > still eg. due to useing intel_dp->lane_count, but no less racy than
> > > > > what we already had. We'll repeat the check in from intel_dp_detect()
> > > > > with proper locking, where we'll also check if the link as actually
> > > > > active or not.
> > > > > 
> > > > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_dp.c | 154 +++++++++++++++++-----------------------
> > > > >  1 file changed, 66 insertions(+), 88 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > > index 4a4184c21989..675b83f57a07 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > > @@ -3842,15 +3842,6 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
> > > > >  		bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
> > > > >  go_again:
> > > > >  		if (bret == true) {
> > > > > -
> > > > > -			/* check link status - esi[10] = 0x200c */
> > > > > -			if (intel_dp->active_streams &&
> > > > > -			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > > > -				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > > > -				intel_dp_start_link_train(intel_dp);
> > > > > -				intel_dp_stop_link_train(intel_dp);
> > > > > -			}
> > > > > -
> > > > >  			DRM_DEBUG_KMS("got esi %3ph\n", esi);
> > > > >  			ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
> > > > >  
> > > > > @@ -3886,34 +3877,42 @@ go_again:
> > > > >  	return -EINVAL;
> > > > >  }
> > > > >  
> > > > > -static void
> > > > > -intel_dp_check_link_status(struct intel_dp *intel_dp)
> > > > > +static bool
> > > > > +intel_dp_link_needs_retrain(struct intel_dp *intel_dp)
> > > > >  {
> > > > > -	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> > > > > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > > > >  	u8 link_status[DP_LINK_STATUS_SIZE];
> > > > >  
> > > > > -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > > > > +	if (intel_dp->active_streams == 0)
> > > > > +		return false;
> > > > > +
> > > > > +	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)
> > > > > +		return true;
> > > > >  
> > > > >  	if (!intel_dp_get_link_status(intel_dp, link_status)) {
> > > > >  		DRM_ERROR("Failed to get link status\n");
> > > > > -		return;
> > > > > +		return false;
> > > > >  	}
> > > > >  
> > > > > -	if (!intel_encoder->base.crtc)
> > > > > -		return;
> > > > > +	return !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count);
> > > > 
> > > > According to the DP spec, we should also check for the clock recovery bit in DPCD
> > > > We should also add a check drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)
> > > 
> > > I think drm_dp_channel_eq_ok() checks all the bits: INTERLANE_ALIGN_DONE,
> > > CR_DONE, EQ_DONE, and SYMBOL_LOCKED.
> > 
> > It only checks for EQ_DONE and INTERLANE_ALIGN_DONE.
> > drm_dp_clock_recovery_ok() checks for DP_LANE_CR_DONE bit.
> > > 
> > > Anyways, while I was looking at the short pulse handling a bit more, I came
> > > to the conclusion that we should rewrite it a bit.
> > > 
> > > The CTS docs seem to say that we're expected to read DPCD 0x200-0x205 on 
> > > short pulse, and use that information to determine what we should do.
> > > Currently we don't do that.
> > > 
> > > So I was thunking that we'd adjust the link_status stuff to read 0x200-0x207
> > > instead of 0x202-0x207, like so:
> > > -#define DP_LINK_STATUS_SIZE       6
> > > +#define DP_LINK_STATUS_SIZE       8
> > > 
> > >  static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
> > >  {
> > > -       return link_status[r - DP_LANE0_1_STATUS];
> > > +       return link_status[r - DP_SINK_COUNT];
> > >  }
> > > 
> > > And then we'd use something like this as our short pulse handler:
> > > 
> > > static bool
> > > intel_dp_short_pulse(struct intel_dp *intel_dp)
> > > {
> > >         u8 link_status[DP_LINK_STATUS_SIZE], tmp;
> > > 
> > >         /*                                                                                                             
> > >          * Clearing compliance test variables to allow capturing                                                       
> > >          * of values for next automated test request.                                                                  
> > >          */
> > >         intel_dp->compliance_test_active = 0;
> > >         intel_dp->compliance_test_type = 0;
> > >         intel_dp->compliance_test_data = 0;
> > > 
> > >         if (!intel_dp_get_link_status(intel_dp, link_status))
> > >                 return false;
> > > 
> > >         tmp = drm_dp_link_status(link_status, DP_DEVICE_SERVICE_IRQ_VECTOR);
> > >         if (tmp)
> > >                 drm_dp_dpcd_writeb(&intel_dp->aux,
> > >                                    DP_DEVICE_SERVICE_IRQ_VECTOR,
> > >                                    tmp);
> > > 
> > >         if (tmp & DP_AUTOMATED_TEST_REQUEST)
> > >                 DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
> > >         if (tmp & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
> > >                 DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
> > > 
> > >         tmp = drm_dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
> > >         if (tmp & DP_DOWNSTREAM_PORT_STATUS_CHANGED)
> > >                 return false;
> > > 
> > >         tmp = drm_dp_link_status(link_status, DP_SINK_COUNT);
> > >         if (DP_GET_SINK_COUNT(tmp) != intel_dp->sink_count)
> > >                 return false;
> > > 
> > >         if (intel_dp->active_streams != 0 &&
> > >             !drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))
> > >                 return false;
> > > 
> > >         return true;
> > > }
> > > 
> > > and obviously fill in whatever else sink irq handling we need.
> > > 
> > > Thoughts? Does that look sane?
> > 
> > Yes all the Link maintenance tests in CTS spec expect DPCD registers
> > 0200h-0205h to be read on loss of symbol lock or loss of clock recovery.
> > So I think it makes sense to read 0200-0205h.
> > 
> > > 
> > > <snip>
> > > > >  
> > > > >  static enum drm_connector_status
> > > > >  intel_dp_detect(struct drm_connector *connector, bool force)
> > > > >  {
> > > > >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> > > > > -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> > > > > -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> > > > >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> > > > > +	enum drm_connector_status status;
> > > > >  
> > > > >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> > > > >  		      connector->base.id, connector->name);
> > > > >  
> > > > > -	if (intel_dp->is_mst) {
> > > > > -		/* MST devices are disconnected from a monitor POV */
> > > > > -		intel_dp_unset_edid(intel_dp);
> > > > > -		if (intel_encoder->type != INTEL_OUTPUT_EDP)
> > > > > -			intel_encoder->type = INTEL_OUTPUT_DP;
> > > > > -		return connector_status_disconnected;
> > > > > -	}
> > > > > -
> > > > > -	/* If full detect is not performed yet, do a full detect */
> > > > > -	if (!intel_dp->detect_done)
> > > > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > > > +	status = intel_dp_long_pulse(intel_connector);
> > > > >  
> > > > > -	intel_dp->detect_done = false;
> > > > > +	if (status == connector_status_connected || intel_dp->is_mst)
> > > > 
> > > > Whya re we not checking for (!intel_encoder->crtc.base) before retraining?
> > > > I had seen issues with connected boot case when connector status is connected and if it
> > > > tries to retrain it fails with retries because there is no active pipe. In that
> > > > case it should not attempt to retrain.
> > > 
> > > I changed it to use intel_dp->active_streams instead. That'll work for MST
> > > as well as SST. Checking for the crtc would only cover SST.
> > > 
> > > > 
> > > > 
> > > > > +		intel_dp_link_retrain(intel_dp);
> > > > >  
> > > > > -	if (is_edp(intel_dp) || intel_connector->detect_edid)
> > > > > -		return connector_status_connected;
> > > > > -	else
> > > > > -		return connector_status_disconnected;
> > > > > +	return status;
> > > > >  }
> > > > >  
> > > > >  static void
> > > > > @@ -4706,39 +4682,41 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
> > > > >  		      port_name(intel_dig_port->port),
> > > > >  		      long_hpd ? "long" : "short");
> > > > >  
> > > > > +	if (long_hpd)
> > > > > +		return IRQ_NONE;
> > > > > +
> > > > >  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> > > > >  	intel_display_power_get(dev_priv, power_domain);
> > > > >  
> > > > > -	if (long_hpd) {
> > > > > -		intel_dp_long_pulse(intel_dp->attached_connector);
> > > > > -		if (intel_dp->is_mst)
> > > > > -			ret = IRQ_HANDLED;
> > > > > -		goto put_power;
> > > > > -
> > > > > -	} else {
> > > > > -		if (intel_dp->is_mst) {
> > > > > -			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > > > -				/*
> > > > > -				 * If we were in MST mode, and device is not
> > > > > -				 * there, get out of MST mode
> > > > > -				 */
> > > > > -				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > > > -					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > > > -				intel_dp->is_mst = false;
> > > > > -				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > > > -								intel_dp->is_mst);
> > > > > -				goto put_power;
> > > > > -			}
> > > > > -		}
> > > > > -
> > > > > -		if (!intel_dp->is_mst) {
> > > > > -			if (!intel_dp_short_pulse(intel_dp)) {
> > > > > -				intel_dp_long_pulse(intel_dp->attached_connector);
> > > > > -				goto put_power;
> > > > > -			}
> > > > > +	if (intel_dp->is_mst) {
> > > > > +		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> > > > > +			/*
> > > > > +			 * If we were in MST mode, and device is not
> > > > > +			 * there, get out of MST mode
> > > > > +			 */
> > > > > +			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
> > > > > +				      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
> > > > > +			intel_dp->is_mst = false;
> > > > > +			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
> > > > > +							intel_dp->is_mst);
> > > > > +			goto put_power;
> > > > >  		}
> > > > > +	} else {
> > > > > +		if (!intel_dp_short_pulse(intel_dp))
> > > > > +			goto put_power;
> > > > >  	}
> > > > >  
> > > > > +	/*
> > > > > +	 * Link retraining happens from the hotplug work,
> > > > > +	 * check if we might need to schdule it.
> > > > > +	 *
> > > > > +	 * There has been known issues of link loss
> > > > > +	 * triggerring long pulse, so let's check both
> > > > > +	 * for short and long pulse.
> > > > > +	 */
> > > > > +	if (intel_dp_link_needs_retrain(intel_dp))
> > > > > +		goto put_power;
> 
> What happens in case of link loss triggering long pulse, does this link retraining
> also get handled in intel_dp_detect()?

Yes, in fact link training is _only_ done from intel_dp_detect(). So if
we detect a link loss from a short hpd, we'll schedule the full
intel_dp_detect() to retrain the link.

> 
> Manasi
> > > > > +
> > > > >  	ret = IRQ_HANDLED;
> > > > >  
> > > > >  put_power:
> > > > > -- 
> > > > > 2.7.4
> > > > > 
> > > 
> > > -- 
> > > Ville Syrjälä
> > > Intel OTC
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup
  2016-07-29  9:55     ` Ville Syrjälä
@ 2016-08-02 14:20       ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-08-02 14:20 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Jul 29, 2016 at 12:55:20PM +0300, Ville Syrjälä wrote:
> On Fri, Jul 29, 2016 at 11:16:19AM +0200, Daniel Vetter wrote:
> > On Thu, Jul 28, 2016 at 05:50:39PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > The MST vs. SST selection should depend purely on the choice of the
> > > connector/encoder. So don't try to determine the correct DDI mode
> > > based on the intel_dp->is_mst, which simply tells us whether the sink
> > > is in MST mode or not. Instead derive the information from the encoder
> > > type. Since the link training code deals in non-fake encoders, we'll
> > > also need to keep a second copy of that information around, which we'll
> > > now designate as 'link_mst'.
> > > 
> > > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Hm, I think it'd be nice if we could shovel all this stuff into the crtc
> > state I think, instead of noodling it out of somewhere else.
> 
> You mean stuffing a pre-computed (partial?) register value in the
> crtc state? That could work too.

Yeah. But reading ahead I'm not sure where exactly we need to store that,
since recovering that with your sync_state rfc might get tricky.
-Daniel

> 
> > But since we
> > always update it in pre_enable hooks it should be all fine even with
> > TEST_ONLY atomic.
> > 
> > I digress, change looks good.
> > 
> > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > > ---
> > >  drivers/gpu/drm/i915/intel_ddi.c | 21 +++------------------
> > >  drivers/gpu/drm/i915/intel_dp.c  |  1 +
> > >  drivers/gpu/drm/i915/intel_drv.h |  1 +
> > >  3 files changed, 5 insertions(+), 18 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > > index dd1d6fe12297..3b3a0a808477 100644
> > > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > > @@ -1111,7 +1111,6 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
> > >  {
> > >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > >  	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
> > > -	struct drm_encoder *encoder = &intel_encoder->base;
> > >  	struct drm_device *dev = crtc->dev;
> > >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > >  	enum pipe pipe = intel_crtc->pipe;
> > > @@ -1177,29 +1176,15 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
> > >  			temp |= TRANS_DDI_MODE_SELECT_HDMI;
> > >  		else
> > >  			temp |= TRANS_DDI_MODE_SELECT_DVI;
> > > -
> > >  	} else if (type == INTEL_OUTPUT_ANALOG) {
> > >  		temp |= TRANS_DDI_MODE_SELECT_FDI;
> > >  		temp |= (intel_crtc->config->fdi_lanes - 1) << 1;
> > > -
> > >  	} else if (type == INTEL_OUTPUT_DP ||
> > >  		   type == INTEL_OUTPUT_EDP) {
> > > -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > > -
> > > -		if (intel_dp->is_mst) {
> > > -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> > > -		} else
> > > -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> > > -
> > > +		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> > >  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
> > >  	} else if (type == INTEL_OUTPUT_DP_MST) {
> > > -		struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
> > > -
> > > -		if (intel_dp->is_mst) {
> > > -			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> > > -		} else
> > > -			temp |= TRANS_DDI_MODE_SELECT_DP_SST;
> > > -
> > > +		temp |= TRANS_DDI_MODE_SELECT_DP_MST;
> > >  		temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
> > >  	} else {
> > >  		WARN(1, "Invalid encoder type %d for pipe %c\n",
> > > @@ -2105,7 +2090,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> > >  
> > >  	val = DP_TP_CTL_ENABLE |
> > >  	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
> > > -	if (intel_dp->is_mst)
> > > +	if (intel_dp->link_mst)
> > >  		val |= DP_TP_CTL_MODE_MST;
> > >  	else {
> > >  		val |= DP_TP_CTL_MODE_SST;
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 8c38e3483989..0096c651c21f 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -1651,6 +1651,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp,
> > >  {
> > >  	intel_dp->link_rate = pipe_config->port_clock;
> > >  	intel_dp->lane_count = pipe_config->lane_count;
> > > +	intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
> > >  }
> > >  
> > >  static void intel_dp_prepare(struct intel_encoder *encoder)
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index e74d851868c5..70d7f33d6747 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -852,6 +852,7 @@ struct intel_dp {
> > >  	int link_rate;
> > >  	uint8_t lane_count;
> > >  	uint8_t sink_count;
> > > +	bool link_mst;
> > >  	bool has_audio;
> > >  	bool detect_done;
> > >  	enum hdmi_force_audio force_audio;
> > > -- 
> > > 2.7.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
> 
> -- 
> Ville Syrjälä
> Intel OTC

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port
  2016-07-29 11:28     ` Ville Syrjälä
@ 2016-08-02 14:22       ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-08-02 14:22 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Jul 29, 2016 at 02:28:26PM +0300, Ville Syrjälä wrote:
> On Fri, Jul 29, 2016 at 11:19:18AM +0200, Daniel Vetter wrote:
> > On Thu, Jul 28, 2016 at 05:50:40PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > We can't mix MST with SST/HDMI on the same physical port, so we'll need
> > > to reject such configurations in check_digital_port_conflicts(). Nothing
> > > else will prevent this as MST has its fake encoders and its own connectors
> > > so the cloning checks won't catch this.
> > > 
> > > The same digital port can be used multiple times, but only if all the
> > > encoders involved are MST encoders, so we only want to check MST vs.
> > > SST/HDMI, not MST vs. MST. And SST/HDMI vs. SST/HDMI we already check.
> > > 
> > > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > I'd be awesome if we could have some testcases for this. We can e.g. try
> > to enable HDMI without it being connected (it'll fall back to dvi mode),
> > so could use that to try enabling both hdmi and dp or dp mst out of sheer
> > nastiness. I don't even think we need to check that it gets rejected
> > correctly, just trying to do such a modeset on a broken kernel should
> > result in plenty of fireworks in dmesg (state checker for sure will be
> > unhapy) to make it obvious it's broken. Aka would absolutely love if this
> > patch gained a Testcase: line. Either way:
> 
> What I've occasionally used for testing is kms_setmode with a patch to
> ignore all errors from setcrtc so that it doesn't abort midway. IIRC
> last time I did that on eg. HSW there were plenty of state checker
> complaints. In its default state kms_setmode has a bit of a problem
> because it doesn't know about conflicting connectors, nor does it know
> if we're supposed to have one encoder per connector or pair of
> connectors (DDI vs. !DDI). And also IIRC encoder/connector stealing
> will wreac some extra havoc here. Not sure if there's a good way to
> try and fix it so that by default kms_setmode would really test
> what's it's pretending to test on all platforms.
> 
> I guess we could at least promote my hack to a proper command line
> option, so that we can try to feed as many combinations to the kernel
> as possible.

We could promote it to a full test using atomic. Do a TEST_ONLY atomic
commit, then a real one and compare whether results agree. And if there's
any noise on dmesg then also fall over (like we do with all tests).

Of course that doens't encode the expectations we have on all platforms,
but I'm not sure there's enough value in maintaining such a detailed
testcase. The above would be generic, could run everywhere, doesn't need
updating and should at least uncover any internal inconsistencies.
-Daniel

> 
> > 
> > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > 
> > > ---
> > >  drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
> > >  1 file changed, 10 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index c4c1c85366de..a6699c76bef3 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -12305,6 +12305,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> > >  	struct drm_device *dev = state->dev;
> > >  	struct drm_connector *connector;
> > >  	unsigned int used_ports = 0;
> > > +	unsigned int used_mst_ports = 0;
> > >  
> > >  	/*
> > >  	 * Walk the connector list instead of the encoder
> > > @@ -12341,11 +12342,20 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
> > >  				return false;
> > >  
> > >  			used_ports |= port_mask;
> > > +			break;
> > > +		case INTEL_OUTPUT_DP_MST:
> > > +			used_mst_ports |=
> > > +				1 << enc_to_mst(&encoder->base)->primary->port;
> > > +			break;
> > >  		default:
> > >  			break;
> > >  		}
> > >  	}
> > >  
> > > +	/* can't mix MST and SST/HDMI on the same port */
> > > +	if (used_ports & used_mst_ports)
> > > +		return false;
> > > +
> > >  	return true;
> > >  }
> > >  
> > > -- 
> > > 2.7.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
> 
> -- 
> Ville Syrjälä
> Intel OTC

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 05/12] drm/i915: Track active streams also for DP SST
  2016-07-29 18:36       ` Jim Bride
@ 2016-08-02 14:28         ` Daniel Vetter
  0 siblings, 0 replies; 54+ messages in thread
From: Daniel Vetter @ 2016-08-02 14:28 UTC (permalink / raw)
  To: Jim Bride; +Cc: Ander Conselvan de Oliveira, intel-gfx

On Fri, Jul 29, 2016 at 11:36:40AM -0700, Jim Bride wrote:
> On Fri, Jul 29, 2016 at 02:36:23PM +0300, Ville Syrjälä wrote:
> > On Fri, Jul 29, 2016 at 11:22:32AM +0200, Daniel Vetter wrote:
> > > On Thu, Jul 28, 2016 at 05:50:41PM +0300, ville.syrjala@linux.intel.com wrote:
> > > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > 
> > > > s/active_mst_links/active_streams/ and use it also for SST. We can then
> > > > use this information in the hpd handling to see if the link is active
> > > > or not, and thus whether we may need to retrain.
> > > > 
> > > > Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> > > > Cc: Jim Bride <jim.bride@linux.intel.com>
> > > > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > > > Cc: Durgadoss R <durgadoss.r@intel.com>
> > > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Hm, more state not in the state structures, and not cross-checked :( Ben
> > > Skeggs just pinged me on this, and one of the ideas he's now looking into
> > > is a separate state array for mst ports to fully keep track of this. Kinda
> > > like we keep track of the shared dplls.
> > 
> > Yeah it's a bit a mess. The other option I've outlined before might be a
> > fake crtc to drive the primary, and then use atomic enable/disable it at
> > the right time depending the state the of the actual MST streams.

Was more thinking of tracking a intel_dp_mst_port_state per mst capable
port. And then treating it similarly to how we treat the shared dpll,
including state readout, tracking, checking and all that. Fake crtc seems
like abusing the wrong concept.

But tbh I'm not entirely sure what really makes the most sense, maybe
better to keep on stitching stuff together to at least fix the bugs for
now.

> > Speaking of atomic/mst, I'm not sure our link retraining is really good
> > enough for MST. IIRC I saw a note in the spec that the payloads and
> > whatnot might get deallocated by the sink/hub if the link drops. I think
> > I have to re-read the spec a few times to make sure, but if that's the
> > case then we'd have to pimp up the link retraining to be MST aware. But,
> > I had an alternative idea recently; What if we just force a modeset on
> > all the pipes on that port? IIRC the spec even says that for link
> > retraining we should really be doing more or less the full modeset
> > sequence. It should also get rid of the FIFO underruns we now get every
> > time we retrain the link. Any thoughts?
> 
> If we ensure that we train the link at the widest and fastest configuration
> possible in the first place (which is how I interpret what the DP spec says
> to do for link training) then we shouldn't be in a situation where we need
> to retrain the main link unless the link is lost, in which case all of the
> pipes & payloads associated with the link will need to be re-configured
> anyhow (since there's no guarantee that the link bandwidth will be the same
> once the re-training was done.)  This seems like a simpler solution, IMHO.

We already link train the widest/faster link for mst. And this is about
retraining when the link is lost.

One question I have on this plan is what happens for a full unplug. Atm I
think we expect userspace to do a full modeset and we won't reconnect the
current state to the replugged hw. This is a bit different from all other
connectors (and dp sst) where an accidental cable trip doesn't result in a
black screen (assuming userspace doesn't fix things up on its own).

But reconnecting our internal dp objects with the replugged physical ones
might be tricky, so not sure this is a feasible plane. Besides this it
makes sense.
-Daniel


> 
> Jim
> 
> 
> > > 
> > > Again just ideas, code looks correct.
> > > 
> > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > 
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_ddi.c    | 10 ++++++++++
> > > >  drivers/gpu/drm/i915/intel_dp.c     |  8 +++++++-
> > > >  drivers/gpu/drm/i915/intel_dp_mst.c | 16 ++++++++--------
> > > >  drivers/gpu/drm/i915/intel_drv.h    |  2 +-
> > > >  4 files changed, 26 insertions(+), 10 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > > > index 3b3a0a808477..bc188ee6e37f 100644
> > > > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > > > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > > > @@ -1616,6 +1616,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
> > > >  
> > > >  		intel_ddi_init_dp_buf_reg(intel_encoder);
> > > >  
> > > > +		WARN_ON(intel_dp->active_streams != 0);
> > > > +		intel_dp->active_streams++;
> > > > +
> > > >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > > >  		intel_dp_start_link_train(intel_dp);
> > > >  		if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
> > > > @@ -1733,6 +1736,13 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
> > > >  		intel_psr_disable(intel_dp);
> > > >  		intel_edp_backlight_off(intel_dp);
> > > >  	}
> > > > +
> > > > +	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> > > > +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> > > > +
> > > > +		intel_dp->active_streams--;
> > > > +		WARN_ON(intel_dp->active_streams != 0);
> > > > +	}
> > > >  }
> > > >  
> > > >  bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
> > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > index 0096c651c21f..3a9c5d3b5c66 100644
> > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > @@ -2685,6 +2685,9 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> > > >  				    lane_mask);
> > > >  	}
> > > >  
> > > > +	WARN_ON(intel_dp->active_streams != 0);
> > > > +	intel_dp->active_streams++;
> > > > +
> > > >  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > > >  	intel_dp_start_link_train(intel_dp);
> > > >  	intel_dp_stop_link_train(intel_dp);
> > > > @@ -3344,6 +3347,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
> > > >  
> > > >  	DRM_DEBUG_KMS("\n");
> > > >  
> > > > +	intel_dp->active_streams--;
> > > > +	WARN_ON(intel_dp->active_streams != 0);
> > > > +
> > > >  	if ((IS_GEN7(dev) && port == PORT_A) ||
> > > >  	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
> > > >  		DP &= ~DP_LINK_TRAIN_MASK_CPT;
> > > > @@ -3826,7 +3832,7 @@ go_again:
> > > >  		if (bret == true) {
> > > >  
> > > >  			/* check link status - esi[10] = 0x200c */
> > > > -			if (intel_dp->active_mst_links &&
> > > > +			if (intel_dp->active_streams &&
> > > >  			    !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
> > > >  				DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
> > > >  				intel_dp_start_link_train(intel_dp);
> > > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > > index 68a005d729e9..857cfa6928b3 100644
> > > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > > @@ -99,7 +99,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
> > > >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> > > >  	int ret;
> > > >  
> > > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > > >  
> > > >  	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
> > > >  
> > > > @@ -115,7 +115,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> > > >  	struct intel_digital_port *intel_dig_port = intel_mst->primary;
> > > >  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> > > >  
> > > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > > >  
> > > >  	/* this can fail */
> > > >  	drm_dp_check_act_status(&intel_dp->mst_mgr);
> > > > @@ -124,10 +124,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> > > >  
> > > >  	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
> > > >  
> > > > -	intel_dp->active_mst_links--;
> > > > +	intel_dp->active_streams--;
> > > >  
> > > >  	intel_mst->connector = NULL;
> > > > -	if (intel_dp->active_mst_links == 0) {
> > > > +	if (intel_dp->active_streams == 0) {
> > > >  		intel_dig_port->base.post_disable(&intel_dig_port->base);
> > > >  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
> > > >  	}
> > > > @@ -165,11 +165,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> > > >  	 */
> > > >  	found->encoder = encoder;
> > > >  
> > > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > > >  
> > > >  	intel_mst->connector = found;
> > > >  
> > > > -	if (intel_dp->active_mst_links == 0) {
> > > > +	if (intel_dp->active_streams == 0) {
> > > >  		intel_prepare_ddi_buffer(&intel_dig_port->base);
> > > >  
> > > >  		intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config);
> > > > @@ -193,7 +193,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> > > >  	}
> > > >  
> > > >  
> > > > -	intel_dp->active_mst_links++;
> > > > +	intel_dp->active_streams++;
> > > >  	temp = I915_READ(DP_TP_STATUS(port));
> > > >  	I915_WRITE(DP_TP_STATUS(port), temp);
> > > >  
> > > > @@ -210,7 +210,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
> > > >  	enum port port = intel_dig_port->port;
> > > >  	int ret;
> > > >  
> > > > -	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> > > > +	DRM_DEBUG_KMS("%d\n", intel_dp->active_streams);
> > > >  
> > > >  	if (intel_wait_for_register(dev_priv,
> > > >  				    DP_TP_STATUS(port),
> > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > > index 70d7f33d6747..7fef18288aa2 100644
> > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > @@ -894,7 +894,7 @@ struct intel_dp {
> > > >  
> > > >  	bool can_mst; /* this port supports mst */
> > > >  	bool is_mst;
> > > > -	int active_mst_links;
> > > > +	int active_streams; /* number of active streams (for SST and MST both) */
> > > >  	/* connector directly attached - won't be use for modeset in mst world */
> > > >  	struct intel_connector *attached_connector;
> > > >  
> > > > -- 
> > > > 2.7.4
> > > > 
> > > > _______________________________________________
> > > > Intel-gfx mailing list
> > > > Intel-gfx@lists.freedesktop.org
> > > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > 
> > > -- 
> > > Daniel Vetter
> > > Software Engineer, Intel Corporation
> > > http://blog.ffwll.ch
> > 
> > -- 
> > Ville Syrjälä
> > Intel OTC
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3)
  2016-07-29 14:27 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3) Patchwork
@ 2016-08-04 12:35   ` Ville Syrjälä
  0 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-08-04 12:35 UTC (permalink / raw)
  To: intel-gfx

On Fri, Jul 29, 2016 at 02:27:36PM -0000, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915: Move DP link retraining to hotplug work etc. (rev3)
> URL   : https://patchwork.freedesktop.org/series/10354/
> State : failure
> 
> == Summary ==
> 
> Series 10354v3 drm/i915: Move DP link retraining to hotplug work etc.
> http://patchwork.freedesktop.org/api/1.0/series/10354/revisions/3/mbox
> 
> Test drv_module_reload_basic:
>                 skip       -> PASS       (ro-ivb-i7-3770)
>                 skip       -> PASS       (ro-skl3-i5-6260u)
> Test kms_cursor_legacy:
>         Subgroup basic-cursor-vs-flip-varying-size:
>                 pass       -> FAIL       (ro-ilk1-i5-650)

(kms_cursor_legacy:7989) DEBUG: Using a target of 32 cursor updates per half-vblank
(kms_cursor_legacy:7989) WARNING: page flip 35 was delayed, missed 1 frames
(kms_cursor_legacy:7989) CRITICAL: Test assertion failure function basic_cursor_vs_flip, file kms_cursor_legacy.c:670:
(kms_cursor_legacy:7989) CRITICAL: Failed assertion: vbl.sequence == vblank_start + 60
(kms_cursor_legacy:7989) CRITICAL: error: 11257 != 11256

https://bugs.freedesktop.org/show_bug.cgi?id=96701

>         Subgroup basic-flip-vs-cursor-legacy:
>                 pass       -> FAIL       (ro-bdw-i5-5250u)

(kms_cursor_legacy:8659) DEBUG: Test requirement passed: target > 1
(kms_cursor_legacy:8659) DEBUG: Using a target of 64 cursor updates per half-vblank
(kms_cursor_legacy:8659) CRITICAL: Test assertion failure function basic_flip_vs_cursor, file kms_cursor_legacy.c:514:
(kms_cursor_legacy:8659) CRITICAL: Failed assertion: get_vblank(display->drm_fd, pipe, 0) == vblank_start
(kms_cursor_legacy:8659) CRITICAL: error: 11057 != 11056

https://bugs.freedesktop.org/show_bug.cgi?id=97188

>         Subgroup basic-flip-vs-cursor-varying-size:
>                 fail       -> PASS       (ro-skl3-i5-6260u)
>                 fail       -> PASS       (ro-snb-i7-2620M)
>                 pass       -> FAIL       (ro-bdw-i5-5250u)

same as the other one

> 
> fi-kbl-qkkr      total:239  pass:180  dwarn:29  dfail:0   fail:3   skip:27 
> fi-skl-i5-6260u  total:239  pass:223  dwarn:0   dfail:0   fail:2   skip:14 
> fi-snb-i7-2600   total:239  pass:197  dwarn:0   dfail:0   fail:0   skip:42 
> ro-bdw-i5-5250u  total:239  pass:217  dwarn:4   dfail:0   fail:2   skip:16 
> ro-bdw-i7-5557U  total:239  pass:222  dwarn:0   dfail:0   fail:1   skip:16 
> ro-bdw-i7-5600u  total:239  pass:206  dwarn:0   dfail:0   fail:1   skip:32 
> ro-bsw-n3050     total:239  pass:193  dwarn:0   dfail:0   fail:4   skip:42 
> ro-hsw-i3-4010u  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
> ro-hsw-i7-4770r  total:239  pass:213  dwarn:0   dfail:0   fail:0   skip:26 
> ro-ilk-i7-620lm  total:239  pass:171  dwarn:1   dfail:0   fail:2   skip:65 
> ro-ilk1-i5-650   total:234  pass:171  dwarn:0   dfail:0   fail:3   skip:60 
> ro-ivb-i7-3770   total:239  pass:204  dwarn:0   dfail:0   fail:0   skip:35 
> ro-ivb2-i7-3770  total:239  pass:208  dwarn:0   dfail:0   fail:0   skip:31 
> ro-skl3-i5-6260u total:239  pass:222  dwarn:0   dfail:0   fail:3   skip:14 
> ro-snb-i7-2620M  total:239  pass:197  dwarn:0   dfail:0   fail:1   skip:41 
> fi-hsw-i7-4770k failed to connect after reboot
> fi-skl-i7-6700k failed to connect after reboot
> 
> Results at /archive/results/CI_IGT_test/RO_Patchwork_1643/
> 
> cb7629d drm-intel-nightly: 2016y-07m-28d-11h-02m-33s UTC integration manifest
> 8bbaa8b drm/i915: Add encoder .sync_state() hook
> 1b7b5401 drm/i915: Don't try to ack sink irqs when there are none
> d2da7a5 drm/i915: Allow rate_to_index() to return non-exact matches
> 489af04 drm/i915: Remove useless rate_to_index() usage
> 8a3de80 drm/i915: Skip dpcd/edid read unless there was a long hpd
> 27363d5 drm/i915: Move DP link retraining into intel_dp_detect()
> 1c8a5ee drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
> 4cb73b1 drm/i915: Track active streams also for DP SST
> 0d76448 drm/i915: Reject mixing MST and SST/HDMI on the same digital port
> 3c6377c drm/i915: Avoid mixing up SST and MST in DDI setup
> 1f1993f drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
> 4512a10 drm/i915: Ignore initial lid state for eDP

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc.
  2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
                   ` (13 preceding siblings ...)
  2016-07-29 14:27 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3) Patchwork
@ 2016-08-04 13:08 ` Ville Syrjälä
  14 siblings, 0 replies; 54+ messages in thread
From: Ville Syrjälä @ 2016-08-04 13:08 UTC (permalink / raw)
  To: intel-gfx; +Cc: Ander Conselvan de Oliveira

On Thu, Jul 28, 2016 at 05:50:36PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Ok, so while looking at the upfront link training stuff, it became obvious
> that we needs to do something about the link training stuff that we have
> in hpd_pulse currently. The thing is, you can't grab any modeset locks from
> that work since it could lead to a deadlock with MST sideband stuff.
> So here's a quick attempt at moving the stuff over to the hotplug work.
> 
> I've included a few other things at the start just to make the
> surroundings a little less broken (some of that I've posted before).
> And there are a few potentially helpful snippets at the end too.
> The main meat is in the middle.
> 
> Entire series avaialable here:
> git://github.com/vsyrjala/linux.git dp_retrain_fixes
> 
> Ville Syrjälä (12):
>   drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP
>   drm/i915: Avoid mixing up SST and MST in DDI setup
>   drm/i915: Reject mixing MST and SST/HDMI on the same digital port
>   drm/i915: Track active streams also for DP SST
>   drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails
>   drm/i915: Remove useless rate_to_index() usage
>   drm/i915: Don't try to ack sink irqs when there are none

I've pushed these to dinq. Thanks for the reviews.

>   drm/i915: Ignore initial lid state for eDP
>   drm/i915: Move DP link retraining into intel_dp_detect()
>   drm/i915: Skip dpcd/edid read unless there was a long hpd
>   drm/i915: Allow rate_to_index() to return non-exact matches
>   drm/i915: Add encoder .sync_state() hook

These are left over. Probably most of them need some
rework/rethinking anyway.

> 
>  drivers/gpu/drm/i915/intel_ddi.c     |  35 ++--
>  drivers/gpu/drm/i915/intel_display.c |  14 ++
>  drivers/gpu/drm/i915/intel_dp.c      | 390 ++++++++++++++++++-----------------
>  drivers/gpu/drm/i915/intel_dp_mst.c  |  16 +-
>  drivers/gpu/drm/i915/intel_drv.h     |  12 +-
>  5 files changed, 255 insertions(+), 212 deletions(-)
> 
> Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
> Cc: Jim Bride <jim.bride@linux.intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Durgadoss R <durgadoss.r@intel.com>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2016-08-04 13:08 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-28 14:50 [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc ville.syrjala
2016-07-28 14:50 ` [PATCH 01/12] drm/i915: Ignore initial lid state for eDP ville.syrjala
2016-07-28 15:47   ` Chris Wilson
2016-07-28 16:01     ` Ville Syrjälä
2016-07-28 16:36       ` Chris Wilson
2016-07-28 16:48         ` Ville Syrjälä
2016-07-28 14:50 ` [PATCH 02/12] drm/i915: Read PSR caps/intermediate freqs/etc. only once on eDP ville.syrjala
2016-07-28 17:30   ` Chris Wilson
2016-07-28 17:45     ` Ville Syrjälä
2016-07-29 13:52   ` [PATCH v3 " ville.syrjala
2016-07-28 14:50 ` [PATCH 03/12] drm/i915: Avoid mixing up SST and MST in DDI setup ville.syrjala
2016-07-29  9:16   ` Daniel Vetter
2016-07-29  9:55     ` Ville Syrjälä
2016-08-02 14:20       ` Daniel Vetter
2016-08-01  9:24   ` Maarten Lankhorst
2016-07-28 14:50 ` [PATCH 04/12] drm/i915: Reject mixing MST and SST/HDMI on the same digital port ville.syrjala
2016-07-29  9:19   ` Daniel Vetter
2016-07-29 11:28     ` Ville Syrjälä
2016-08-02 14:22       ` Daniel Vetter
2016-08-01  9:28   ` Maarten Lankhorst
2016-07-28 14:50 ` [PATCH 05/12] drm/i915: Track active streams also for DP SST ville.syrjala
2016-07-29  9:22   ` Daniel Vetter
2016-07-29 11:36     ` Ville Syrjälä
2016-07-29 18:36       ` Jim Bride
2016-08-02 14:28         ` Daniel Vetter
2016-07-28 14:50 ` [PATCH 06/12] drm/i915: Allow MST sinks to work even if drm_probe_ddc() fails ville.syrjala
2016-07-29  9:29   ` Daniel Vetter
2016-07-29 11:41     ` Ville Syrjälä
2016-07-29 13:51   ` [PATCH v2 " ville.syrjala
2016-07-28 14:50 ` [PATCH 07/12] drm/i915: Move DP link retraining into intel_dp_detect() ville.syrjala
2016-07-28 19:48   ` Manasi Navare
2016-07-28 20:15     ` Ville Syrjälä
2016-07-29  0:36       ` Manasi Navare
2016-07-29  9:52         ` Ville Syrjälä
2016-07-29 21:42           ` Manasi Navare
2016-07-29 21:45         ` Manasi Navare
2016-08-01 10:03           ` Ville Syrjälä
2016-07-29 20:37   ` Jim Bride
2016-07-28 14:50 ` [PATCH 08/12] drm/i915: Skip dpcd/edid read unless there was a long hpd ville.syrjala
2016-07-28 15:38   ` Chris Wilson
2016-07-28 15:44     ` Ville Syrjälä
2016-07-28 14:50 ` [PATCH 09/12] drm/i915: Remove useless rate_to_index() usage ville.syrjala
2016-07-29  9:33   ` Daniel Vetter
2016-07-28 14:50 ` [PATCH 10/12] drm/i915: Allow rate_to_index() to return non-exact matches ville.syrjala
2016-07-29  9:35   ` Daniel Vetter
2016-07-29 11:43     ` Ville Syrjälä
2016-07-28 14:50 ` [PATCH 11/12] drm/i915: Don't try to ack sink irqs when there are none ville.syrjala
2016-07-29  9:38   ` Daniel Vetter
2016-07-28 14:50 ` [RFC][PATCH 12/12] drm/i915: Add encoder .sync_state() hook ville.syrjala
2016-07-29  9:42   ` Daniel Vetter
2016-07-28 15:39 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc Patchwork
2016-07-29 14:27 ` ✗ Ro.CI.BAT: failure for drm/i915: Move DP link retraining to hotplug work etc. (rev3) Patchwork
2016-08-04 12:35   ` Ville Syrjälä
2016-08-04 13:08 ` [PATCH 00/12] drm/i915: Move DP link retraining to hotplug work etc Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.