All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent
@ 2016-10-07 23:32 Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 1/5] drm/i915: Change the placement of some static functions in intel_dp.c Manasi Navare
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

This adds support in the kernel to handle link training compliance
requests and send a uevent to train at requested parameters.
In this patch series, if the link training fails in modeset, then a
hotplug uevent is added to a work queue and scheduled and failed link
parameters are stored in intel_dp structure. This uevent
gets executed after the modeset is completed and after locks are released.
In the modeset retry, modes are validated based on lower link rate from
the failed link rate value to prune the modes in intel_dp_mode_valid().
The lower link rate is then used toc onfigure the pipe and link is retrained
at this lower link rate.

I have tested this with DPR-120 and the compliance tests are passing.
The DP CTS spec is based on DP 1.2 spec and it only expects to reduce the link
rate and train at the max lane count without reducing the lane count. Lane count
reduction is added in DP 1.3 so Unigraf has agreed to add it to their next SW release.
Hence I have not implemented fallback for lane count. But I can add it if you think
we should add DP 1.3 link training algorithm.

Please let me know your feedback on this. Compliance app is not required for link training
tests and so I have tested this fallback using kernel console mode on Source DUT.

v2:
* Corect the order of patches for correct dependencies

Manasi Navare (4):
  drm/i915; Add a function to return index of link rate
  drm/i915: Add support for DP link training compliance
  drm/i915: Work queue for uevent
  drm/i915: Link Rate fallback on Link training failure

Navare, Manasi D (1):
  drm/i915: Change the placement of some static functions in intel_dp.c

 drivers/gpu/drm/i915/i915_drv.h               |   2 +
 drivers/gpu/drm/i915/intel_ddi.c              |  10 +-
 drivers/gpu/drm/i915/intel_dp.c               | 277 ++++++++++++++++++--------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  12 +-
 drivers/gpu/drm/i915/intel_drv.h              |   8 +-
 5 files changed, 217 insertions(+), 92 deletions(-)

-- 
1.9.1

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

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

* [PATCH RFC v2 1/5] drm/i915: Change the placement of some static functions in intel_dp.c
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
@ 2016-10-07 23:32 ` Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 2/5] drm/i915; Add a function to return index of link rate Manasi Navare
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

From: "Navare, Manasi D" <manasi.d.navare@intel.com>

These static helper functions are required to be used during
fallback link rate implemnetation so they need to be placed at the top
of the file.

v3:
* Add cleanup to other patch (Mika Kahola)
v2:
* Dont move around functions declared in intel_drv.h (Rodrigo Vivi)

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Reviewed-by: Mika Kahola <mika.kahola@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 150 ++++++++++++++++++++--------------------
 1 file changed, 75 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5992093..c463c2e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -213,6 +213,81 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
+static int
+intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
+{
+	if (intel_dp->num_sink_rates) {
+		*sink_rates = intel_dp->sink_rates;
+		return intel_dp->num_sink_rates;
+	}
+
+	*sink_rates = default_rates;
+
+	return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
+}
+
+static int
+intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	int size;
+
+	if (IS_BROXTON(dev)) {
+		*source_rates = bxt_rates;
+		size = ARRAY_SIZE(bxt_rates);
+	} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+		*source_rates = skl_rates;
+		size = ARRAY_SIZE(skl_rates);
+	} else {
+		*source_rates = default_rates;
+		size = ARRAY_SIZE(default_rates);
+	}
+
+	/* This depends on the fact that 5.4 is last value in the array */
+	if (!intel_dp_source_supports_hbr2(intel_dp))
+		size--;
+
+	return size;
+}
+
+static int intersect_rates(const int *source_rates, int source_len,
+			   const int *sink_rates, int sink_len,
+			   int *common_rates)
+{
+	int i = 0, j = 0, k = 0;
+
+	while (i < source_len && j < sink_len) {
+		if (source_rates[i] == sink_rates[j]) {
+			if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
+				return k;
+			common_rates[k] = source_rates[i];
+			++k;
+			++i;
+			++j;
+		} else if (source_rates[i] < sink_rates[j]) {
+			++i;
+		} else {
+			++j;
+		}
+	}
+	return k;
+}
+
+static int intel_dp_common_rates(struct intel_dp *intel_dp,
+				 int *common_rates)
+{
+	const int *source_rates, *sink_rates;
+	int source_len, sink_len;
+
+	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	source_len = intel_dp_source_rates(intel_dp, &source_rates);
+
+	return intersect_rates(source_rates, source_len,
+			       sink_rates, sink_len,
+			       common_rates);
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
@@ -1281,19 +1356,6 @@ intel_dp_aux_init(struct intel_dp *intel_dp)
 	intel_dp->aux.transfer = intel_dp_aux_transfer;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
-}
-
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1306,31 +1368,6 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
 		return false;
 }
 
-static int
-intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	int size;
-
-	if (IS_BROXTON(dev_priv)) {
-		*source_rates = bxt_rates;
-		size = ARRAY_SIZE(bxt_rates);
-	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-		*source_rates = skl_rates;
-		size = ARRAY_SIZE(skl_rates);
-	} else {
-		*source_rates = default_rates;
-		size = ARRAY_SIZE(default_rates);
-	}
-
-	/* This depends on the fact that 5.4 is last value in the array */
-	if (!intel_dp_source_supports_hbr2(intel_dp))
-		size--;
-
-	return size;
-}
-
 static void
 intel_dp_set_clock(struct intel_encoder *encoder,
 		   struct intel_crtc_state *pipe_config)
@@ -1364,43 +1401,6 @@ intel_dp_set_clock(struct intel_encoder *encoder,
 	}
 }
 
-static int intersect_rates(const int *source_rates, int source_len,
-			   const int *sink_rates, int sink_len,
-			   int *common_rates)
-{
-	int i = 0, j = 0, k = 0;
-
-	while (i < source_len && j < sink_len) {
-		if (source_rates[i] == sink_rates[j]) {
-			if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
-				return k;
-			common_rates[k] = source_rates[i];
-			++k;
-			++i;
-			++j;
-		} else if (source_rates[i] < sink_rates[j]) {
-			++i;
-		} else {
-			++j;
-		}
-	}
-	return k;
-}
-
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
-				 int *common_rates)
-{
-	const int *source_rates, *sink_rates;
-	int source_len, sink_len;
-
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	source_len = intel_dp_source_rates(intel_dp, &source_rates);
-
-	return intersect_rates(source_rates, source_len,
-			       sink_rates, sink_len,
-			       common_rates);
-}
-
 static void snprintf_int_array(char *str, size_t len,
 			       const int *array, int nelem)
 {
-- 
1.9.1

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

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

* [PATCH RFC v2 2/5] drm/i915; Add a function to return index of link rate
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 1/5] drm/i915: Change the placement of some static functions in intel_dp.c Manasi Navare
@ 2016-10-07 23:32 ` Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 3/5] drm/i915: Add support for DP link training compliance Manasi Navare
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

This is required to return the index of link rate into
common_rates array. This gets used to retry the link
training at lower link rate.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c463c2e..4ab4aa1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -288,6 +288,21 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp,
 			       common_rates);
 }
 
+static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int *common_rates,
+				    int link_rate)
+{
+	int common_len;
+	int index;
+
+	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	for (index = 0; index < common_len; index++) {
+		if (link_rate == common_rates[common_len - index - 1])
+			return common_len - index - 1;
+	}
+
+	return -1;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
-- 
1.9.1

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

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

* [PATCH RFC v2 3/5] drm/i915: Add support for DP link training compliance
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 1/5] drm/i915: Change the placement of some static functions in intel_dp.c Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 2/5] drm/i915; Add a function to return index of link rate Manasi Navare
@ 2016-10-07 23:32 ` Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 4/5] drm/i915: Work queue for uevent Manasi Navare
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

This patch adds support to handle automated DP compliance
link training test requests. This patch has been tested with
Unigraf DPR-120 DP Compliance device for testing Link
Training Compliance.
After we get a short pulse Compliance test request, test
request values are read and hotplug uevent is sent in order
to trigger another modeset during which the pipe is configured
and link is enabled for link parameters requested by the test.

Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 71 ++++++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 2 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4ab4aa1..610316f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1567,6 +1567,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
+	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
@@ -1608,6 +1609,20 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return false;
 
+	/* Use values requested by Compliance Test Request */
+	if (intel_dp->compliance_test_link_rate &&
+	    intel_dp->compliance_test_lane_count) {
+			link_rate_index = intel_dp_link_rate_index(intel_dp,
+								   common_rates,
+								   drm_dp_bw_code_to_link_rate(intel_dp->compliance_test_link_rate));
+			if (link_rate_index >= 0)
+				min_clock = max_clock = link_rate_index;
+			min_lane_count = max_lane_count = intel_dp->compliance_test_lane_count;
+
+			intel_dp->compliance_test_link_rate = 0;
+			intel_dp->compliance_test_lane_count = 0;
+		}
+
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
 		      "max bw %d pixel clock %iKHz\n",
 		      max_lane_count, common_rates[max_clock],
@@ -1655,6 +1670,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 				}
 			}
 		}
+
 	}
 
 	return false;
@@ -3835,6 +3851,29 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
 	uint8_t test_result = DP_TEST_ACK;
+	int status = 0;
+	/* (DP CTS 1.2)
+	 * 4.3.1.11
+	 */
+	/* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */
+	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT,
+				  &intel_dp->compliance_test_lane_count);
+
+	if (status <= 0) {
+		DRM_DEBUG_KMS("Could not read test lane count from "
+			      "reference sink\n");
+		return 0;
+	}
+	intel_dp->compliance_test_lane_count &= DP_MAX_LANE_COUNT_MASK;
+
+	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
+				   &intel_dp->compliance_test_link_rate);
+	if (status <= 0) {
+		DRM_DEBUG_KMS("Could not read test link rate from "
+			      "refernce sink\n");
+		return 0;
+	}
+
 	return test_result;
 }
 
@@ -3935,11 +3974,14 @@ static void intel_dp_handle_test_request(struct intel_dp *intel_dp)
 	}
 
 update_status:
-	status = drm_dp_dpcd_write(&intel_dp->aux,
-				   DP_TEST_RESPONSE,
-				   &response, 1);
-	if (status <= 0)
-		DRM_DEBUG_KMS("Could not write test response to sink\n");
+	if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) {
+		status = drm_dp_dpcd_write(&intel_dp->aux,
+					   DP_TEST_RESPONSE,
+					   &response, 1);
+		if (status <= 0)
+			DRM_DEBUG_KMS("Could not write test response "
+				      "to sink\n");
+	}
 }
 
 static int
@@ -4019,9 +4061,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
 		return;
 
-	/* 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 ((!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
 			      intel_encoder->base.name);
 		intel_dp_start_link_train(intel_dp);
@@ -4046,6 +4086,7 @@ static bool
 intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 	u8 sink_irq_vector = 0;
 	u8 old_sink_count = intel_dp->sink_count;
 	bool ret;
@@ -4080,8 +4121,9 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 				   DP_DEVICE_SERVICE_IRQ_VECTOR,
 				   sink_irq_vector);
 
-		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
-			DRM_DEBUG_DRIVER("Test request in short pulse not handled\n");
+		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST) {
+			intel_dp_handle_test_request(intel_dp);
+		}
 		if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
 			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
 	}
@@ -4089,6 +4131,10 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 	intel_dp_check_link_status(intel_dp);
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING)) {
+		/* Send a Hotplug Uevent to userspace to start modeset */
+		drm_kms_helper_hotplug_event(intel_encoder->base.dev);
+	}
 
 	return true;
 }
@@ -4366,6 +4412,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	/* Can't disconnect eDP, but you can close the lid... */
 	if (is_edp(intel_dp))
 		status = edp_detect(intel_dp);
+	else if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) {
+		status = connector_status_disconnected;
+		intel_dp->compliance_test_type = 0;
+		goto out;
+	}
 	else if (intel_digital_port_connected(to_i915(dev),
 					      dp_to_dig_port(intel_dp)))
 		status = intel_dp_detect_dpcd(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f48e79a..82fc4fe 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -951,6 +951,8 @@ struct intel_dp {
 	unsigned long compliance_test_type;
 	unsigned long compliance_test_data;
 	bool compliance_test_active;
+	u8 compliance_test_lane_count;
+	u8 compliance_test_link_rate;
 };
 
 struct intel_digital_port {
-- 
1.9.1

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

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

* [PATCH RFC v2 4/5] drm/i915: Work queue for uevent
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
                   ` (2 preceding siblings ...)
  2016-10-07 23:32 ` [PATCH RFC v2 3/5] drm/i915: Add support for DP link training compliance Manasi Navare
@ 2016-10-07 23:32 ` Manasi Navare
  2016-10-07 23:32 ` [PATCH RFC v2 5/5] drm/i915: Link Rate fallback on Link training failure Manasi Navare
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

We create a work queue for sending a hotplug uevent. This
gets scheduled on link training failure and gets executed after
modeset is finished and all locks are released.
This was required to avoid deadlock.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_dp.c | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a219a35..9592e64 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1962,6 +1962,8 @@ struct drm_i915_private {
 
 	struct drm_i915_gem_object *vlv_pctx;
 
+	struct work_struct i915_modeset_retry_work;
+
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 610316f..06c9d17 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5691,6 +5691,15 @@ out_vdd_off:
 	return false;
 }
 
+static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv;
+
+	dev_priv = container_of(work, typeof(*dev_priv), i915_modeset_retry_work);
+	DRM_DEBUG_KMS("\nManasi: Sending Uevent");
+	drm_kms_helper_hotplug_event(&dev_priv->drm);
+}
+
 bool
 intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			struct intel_connector *intel_connector)
@@ -5703,6 +5712,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	enum port port = intel_dig_port->port;
 	int type;
 
+	/* Initialize the work for modeset in case of link train failure */
+	INIT_WORK(&dev_priv->i915_modeset_retry_work, intel_dp_modeset_retry_work_fn);
+
 	if (WARN(intel_dig_port->max_lanes < 1,
 		 "Not enough lanes (%d) for DP on port %c\n",
 		 intel_dig_port->max_lanes, port_name(port)))
-- 
1.9.1

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

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

* [PATCH RFC v2 5/5] drm/i915: Link Rate fallback on Link training failure
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
                   ` (3 preceding siblings ...)
  2016-10-07 23:32 ` [PATCH RFC v2 4/5] drm/i915: Work queue for uevent Manasi Navare
@ 2016-10-07 23:32 ` Manasi Navare
  2016-10-10 13:17 ` [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Jani Nikula
  2016-10-10 14:20 ` ✗ Fi.CI.BAT: warning for Link Training Compliance support, link rate fallback sending Uevent (rev2) Patchwork
  6 siblings, 0 replies; 8+ messages in thread
From: Manasi Navare @ 2016-10-07 23:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: daniel.vetter

If link training at a link rate optimal for a particular
mode fails during modeset's atomic commit phase, then we
let the modeset complete and then retry. We save the link rate
value at which link training failed and use a lower link rate
to prune the modes during the next modeset, configure the pipe at
lower link rate and retrian at lower link rate.

This is also required to pass DP CTS tests 4.3.1.3, 4.3.1.4,
4.3.1.6.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c              | 10 ++++++++-
 drivers/gpu/drm/i915/intel_dp.c               | 31 ++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_dp_link_training.c | 12 ++++++++---
 drivers/gpu/drm/i915/intel_drv.h              |  6 +++++-
 4 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 35f0b7c..d3b5671 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1652,7 +1652,15 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	intel_prepare_dp_ddi_buffers(encoder);
 	intel_ddi_init_dp_buf_reg(encoder);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	intel_dp_start_link_train(intel_dp);
+	if (!intel_dp_start_link_train(intel_dp)) {
+		DRM_ERROR("Link Training failed at link rate = %d, lane count = %d",
+			  link_rate, lane_count);
+		intel_dp->link_train_failed = true;
+		intel_dp->link_train_failed_link_rate = link_rate;
+		intel_dp->link_train_failed_lane_count = lane_count;
+		/* Schedule a Hotplug Uevent to userspace to start modeset */
+		schedule_work(&dev_priv->i915_modeset_retry_work);
+	}
 	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
 		intel_dp_stop_link_train(intel_dp);
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 06c9d17..9c1944a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -313,6 +313,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	int target_clock = mode->clock;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
 	int max_dotclk;
+	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
 
 	max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
 
@@ -326,8 +327,22 @@ intel_dp_mode_valid(struct drm_connector *connector,
 		target_clock = fixed_mode->clock;
 	}
 
-	max_link_clock = intel_dp_max_link_rate(intel_dp);
-	max_lanes = intel_dp_max_lane_count(intel_dp);
+	/* Prune the modes based on the link rate that failed */
+	if (intel_dp->link_train_failed_link_rate) {
+		intel_dp->link_rate_index = intel_dp_link_rate_index(intel_dp,
+								     common_rates,
+								     intel_dp->link_train_failed_link_rate);
+		if (intel_dp->link_rate_index > 0) {
+			max_link_clock = common_rates[intel_dp->link_rate_index - 1];
+			max_lanes = intel_dp_max_lane_count(intel_dp);
+		} else
+			/* Here we can lower the lane count, but that is DP 1.3 not 1.2 */
+			DRM_ERROR(" No Valid Mode Supported for this Link");
+	}
+	else {
+		max_link_clock = intel_dp_max_link_rate(intel_dp);
+		max_lanes = intel_dp_max_lane_count(intel_dp);
+	}
 
 	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
 	mode_rate = intel_dp_link_required(target_clock, 18);
@@ -1623,6 +1638,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 			intel_dp->compliance_test_lane_count = 0;
 		}
 
+	/* Fall back to lower link rate in case of failure in previous modeset */
+	if (intel_dp->link_train_failed_link_rate) {
+		min_lane_count = max_lane_count;
+		min_clock = max_clock = intel_dp->link_rate_index - 1;
+		intel_dp->link_train_failed_link_rate = 0;
+		intel_dp->link_rate_index = -1;
+	}
+
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
 		      "max bw %d pixel clock %iKHz\n",
 		      max_lane_count, common_rates[max_clock],
@@ -4412,9 +4435,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	/* Can't disconnect eDP, but you can close the lid... */
 	if (is_edp(intel_dp))
 		status = edp_detect(intel_dp);
-	else if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) {
+	else if (intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING ||
+		 intel_dp->link_train_failed) {
 		status = connector_status_disconnected;
 		intel_dp->compliance_test_type = 0;
+		intel_dp->link_train_failed = false;
 		goto out;
 	}
 	else if (intel_digital_port_connected(to_i915(dev),
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
index 0048b52..10f81ab 100644
--- a/drivers/gpu/drm/i915/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
@@ -310,9 +310,15 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 				DP_TRAINING_PATTERN_DISABLE);
 }
 
-void
+bool
 intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-	intel_dp_link_training_clock_recovery(intel_dp);
-	intel_dp_link_training_channel_equalization(intel_dp);
+	bool ret;
+
+	if (intel_dp_link_training_clock_recovery(intel_dp)) {
+		ret = intel_dp_link_training_channel_equalization(intel_dp);
+		if (ret)
+			return true;
+	}
+	return false;
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 82fc4fe..10335ab 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -882,6 +882,10 @@ struct intel_dp {
 	uint32_t DP;
 	int link_rate;
 	uint8_t lane_count;
+	int link_train_failed_link_rate;
+	uint8_t link_train_failed_lane_count;
+	int link_rate_index;
+	bool link_train_failed;
 	uint8_t sink_count;
 	bool link_mst;
 	bool has_audio;
@@ -1389,7 +1393,7 @@ bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
 			      int link_rate, uint8_t lane_count,
 			      bool link_mst);
-void intel_dp_start_link_train(struct intel_dp *intel_dp);
+bool intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 void intel_dp_encoder_reset(struct drm_encoder *encoder);
-- 
1.9.1

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

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

* Re: [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
                   ` (4 preceding siblings ...)
  2016-10-07 23:32 ` [PATCH RFC v2 5/5] drm/i915: Link Rate fallback on Link training failure Manasi Navare
@ 2016-10-10 13:17 ` Jani Nikula
  2016-10-10 14:20 ` ✗ Fi.CI.BAT: warning for Link Training Compliance support, link rate fallback sending Uevent (rev2) Patchwork
  6 siblings, 0 replies; 8+ messages in thread
From: Jani Nikula @ 2016-10-10 13:17 UTC (permalink / raw)
  To: Manasi Navare, intel-gfx; +Cc: daniel.vetter

On Sat, 08 Oct 2016, Manasi Navare <manasi.d.navare@intel.com> wrote:
> This adds support in the kernel to handle link training compliance
> requests and send a uevent to train at requested parameters.
> In this patch series, if the link training fails in modeset, then a
> hotplug uevent is added to a work queue and scheduled and failed link
> parameters are stored in intel_dp structure. This uevent
> gets executed after the modeset is completed and after locks are released.
> In the modeset retry, modes are validated based on lower link rate from
> the failed link rate value to prune the modes in intel_dp_mode_valid().
> The lower link rate is then used toc onfigure the pipe and link is retrained
> at this lower link rate.
>
> I have tested this with DPR-120 and the compliance tests are passing.
> The DP CTS spec is based on DP 1.2 spec and it only expects to reduce the link
> rate and train at the max lane count without reducing the lane count. Lane count
> reduction is added in DP 1.3 so Unigraf has agreed to add it to their next SW release.
> Hence I have not implemented fallback for lane count. But I can add it if you think
> we should add DP 1.3 link training algorithm.
>
> Please let me know your feedback on this. Compliance app is not required for link training
> tests and so I have tested this fallback using kernel console mode on Source DUT.

The question is, can you pass the link training tests using a userspace
that responds to hotplug uevents? I think you mentioned a timeout in the
CTS. If you're using fbdev, I think the retry modeset may happen faster
than with a regular userspace.

BR,
Jani.


>
> v2:
> * Corect the order of patches for correct dependencies
>
> Manasi Navare (4):
>   drm/i915; Add a function to return index of link rate
>   drm/i915: Add support for DP link training compliance
>   drm/i915: Work queue for uevent
>   drm/i915: Link Rate fallback on Link training failure
>
> Navare, Manasi D (1):
>   drm/i915: Change the placement of some static functions in intel_dp.c
>
>  drivers/gpu/drm/i915/i915_drv.h               |   2 +
>  drivers/gpu/drm/i915/intel_ddi.c              |  10 +-
>  drivers/gpu/drm/i915/intel_dp.c               | 277 ++++++++++++++++++--------
>  drivers/gpu/drm/i915/intel_dp_link_training.c |  12 +-
>  drivers/gpu/drm/i915/intel_drv.h              |   8 +-
>  5 files changed, 217 insertions(+), 92 deletions(-)

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✗ Fi.CI.BAT: warning for Link Training Compliance support, link rate fallback sending Uevent (rev2)
  2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
                   ` (5 preceding siblings ...)
  2016-10-10 13:17 ` [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Jani Nikula
@ 2016-10-10 14:20 ` Patchwork
  6 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2016-10-10 14:20 UTC (permalink / raw)
  To: Navare, Manasi D; +Cc: intel-gfx

== Series Details ==

Series: Link Training Compliance support, link rate fallback sending Uevent (rev2)
URL   : https://patchwork.freedesktop.org/series/13468/
State : warning

== Summary ==

Series 13468v2 Link Training Compliance support, link rate fallback sending Uevent
https://patchwork.freedesktop.org/api/1.0/series/13468/revisions/2/mbox/

Test drv_module_reload_basic:
                pass       -> SKIP       (fi-ivb-3520m)
Test kms_pipe_crc_basic:
        Subgroup read-crc-pipe-a-frame-sequence:
                pass       -> DMESG-WARN (fi-skl-6770hq)
Test kms_psr_sink_crc:
        Subgroup psr_basic:
                dmesg-warn -> PASS       (fi-skl-6700hq)
Test vgem_basic:
        Subgroup unload:
                skip       -> PASS       (fi-byt-n2820)
                pass       -> SKIP       (fi-ilk-650)
                skip       -> PASS       (fi-bsw-n3050)
                pass       -> SKIP       (fi-skl-6700hq)
                skip       -> PASS       (fi-bdw-5557u)
                pass       -> SKIP       (fi-skl-6260u)

fi-bdw-5557u     total:248  pass:232  dwarn:0   dfail:0   fail:0   skip:16 
fi-bsw-n3050     total:248  pass:205  dwarn:0   dfail:0   fail:0   skip:43 
fi-bxt-t5700     total:248  pass:217  dwarn:0   dfail:0   fail:0   skip:31 
fi-byt-j1900     total:248  pass:214  dwarn:1   dfail:0   fail:1   skip:32 
fi-byt-n2820     total:248  pass:211  dwarn:0   dfail:0   fail:1   skip:36 
fi-hsw-4770      total:248  pass:224  dwarn:0   dfail:0   fail:0   skip:24 
fi-hsw-4770r     total:248  pass:224  dwarn:0   dfail:0   fail:0   skip:24 
fi-ilk-650       total:248  pass:184  dwarn:0   dfail:0   fail:2   skip:62 
fi-ivb-3520m     total:248  pass:220  dwarn:0   dfail:0   fail:0   skip:28 
fi-ivb-3770      total:248  pass:207  dwarn:0   dfail:0   fail:0   skip:41 
fi-kbl-7200u     total:248  pass:222  dwarn:0   dfail:0   fail:0   skip:26 
fi-skl-6260u     total:248  pass:232  dwarn:0   dfail:0   fail:0   skip:16 
fi-skl-6700hq    total:248  pass:224  dwarn:0   dfail:0   fail:0   skip:24 
fi-skl-6700k     total:248  pass:221  dwarn:1   dfail:0   fail:0   skip:26 
fi-skl-6770hq    total:248  pass:230  dwarn:2   dfail:0   fail:1   skip:15 
fi-snb-2520m     total:248  pass:211  dwarn:0   dfail:0   fail:0   skip:37 
fi-snb-2600      total:248  pass:209  dwarn:0   dfail:0   fail:0   skip:39 

Results at /archive/results/CI_IGT_test/Patchwork_2656/

f35ed31aea66b3230c366fcba5f3456ae2cb956e drm-intel-nightly: 2016y-10m-10d-11h-28m-51s UTC integration manifest
ab8641d drm/i915: Link Rate fallback on Link training failure
bf2b27e drm/i915: Work queue for uevent
1498096 drm/i915: Add support for DP link training compliance
49563cd drm/i915; Add a function to return index of link rate
9e268a4 drm/i915: Change the placement of some static functions in intel_dp.c

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

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

end of thread, other threads:[~2016-10-10 14:20 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 23:32 [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Manasi Navare
2016-10-07 23:32 ` [PATCH RFC v2 1/5] drm/i915: Change the placement of some static functions in intel_dp.c Manasi Navare
2016-10-07 23:32 ` [PATCH RFC v2 2/5] drm/i915; Add a function to return index of link rate Manasi Navare
2016-10-07 23:32 ` [PATCH RFC v2 3/5] drm/i915: Add support for DP link training compliance Manasi Navare
2016-10-07 23:32 ` [PATCH RFC v2 4/5] drm/i915: Work queue for uevent Manasi Navare
2016-10-07 23:32 ` [PATCH RFC v2 5/5] drm/i915: Link Rate fallback on Link training failure Manasi Navare
2016-10-10 13:17 ` [PATCH RFC v2 0/5] Link Training Compliance support, link rate fallback sending Uevent Jani Nikula
2016-10-10 14:20 ` ✗ Fi.CI.BAT: warning for Link Training Compliance support, link rate fallback sending Uevent (rev2) Patchwork

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.