All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Kernel PSR Fix-ups
@ 2017-05-05 21:02 Jim Bride
  2017-05-05 21:02 ` [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available Jim Bride
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Jim Bride @ 2017-05-05 21:02 UTC (permalink / raw)
  To: intel-gfx

These patches, along with an upcoming series for IGT, enable our
PSR IGT tests to run reliably once again.  The first change
enables us to run the PSR tests on SKL and KBL RVP platforms,
whose panels have too slow of a setup time when running in their
preferred mode.  The second fixes a minor problem with the way that
we were initializing SRD_CTL that caused us to clobber a bit that we
are not supposed to change in that register on SKL and KBL.  The third
change re-introduces some changes to our link training code to be less
aggressive about changing link state for eDP, because PSR depends on
the link state being the same at PSR exit as it was at PSR entry.
The fourth change greatly increases the reliability of reading the
sink CRC generated by the eDP panel.  

Jim Bride (4):
  drm/i915/edp: Allow alternate fixed mode for eDP if available.
  drm/i915/psr: Clean-up intel_enable_source_psr1()
  drm/i915/edp: Be less aggressive about changing link config on eDP
  drm/i915/psr: Account for sink CRC raciness on some panels

 drivers/gpu/drm/i915/i915_debugfs.c           | 14 +++-
 drivers/gpu/drm/i915/i915_reg.h               |  4 ++
 drivers/gpu/drm/i915/intel_dp.c               | 95 +++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_dp_link_training.c | 11 +++-
 drivers/gpu/drm/i915/intel_drv.h              |  4 ++
 drivers/gpu/drm/i915/intel_dsi.c              |  2 +-
 drivers/gpu/drm/i915/intel_dvo.c              |  2 +-
 drivers/gpu/drm/i915/intel_lvds.c             |  3 +-
 drivers/gpu/drm/i915/intel_panel.c            |  2 +
 drivers/gpu/drm/i915/intel_psr.c              | 21 +++++-
 10 files changed, 136 insertions(+), 22 deletions(-)

-- 
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] 16+ messages in thread

* [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available.
  2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
@ 2017-05-05 21:02 ` Jim Bride
  2017-05-08  8:54   ` Jani Nikula
  2017-05-05 21:02 ` [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1() Jim Bride
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Jim Bride @ 2017-05-05 21:02 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

Some fixed resolution panels actually support more than one mode,
with the only thing different being the refresh rate.  Having this
alternate mode available to us is desirable, because it allows us to
test PSR on panels whose setup time at the preferred mode is too long.
With this patch we allow the use of the alternate mode if it's
available and it was specifically requested.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c    | 34 +++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h   |  2 ++
 drivers/gpu/drm/i915/intel_dsi.c   |  2 +-
 drivers/gpu/drm/i915/intel_dvo.c   |  2 +-
 drivers/gpu/drm/i915/intel_lvds.c  |  3 ++-
 drivers/gpu/drm/i915/intel_panel.c |  2 ++
 6 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 08834f7..d46f72d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1637,6 +1637,19 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
 	return bpp;
 }
 
+static bool intel_edp_compare_alt_mode(struct drm_display_mode *m1,
+				       struct drm_display_mode *m2)
+{
+	return (m1->hdisplay == m2->hdisplay &&
+		m1->hsync_start == m2->hsync_start &&
+		m1->hsync_end == m2->hsync_end &&
+		m1->htotal == m2->htotal &&
+		m1->vdisplay == m2->vdisplay &&
+		m1->vsync_start == m2->vsync_start &&
+		m1->vsync_end == m2->vsync_end &&
+		m1->vtotal == m2->vtotal);
+}
+
 bool
 intel_dp_compute_config(struct intel_encoder *encoder,
 			struct intel_crtc_state *pipe_config,
@@ -1674,8 +1687,16 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;
 
 	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
-		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
-				       adjusted_mode);
+		struct drm_display_mode *panel_mode =
+			intel_connector->panel.alt_fixed_mode;
+		struct drm_display_mode *req_mode = &pipe_config->base.mode;
+
+		if (!intel_edp_compare_alt_mode(req_mode, panel_mode))
+			panel_mode = intel_connector->panel.fixed_mode;
+
+		drm_mode_debug_printmodeline(panel_mode);
+
+		intel_fixed_panel_mode(panel_mode, adjusted_mode);
 
 		if (INTEL_GEN(dev_priv) >= 9) {
 			int ret;
@@ -5829,6 +5850,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_display_mode *fixed_mode = NULL;
+	struct drm_display_mode *alt_fixed_mode = NULL;
 	struct drm_display_mode *downclock_mode = NULL;
 	bool has_dpcd;
 	struct drm_display_mode *scan;
@@ -5884,13 +5906,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
-	/* prefer fixed mode from EDID if available */
+	/* prefer fixed mode from EDID if available, save an alt mode also */
 	list_for_each_entry(scan, &connector->probed_modes, head) {
 		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
 			fixed_mode = drm_mode_duplicate(dev, scan);
 			downclock_mode = intel_dp_drrs_init(
 						intel_connector, fixed_mode);
-			break;
+		} else {
+			alt_fixed_mode = drm_mode_duplicate(dev, scan);
 		}
 	}
 
@@ -5927,7 +5950,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 			      pipe_name(pipe));
 	}
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, alt_fixed_mode,
+			 downclock_mode);
 	intel_connector->panel.backlight.power = intel_edp_backlight_power;
 	intel_panel_setup_backlight(connector, pipe);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 54f3ff8..19d0c8f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -265,6 +265,7 @@ struct intel_encoder {
 
 struct intel_panel {
 	struct drm_display_mode *fixed_mode;
+	struct drm_display_mode *alt_fixed_mode;
 	struct drm_display_mode *downclock_mode;
 	int fitting_mode;
 
@@ -1676,6 +1677,7 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
 /* intel_panel.c */
 int intel_panel_init(struct intel_panel *panel,
 		     struct drm_display_mode *fixed_mode,
+		     struct drm_display_mode *alt_fixed_mode,
 		     struct drm_display_mode *downclock_mode);
 void intel_panel_fini(struct intel_panel *panel);
 void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index fc0ef49..a938f08 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1852,7 +1852,7 @@ void intel_dsi_init(struct drm_i915_private *dev_priv)
 	connector->display_info.width_mm = fixed_mode->width_mm;
 	connector->display_info.height_mm = fixed_mode->height_mm;
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+	intel_panel_init(&intel_connector->panel, fixed_mode, NULL, NULL);
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	intel_dsi_add_properties(intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index c1544a5..39fd4f3 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -554,7 +554,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
 			 */
 			intel_panel_init(&intel_connector->panel,
 					 intel_dvo_get_current_mode(connector),
-					 NULL);
+					 NULL, NULL);
 			intel_dvo->panel_wants_dither = true;
 		}
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 8b942ef..b1e6743 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -1181,7 +1181,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 out:
 	mutex_unlock(&dev->mode_config.mutex);
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
+			 downclock_mode);
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index cb50c52..41eb7b0 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1801,11 +1801,13 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
 
 int intel_panel_init(struct intel_panel *panel,
 		     struct drm_display_mode *fixed_mode,
+		     struct drm_display_mode *alt_fixed_mode,
 		     struct drm_display_mode *downclock_mode)
 {
 	intel_panel_init_backlight_funcs(panel);
 
 	panel->fixed_mode = fixed_mode;
+	panel->alt_fixed_mode = alt_fixed_mode;
 	panel->downclock_mode = downclock_mode;
 
 	return 0;
-- 
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] 16+ messages in thread

* [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1()
  2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
  2017-05-05 21:02 ` [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available Jim Bride
@ 2017-05-05 21:02 ` Jim Bride
  2017-05-23 19:07   ` Rodrigo Vivi
  2017-05-05 21:02 ` [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP Jim Bride
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Jim Bride @ 2017-05-05 21:02 UTC (permalink / raw)
  To: intel-gfx; +Cc: Wayne Boyer, Paulo Zanoni, Rodrigo Vivi

On SKL+ there is a bit in SRD_CTL that software is not supposed to
modify, but we currently clobber that bit when we enable PSR.  In
order to preserve the value of that bit, go ahead and read SRD_CTL and
do a field-wise setting of the various bits that we need to initialize
before writing the register back out.  Additionally, go ahead and
explicitly disable single-frame update since we aren't currently
supporting it.

v2: Do a field-wise init on EDP_PSR_MAX_SLEEP_TIME even though we
    always set it to the max value. (Rodrigo)

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Wayne Boyer <wayne.boyer@intel.com>
Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  4 ++++
 drivers/gpu/drm/i915/intel_psr.c | 21 +++++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ee8170c..3a63555 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3584,18 +3584,22 @@ enum {
 #define   EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES	(1<<25)
 #define   EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES	(2<<25)
 #define   EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES	(3<<25)
+#define   EDP_PSR_MAX_SLEEP_TIME_MASK           (0x1f<<20)
 #define   EDP_PSR_MAX_SLEEP_TIME_SHIFT		20
 #define   EDP_PSR_SKIP_AUX_EXIT			(1<<12)
 #define   EDP_PSR_TP1_TP2_SEL			(0<<11)
 #define   EDP_PSR_TP1_TP3_SEL			(1<<11)
+#define   EDP_PSR_TP2_TP3_TIME_MASK             (3<<8)
 #define   EDP_PSR_TP2_TP3_TIME_500us		(0<<8)
 #define   EDP_PSR_TP2_TP3_TIME_100us		(1<<8)
 #define   EDP_PSR_TP2_TP3_TIME_2500us		(2<<8)
 #define   EDP_PSR_TP2_TP3_TIME_0us		(3<<8)
+#define   EDP_PSR_TP1_TIME_MASK                 (0x3<<4)
 #define   EDP_PSR_TP1_TIME_500us		(0<<4)
 #define   EDP_PSR_TP1_TIME_100us		(1<<4)
 #define   EDP_PSR_TP1_TIME_2500us		(2<<4)
 #define   EDP_PSR_TP1_TIME_0us			(3<<4)
+#define   EDP_PSR_IDLE_FRAME_MASK               (0xf<<0)
 #define   EDP_PSR_IDLE_FRAME_SHIFT		0
 
 #define EDP_PSR_AUX_CTL				_MMIO(dev_priv->psr_mmio_base + 0x10)
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index c3780d0..068c382 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -280,17 +280,32 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
 	 * with the 5 or 6 idle patterns.
 	 */
 	uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
-	uint32_t val = EDP_PSR_ENABLE;
+	uint32_t val = I915_READ(EDP_PSR_CTL);
 
+	val |= EDP_PSR_ENABLE;
+
+	val &= ~EDP_PSR_MAX_SLEEP_TIME_MASK;
 	val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
+
+	val &= ~EDP_PSR_IDLE_FRAME_MASK;
 	val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
 
+	val &= ~EDP_PSR_MIN_LINK_ENTRY_TIME_MASK;
 	if (IS_HASWELL(dev_priv))
 		val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
-	if (dev_priv->psr.link_standby)
+	if (dev_priv->psr.link_standby) {
 		val |= EDP_PSR_LINK_STANDBY;
 
+		/* SFU should only be enabled with link standby, but for
+		 * now we do not support it. */
+		val &= ~BDW_PSR_SINGLE_FRAME;
+	} else {
+		val &= ~EDP_PSR_LINK_STANDBY;
+		val &= ~BDW_PSR_SINGLE_FRAME;
+	}
+
+	val &= ~EDP_PSR_TP1_TIME_MASK;
 	if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
 		val |= EDP_PSR_TP1_TIME_2500us;
 	else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
@@ -300,6 +315,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
 	else
 		val |= EDP_PSR_TP1_TIME_0us;
 
+	val &= ~EDP_PSR_TP2_TP3_TIME_MASK;
 	if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
 		val |= EDP_PSR_TP2_TP3_TIME_2500us;
 	else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
@@ -309,6 +325,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
 	else
 		val |= EDP_PSR_TP2_TP3_TIME_0us;
 
+	val &= ~EDP_PSR_TP1_TP3_SEL;
 	if (intel_dp_source_supports_hbr2(intel_dp) &&
 	    drm_dp_tps3_supported(intel_dp->dpcd))
 		val |= EDP_PSR_TP1_TP3_SEL;
-- 
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] 16+ messages in thread

* [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP
  2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
  2017-05-05 21:02 ` [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available Jim Bride
  2017-05-05 21:02 ` [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1() Jim Bride
@ 2017-05-05 21:02 ` Jim Bride
  2017-05-08  8:41   ` Jani Nikula
  2017-05-08 13:07   ` Mika Kahola
  2017-05-05 21:02 ` [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels Jim Bride
  2017-05-05 21:20 ` ✓ Fi.CI.BAT: success for Kernel PSR Fix-ups Patchwork
  4 siblings, 2 replies; 16+ messages in thread
From: Jim Bride @ 2017-05-05 21:02 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

This set of changes has some history to them.  There were several attempts
to add what was called "fast link training" to i915, which actually wasn't
fast link training as per the DP spec.  These changes were

5fa836a9d859 ("drm/i915: DP link training optimization")
4e96c97742f4 ("drm/i915: eDP link training optimization")

which were eventually hand-reverted by

34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")

in kernel 4.7-rc4.  The eDP pieces of the above revert, however, had some
very bad side-effects on PSR functionality on Skylake. The issue at
hand is that when PSR exits i915 briefly emits TP1 followed by TP2/3
(depending on the original link configuration) in order to quickly get
the source and sink back in synchronization across the link before handing
control back to the i915.  There's an assumption that none of the link
configuration information has changed (and thus it's still valid) since the
last full link training operation.  The revert above was identified via a
bisect as the cause of some of Skylake's PSR woes.  This patch, largely
based on

commit 4e96c97742f4201edf1b0f8e1b1b6b2ac6ff33e7
Author: Mika Kahola <mika.kahola@intel.com>
Date:   Wed Apr 29 09:17:39 2015 +0300
drm/i915: eDP link training optimization

puts the eDP portions of this patch back in place.  None of the flickering
issues that spurred the revert have been seen, and I suspect the real
culprits here were addressed by some of the recent link training changes
that Manasi has implemented, and PSR on Skylake is definitely more happy
with these changes in-place.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Mika Kahola <mika.kahola@intel.com>
Fixes: 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c               |  4 +++-
 drivers/gpu/drm/i915/intel_dp_link_training.c | 11 ++++++++++-
 drivers/gpu/drm/i915/intel_drv.h              |  2 ++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d46f72d..06b8bd4 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -106,7 +106,7 @@ static const int default_rates[] = { 162000, 270000, 540000 };
  * If a CPU or PCH DP output is attached to an eDP panel, this function
  * will return true, and false otherwise.
  */
-static bool is_edp(struct intel_dp *intel_dp)
+bool is_edp(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 
@@ -4690,6 +4690,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 		intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
 
 		intel_dp->reset_link_params = false;
+		intel_dp->train_set_valid = false;
 	}
 
 	intel_dp_print_rates(intel_dp);
@@ -6052,6 +6053,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	intel_dp_set_source_rates(intel_dp);
 
 	intel_dp->reset_link_params = true;
+	intel_dp->train_set_valid = false;
 	intel_dp->pps_pipe = INVALID_PIPE;
 	intel_dp->active_pipe = INVALID_PIPE;
 
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
index b79c1c0..60233e2 100644
--- a/drivers/gpu/drm/i915/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
@@ -94,7 +94,8 @@ static bool
 intel_dp_reset_link_train(struct intel_dp *intel_dp,
 			uint8_t dp_train_pat)
 {
-	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+	if (!intel_dp->train_set_valid)
+		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
 	intel_dp_set_signal_levels(intel_dp);
 	return intel_dp_set_link_train(intel_dp, dp_train_pat);
 }
@@ -162,6 +163,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 				       DP_TRAINING_PATTERN_1 |
 				       DP_LINK_SCRAMBLING_DISABLE)) {
 		DRM_ERROR("failed to enable link training\n");
+		intel_dp->train_set_valid = false;
 		return false;
 	}
 
@@ -174,21 +176,25 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 
 		if (!intel_dp_get_link_status(intel_dp, link_status)) {
 			DRM_ERROR("failed to get link status\n");
+			intel_dp->train_set_valid = false;
 			return false;
 		}
 
 		if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			DRM_DEBUG_KMS("clock recovery OK\n");
+			intel_dp->train_set_valid = is_edp(intel_dp);
 			return true;
 		}
 
 		if (voltage_tries == 5) {
 			DRM_DEBUG_KMS("Same voltage tried 5 times\n");
+			intel_dp->train_set_valid = false;
 			return false;
 		}
 
 		if (max_vswing_tries == 1) {
 			DRM_DEBUG_KMS("Max Voltage Swing reached\n");
+			intel_dp->train_set_valid = false;
 			return false;
 		}
 
@@ -198,6 +204,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		intel_get_adjust_train(intel_dp, link_status);
 		if (!intel_dp_update_link_train(intel_dp)) {
 			DRM_ERROR("failed to update link training\n");
+			intel_dp->train_set_valid = false;
 			return false;
 		}
 
@@ -256,6 +263,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 				     training_pattern |
 				     DP_LINK_SCRAMBLING_DISABLE)) {
 		DRM_ERROR("failed to start channel equalization\n");
+		intel_dp->train_set_valid = false;
 		return false;
 	}
 
@@ -296,6 +304,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 	/* Try 5 times, else fail and try at lower BW */
 	if (tries == 5) {
 		intel_dp_dump_link_status(link_status);
+		intel_dp->train_set_valid = false;
 		DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 19d0c8f..149d4c9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -977,6 +977,7 @@ struct intel_dp {
 	struct drm_dp_aux aux;
 	enum intel_display_power_domain aux_power_domain;
 	uint8_t train_set[4];
+	bool train_set_valid;
 	int panel_power_up_delay;
 	int panel_power_down_delay;
 	int panel_power_cycle_delay;
@@ -1551,6 +1552,7 @@ bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
 bool __intel_dp_read_desc(struct intel_dp *intel_dp,
 			  struct intel_dp_desc *desc);
 bool intel_dp_read_desc(struct intel_dp *intel_dp);
+bool is_edp(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
 bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
-- 
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] 16+ messages in thread

* [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels
  2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
                   ` (2 preceding siblings ...)
  2017-05-05 21:02 ` [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP Jim Bride
@ 2017-05-05 21:02 ` Jim Bride
  2017-05-08  9:12   ` Jani Nikula
  2017-05-05 21:20 ` ✓ Fi.CI.BAT: success for Kernel PSR Fix-ups Patchwork
  4 siblings, 1 reply; 16+ messages in thread
From: Jim Bride @ 2017-05-05 21:02 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

According to the eDP spec, when the count field in TEST_SINK_MISC
increments then the six bytes of sink CRC information in the DPCD
should be valid.  Unfortunately, this doesn't seem to be the case
on some panels, and as a result we get some incorrect and inconsistent
values from the sink CRC DPCD locations at times.  This problem exhibits
itself more on faster processors (relative failure rates HSW < SKL < KBL.)
In order to try and account for this, we try a lot harder to read the sink
CRC until we get consistent values twice in a row before returning what we
read and delay for a time before trying to read.  We still see some
occasional failures, but reading the sink CRC is much more reliable,
particularly on SKL and KBL, with these changes than without.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++--
 drivers/gpu/drm/i915/intel_dp.c     | 57 ++++++++++++++++++++++++++++++++-----
 2 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 870c470..4902473 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2718,7 +2718,7 @@ static int i915_sink_crc(struct seq_file *m, void *data)
 	struct intel_connector *connector;
 	struct drm_connector_list_iter conn_iter;
 	struct intel_dp *intel_dp = NULL;
-	int ret;
+	int ret, tries = 6;
 	u8 crc[6];
 
 	drm_modeset_lock_all(dev);
@@ -2738,9 +2738,17 @@ static int i915_sink_crc(struct seq_file *m, void *data)
 
 		intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
 
-		ret = intel_dp_sink_crc(intel_dp, crc);
-		if (ret)
+		memset(crc, 0, 6);
+		do {
+			ret = intel_dp_sink_crc(intel_dp, crc);
+			if (ret == -ETIMEDOUT)
+				usleep_range(500, 700);
+		} while ((ret == -ETIMEDOUT) && --tries);
+
+		if (ret != 0) {
+			seq_printf(m, "000000000000\n");
 			goto out;
+		}
 
 		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
 			   crc[0], crc[1], crc[2],
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 06b8bd4..217bc06 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3877,13 +3877,15 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
 
 	do {
 		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
-
+		usleep_range(16700, 17000);
 		if (drm_dp_dpcd_readb(&intel_dp->aux,
 				      DP_TEST_SINK_MISC, &buf) < 0) {
+			DRM_DEBUG_KMS("Could not read TEST_SINK_MISC\n");
 			ret = -EIO;
 			goto out;
 		}
 		count = buf & DP_TEST_COUNT_MASK;
+		DRM_DEBUG_KMS("PSR count is %d\n", count);
 	} while (--attempts && count);
 
 	if (attempts == 0) {
@@ -3928,6 +3930,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
 	}
 
 	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+	usleep_range(16700, 17000);
+	DRM_DEBUG_KMS("PSR Successfully started sink CRC\n");
 	return 0;
 }
 
@@ -3939,21 +3943,30 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 	u8 buf;
 	int count, ret;
 	int attempts = 6;
+	u8 old_crc[6];
+
+	if (crc != NULL)
+		memset(crc, 0, 6);
+	else
+		return -ENOMEM;
 
 	ret = intel_dp_sink_crc_start(intel_dp);
-	if (ret)
+	if (ret) {
+		DRM_DEBUG_KMS("Could not start sink crc; ret %d\n", ret);
 		return ret;
+	}
 
 	do {
 		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+		usleep_range(16700, 17000);
 
 		if (drm_dp_dpcd_readb(&intel_dp->aux,
 				      DP_TEST_SINK_MISC, &buf) < 0) {
+			DRM_DEBUG_KMS("Cound not read TEST_SINK_MISC\n");
 			ret = -EIO;
 			goto stop;
 		}
 		count = buf & DP_TEST_COUNT_MASK;
-
 	} while (--attempts && count == 0);
 
 	if (attempts == 0) {
@@ -3962,11 +3975,41 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 		goto stop;
 	}
 
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
-		ret = -EIO;
-		goto stop;
-	}
+	attempts = 6;
+	memset(old_crc, 0xFF, 6);
+	do {
+		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
+		usleep_range(16500, 17000);
+		if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR,
+				     crc, 6) < 0) {
+			DRM_DEBUG_KMS("Could not read sink crc\n");
+			ret = -EIO;
+			goto stop;
+		}
+
+		if (memcmp(old_crc, crc, 6) == 0) {
+			DRM_DEBUG_KMS("PSR Active: %3s Matching crc values found:"
+				      "%02x%02x%02x%02x%02x%02x\n",
+				      yesno(dev_priv->psr.active),
+				      crc[0], crc[1], crc[2],
+				      crc[3], crc[4], crc[5]);
+			ret = 0;
+			goto stop;
+		} else {
+			DRM_DEBUG_KMS("PSR Active: %3s crc %02x%02x%02x%02x%02x%02x "
+				      "doesn't match "
+				      "previous %02x%02x%02x%02x%02x%02x\n",
+				      yesno(dev_priv->psr.active),
+				      crc[0], crc[1], crc[2],
+				      crc[3], crc[4], crc[5],
+				      old_crc[0], old_crc[1], old_crc[2],
+				      old_crc[3], old_crc[4], old_crc[5]);
+			memcpy(old_crc, crc, 6);
+		}
+	} while (--attempts);
 
+	DRM_DEBUG_KMS("Failed to get CRC after 6 attempts.\n");
+	ret = -ETIMEDOUT;
 stop:
 	intel_dp_sink_crc_stop(intel_dp);
 	return ret;
-- 
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] 16+ messages in thread

* ✓ Fi.CI.BAT: success for Kernel PSR Fix-ups
  2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
                   ` (3 preceding siblings ...)
  2017-05-05 21:02 ` [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels Jim Bride
@ 2017-05-05 21:20 ` Patchwork
  4 siblings, 0 replies; 16+ messages in thread
From: Patchwork @ 2017-05-05 21:20 UTC (permalink / raw)
  To: jim.bride; +Cc: intel-gfx

== Series Details ==

Series: Kernel PSR Fix-ups
URL   : https://patchwork.freedesktop.org/series/24049/
State : success

== Summary ==

Series 24049v1 Kernel PSR Fix-ups
https://patchwork.freedesktop.org/api/1.0/series/24049/revisions/1/mbox/

Test gem_exec_flush:
        Subgroup basic-batch-kernel-default-uc:
                fail       -> PASS       (fi-snb-2600) fdo#100007

fdo#100007 https://bugs.freedesktop.org/show_bug.cgi?id=100007

fi-bdw-5557u     total:278  pass:267  dwarn:0   dfail:0   fail:0   skip:11  time:432s
fi-bdw-gvtdvm    total:278  pass:256  dwarn:8   dfail:0   fail:0   skip:14  time:427s
fi-bxt-j4205     total:278  pass:259  dwarn:0   dfail:0   fail:0   skip:19  time:508s
fi-bxt-t5700     total:278  pass:258  dwarn:0   dfail:0   fail:0   skip:20  time:531s
fi-byt-j1900     total:278  pass:254  dwarn:0   dfail:0   fail:0   skip:24  time:489s
fi-byt-n2820     total:278  pass:250  dwarn:0   dfail:0   fail:0   skip:28  time:488s
fi-hsw-4770      total:278  pass:262  dwarn:0   dfail:0   fail:0   skip:16  time:410s
fi-hsw-4770r     total:278  pass:262  dwarn:0   dfail:0   fail:0   skip:16  time:413s
fi-ilk-650       total:278  pass:228  dwarn:0   dfail:0   fail:0   skip:50  time:416s
fi-ivb-3520m     total:278  pass:260  dwarn:0   dfail:0   fail:0   skip:18  time:480s
fi-ivb-3770      total:278  pass:260  dwarn:0   dfail:0   fail:0   skip:18  time:476s
fi-kbl-7500u     total:278  pass:260  dwarn:0   dfail:0   fail:0   skip:18  time:456s
fi-kbl-7560u     total:278  pass:267  dwarn:1   dfail:0   fail:0   skip:10  time:577s
fi-skl-6260u     total:278  pass:268  dwarn:0   dfail:0   fail:0   skip:10  time:456s
fi-skl-6700k     total:278  pass:256  dwarn:4   dfail:0   fail:0   skip:18  time:456s
fi-skl-6770hq    total:278  pass:268  dwarn:0   dfail:0   fail:0   skip:10  time:489s
fi-skl-gvtdvm    total:278  pass:265  dwarn:0   dfail:0   fail:0   skip:13  time:428s
fi-snb-2520m     total:278  pass:250  dwarn:0   dfail:0   fail:0   skip:28  time:527s
fi-snb-2600      total:278  pass:249  dwarn:0   dfail:0   fail:0   skip:29  time:402s
fi-bsw-n3050 failed to collect. IGT log at Patchwork_4633/fi-bsw-n3050/igt.log

fb550f86433515f36a0de161631541ec114581e3 drm-tip: 2017y-05m-05d-18h-33m-52s UTC integration manifest
46a8d3e drm/i915/psr: Account for sink CRC raciness on some panels
829bb88 drm/i915/edp: Be less aggressive about changing link config on eDP
a1d3407 drm/i915/psr: Clean-up intel_enable_source_psr1()
b74b07c drm/i915/edp: Allow alternate fixed mode for eDP if available.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_4633/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP
  2017-05-05 21:02 ` [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP Jim Bride
@ 2017-05-08  8:41   ` Jani Nikula
  2017-05-08 16:59     ` Jim Bride
  2017-05-08 13:07   ` Mika Kahola
  1 sibling, 1 reply; 16+ messages in thread
From: Jani Nikula @ 2017-05-08  8:41 UTC (permalink / raw)
  To: Jim Bride, intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> This set of changes has some history to them.  There were several attempts
> to add what was called "fast link training" to i915, which actually wasn't
> fast link training as per the DP spec.  These changes were
>
> 5fa836a9d859 ("drm/i915: DP link training optimization")
> 4e96c97742f4 ("drm/i915: eDP link training optimization")
>
> which were eventually hand-reverted by
>
> 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
>
> in kernel 4.7-rc4.  The eDP pieces of the above revert, however, had some
> very bad side-effects on PSR functionality on Skylake. The issue at
> hand is that when PSR exits i915 briefly emits TP1 followed by TP2/3
> (depending on the original link configuration) in order to quickly get
> the source and sink back in synchronization across the link before handing
> control back to the i915.  There's an assumption that none of the link
> configuration information has changed (and thus it's still valid) since the
> last full link training operation.  The revert above was identified via a
> bisect as the cause of some of Skylake's PSR woes.  This patch, largely
> based on
>
> commit 4e96c97742f4201edf1b0f8e1b1b6b2ac6ff33e7
> Author: Mika Kahola <mika.kahola@intel.com>
> Date:   Wed Apr 29 09:17:39 2015 +0300
> drm/i915: eDP link training optimization
>
> puts the eDP portions of this patch back in place.  None of the flickering
> issues that spurred the revert have been seen, and I suspect the real
> culprits here were addressed by some of the recent link training changes
> that Manasi has implemented, and PSR on Skylake is definitely more happy
> with these changes in-place.

I'm weary of all the back and forth wrt PSR and DP, and wary of creating
new ones. Would it make sense to restrict this patch to PSR?

BR,
Jani.


>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Mika Kahola <mika.kahola@intel.com>
> Fixes: 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
> Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c               |  4 +++-
>  drivers/gpu/drm/i915/intel_dp_link_training.c | 11 ++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h              |  2 ++
>  3 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d46f72d..06b8bd4 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -106,7 +106,7 @@ static const int default_rates[] = { 162000, 270000, 540000 };
>   * If a CPU or PCH DP output is attached to an eDP panel, this function
>   * will return true, and false otherwise.
>   */
> -static bool is_edp(struct intel_dp *intel_dp)
> +bool is_edp(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  
> @@ -4690,6 +4690,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
>  		intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
>  
>  		intel_dp->reset_link_params = false;
> +		intel_dp->train_set_valid = false;
>  	}
>  
>  	intel_dp_print_rates(intel_dp);
> @@ -6052,6 +6053,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	intel_dp_set_source_rates(intel_dp);
>  
>  	intel_dp->reset_link_params = true;
> +	intel_dp->train_set_valid = false;
>  	intel_dp->pps_pipe = INVALID_PIPE;
>  	intel_dp->active_pipe = INVALID_PIPE;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
> index b79c1c0..60233e2 100644
> --- a/drivers/gpu/drm/i915/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
> @@ -94,7 +94,8 @@ static bool
>  intel_dp_reset_link_train(struct intel_dp *intel_dp,
>  			uint8_t dp_train_pat)
>  {
> -	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
> +	if (!intel_dp->train_set_valid)
> +		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
>  	intel_dp_set_signal_levels(intel_dp);
>  	return intel_dp_set_link_train(intel_dp, dp_train_pat);
>  }
> @@ -162,6 +163,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
>  				       DP_TRAINING_PATTERN_1 |
>  				       DP_LINK_SCRAMBLING_DISABLE)) {
>  		DRM_ERROR("failed to enable link training\n");
> +		intel_dp->train_set_valid = false;
>  		return false;
>  	}
>  
> @@ -174,21 +176,25 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
>  
>  		if (!intel_dp_get_link_status(intel_dp, link_status)) {
>  			DRM_ERROR("failed to get link status\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
>  		if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
>  			DRM_DEBUG_KMS("clock recovery OK\n");
> +			intel_dp->train_set_valid = is_edp(intel_dp);
>  			return true;
>  		}
>  
>  		if (voltage_tries == 5) {
>  			DRM_DEBUG_KMS("Same voltage tried 5 times\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
>  		if (max_vswing_tries == 1) {
>  			DRM_DEBUG_KMS("Max Voltage Swing reached\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
> @@ -198,6 +204,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
>  		intel_get_adjust_train(intel_dp, link_status);
>  		if (!intel_dp_update_link_train(intel_dp)) {
>  			DRM_ERROR("failed to update link training\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
> @@ -256,6 +263,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
>  				     training_pattern |
>  				     DP_LINK_SCRAMBLING_DISABLE)) {
>  		DRM_ERROR("failed to start channel equalization\n");
> +		intel_dp->train_set_valid = false;
>  		return false;
>  	}
>  
> @@ -296,6 +304,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
>  	/* Try 5 times, else fail and try at lower BW */
>  	if (tries == 5) {
>  		intel_dp_dump_link_status(link_status);
> +		intel_dp->train_set_valid = false;
>  		DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 19d0c8f..149d4c9 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -977,6 +977,7 @@ struct intel_dp {
>  	struct drm_dp_aux aux;
>  	enum intel_display_power_domain aux_power_domain;
>  	uint8_t train_set[4];
> +	bool train_set_valid;
>  	int panel_power_up_delay;
>  	int panel_power_down_delay;
>  	int panel_power_cycle_delay;
> @@ -1551,6 +1552,7 @@ bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
>  bool __intel_dp_read_desc(struct intel_dp *intel_dp,
>  			  struct intel_dp_desc *desc);
>  bool intel_dp_read_desc(struct intel_dp *intel_dp);
> +bool is_edp(struct intel_dp *intel_dp);
>  int intel_dp_link_required(int pixel_clock, int bpp);
>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>  bool intel_digital_port_connected(struct drm_i915_private *dev_priv,

-- 
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] 16+ messages in thread

* Re: [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available.
  2017-05-05 21:02 ` [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available Jim Bride
@ 2017-05-08  8:54   ` Jani Nikula
  2017-05-08 16:52     ` Jim Bride
  0 siblings, 1 reply; 16+ messages in thread
From: Jani Nikula @ 2017-05-08  8:54 UTC (permalink / raw)
  To: Jim Bride, intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> Some fixed resolution panels actually support more than one mode,
> with the only thing different being the refresh rate.  Having this
> alternate mode available to us is desirable, because it allows us to
> test PSR on panels whose setup time at the preferred mode is too long.
> With this patch we allow the use of the alternate mode if it's
> available and it was specifically requested.

All in all this feels like a hack. The generic solution would be to
allow any mode to be set again.

A few specific comments inline.

BR,
Jani.

> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c    | 34 +++++++++++++++++++++++++++++-----
>  drivers/gpu/drm/i915/intel_drv.h   |  2 ++
>  drivers/gpu/drm/i915/intel_dsi.c   |  2 +-
>  drivers/gpu/drm/i915/intel_dvo.c   |  2 +-
>  drivers/gpu/drm/i915/intel_lvds.c  |  3 ++-
>  drivers/gpu/drm/i915/intel_panel.c |  2 ++
>  6 files changed, 37 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 08834f7..d46f72d 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1637,6 +1637,19 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
>  	return bpp;
>  }
>  
> +static bool intel_edp_compare_alt_mode(struct drm_display_mode *m1,
> +				       struct drm_display_mode *m2)
> +{
> +	return (m1->hdisplay == m2->hdisplay &&
> +		m1->hsync_start == m2->hsync_start &&
> +		m1->hsync_end == m2->hsync_end &&
> +		m1->htotal == m2->htotal &&
> +		m1->vdisplay == m2->vdisplay &&
> +		m1->vsync_start == m2->vsync_start &&
> +		m1->vsync_end == m2->vsync_end &&
> +		m1->vtotal == m2->vtotal);
> +}

See drm_mode_equal and friends.

> +
>  bool
>  intel_dp_compute_config(struct intel_encoder *encoder,
>  			struct intel_crtc_state *pipe_config,
> @@ -1674,8 +1687,16 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>  	pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;
>  
>  	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
> -		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
> -				       adjusted_mode);
> +		struct drm_display_mode *panel_mode =
> +			intel_connector->panel.alt_fixed_mode;
> +		struct drm_display_mode *req_mode = &pipe_config->base.mode;
> +
> +		if (!intel_edp_compare_alt_mode(req_mode, panel_mode))
> +			panel_mode = intel_connector->panel.fixed_mode;
> +
> +		drm_mode_debug_printmodeline(panel_mode);
> +
> +		intel_fixed_panel_mode(panel_mode, adjusted_mode);
>  
>  		if (INTEL_GEN(dev_priv) >= 9) {
>  			int ret;
> @@ -5829,6 +5850,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	struct drm_device *dev = intel_encoder->base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct drm_display_mode *fixed_mode = NULL;
> +	struct drm_display_mode *alt_fixed_mode = NULL;
>  	struct drm_display_mode *downclock_mode = NULL;
>  	bool has_dpcd;
>  	struct drm_display_mode *scan;
> @@ -5884,13 +5906,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	}
>  	intel_connector->edid = edid;
>  
> -	/* prefer fixed mode from EDID if available */
> +	/* prefer fixed mode from EDID if available, save an alt mode also */
>  	list_for_each_entry(scan, &connector->probed_modes, head) {
>  		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
>  			fixed_mode = drm_mode_duplicate(dev, scan);
>  			downclock_mode = intel_dp_drrs_init(
>  						intel_connector, fixed_mode);
> -			break;
> +		} else {
> +			alt_fixed_mode = drm_mode_duplicate(dev, scan);
>  		}

This changes the fixed mode if there are more than one preferred
mode. This will also leak all but the two modes.

>  	}
>  
> @@ -5927,7 +5950,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  			      pipe_name(pipe));
>  	}
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, alt_fixed_mode,
> +			 downclock_mode);
>  	intel_connector->panel.backlight.power = intel_edp_backlight_power;
>  	intel_panel_setup_backlight(connector, pipe);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 54f3ff8..19d0c8f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -265,6 +265,7 @@ struct intel_encoder {
>  
>  struct intel_panel {
>  	struct drm_display_mode *fixed_mode;
> +	struct drm_display_mode *alt_fixed_mode;
>  	struct drm_display_mode *downclock_mode;
>  	int fitting_mode;
>  
> @@ -1676,6 +1677,7 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
>  /* intel_panel.c */
>  int intel_panel_init(struct intel_panel *panel,
>  		     struct drm_display_mode *fixed_mode,
> +		     struct drm_display_mode *alt_fixed_mode,
>  		     struct drm_display_mode *downclock_mode);
>  void intel_panel_fini(struct intel_panel *panel);
>  void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> index fc0ef49..a938f08 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -1852,7 +1852,7 @@ void intel_dsi_init(struct drm_i915_private *dev_priv)
>  	connector->display_info.width_mm = fixed_mode->width_mm;
>  	connector->display_info.height_mm = fixed_mode->height_mm;
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL, NULL);
>  	intel_panel_setup_backlight(connector, INVALID_PIPE);
>  
>  	intel_dsi_add_properties(intel_connector);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index c1544a5..39fd4f3 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -554,7 +554,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
>  			 */
>  			intel_panel_init(&intel_connector->panel,
>  					 intel_dvo_get_current_mode(connector),
> -					 NULL);
> +					 NULL, NULL);
>  			intel_dvo->panel_wants_dither = true;
>  		}
>  
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 8b942ef..b1e6743 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -1181,7 +1181,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
>  out:
>  	mutex_unlock(&dev->mode_config.mutex);
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
> +			 downclock_mode);
>  	intel_panel_setup_backlight(connector, INVALID_PIPE);
>  
>  	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index cb50c52..41eb7b0 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1801,11 +1801,13 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
>  
>  int intel_panel_init(struct intel_panel *panel,
>  		     struct drm_display_mode *fixed_mode,
> +		     struct drm_display_mode *alt_fixed_mode,
>  		     struct drm_display_mode *downclock_mode)
>  {
>  	intel_panel_init_backlight_funcs(panel);
>  
>  	panel->fixed_mode = fixed_mode;
> +	panel->alt_fixed_mode = alt_fixed_mode;
>  	panel->downclock_mode = downclock_mode;
>  
>  	return 0;

-- 
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] 16+ messages in thread

* Re: [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels
  2017-05-05 21:02 ` [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels Jim Bride
@ 2017-05-08  9:12   ` Jani Nikula
  2017-05-08 17:29     ` Jim Bride
  0 siblings, 1 reply; 16+ messages in thread
From: Jani Nikula @ 2017-05-08  9:12 UTC (permalink / raw)
  To: Jim Bride, intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> According to the eDP spec, when the count field in TEST_SINK_MISC
> increments then the six bytes of sink CRC information in the DPCD
> should be valid.  Unfortunately, this doesn't seem to be the case
> on some panels, and as a result we get some incorrect and inconsistent
> values from the sink CRC DPCD locations at times.  This problem exhibits
> itself more on faster processors (relative failure rates HSW < SKL < KBL.)
> In order to try and account for this, we try a lot harder to read the sink
> CRC until we get consistent values twice in a row before returning what we
> read and delay for a time before trying to read.  We still see some
> occasional failures, but reading the sink CRC is much more reliable,
> particularly on SKL and KBL, with these changes than without.

Retrying seems like a good idea. But this patch retries up to 36 times
if the two consecutive reads don't match, which is excessive.

The sleeps should probably be a separate change. Also not happy about
the magic numbers there.

Also, there are plenty of what seem like unrelated changes. Whitespace,
debug logging, error checking, etc.


BR,
Jani.


>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++--
>  drivers/gpu/drm/i915/intel_dp.c     | 57 ++++++++++++++++++++++++++++++++-----
>  2 files changed, 61 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 870c470..4902473 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2718,7 +2718,7 @@ static int i915_sink_crc(struct seq_file *m, void *data)
>  	struct intel_connector *connector;
>  	struct drm_connector_list_iter conn_iter;
>  	struct intel_dp *intel_dp = NULL;
> -	int ret;
> +	int ret, tries = 6;
>  	u8 crc[6];
>  
>  	drm_modeset_lock_all(dev);
> @@ -2738,9 +2738,17 @@ static int i915_sink_crc(struct seq_file *m, void *data)
>  
>  		intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
>  
> -		ret = intel_dp_sink_crc(intel_dp, crc);
> -		if (ret)
> +		memset(crc, 0, 6);
> +		do {
> +			ret = intel_dp_sink_crc(intel_dp, crc);
> +			if (ret == -ETIMEDOUT)
> +				usleep_range(500, 700);
> +		} while ((ret == -ETIMEDOUT) && --tries);
> +
> +		if (ret != 0) {
> +			seq_printf(m, "000000000000\n");
>  			goto out;
> +		}
>  
>  		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
>  			   crc[0], crc[1], crc[2],
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 06b8bd4..217bc06 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3877,13 +3877,15 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
>  
>  	do {
>  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> -
> +		usleep_range(16700, 17000);
>  		if (drm_dp_dpcd_readb(&intel_dp->aux,
>  				      DP_TEST_SINK_MISC, &buf) < 0) {
> +			DRM_DEBUG_KMS("Could not read TEST_SINK_MISC\n");
>  			ret = -EIO;
>  			goto out;
>  		}
>  		count = buf & DP_TEST_COUNT_MASK;
> +		DRM_DEBUG_KMS("PSR count is %d\n", count);
>  	} while (--attempts && count);
>  
>  	if (attempts == 0) {
> @@ -3928,6 +3930,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
>  	}
>  
>  	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> +	usleep_range(16700, 17000);
> +	DRM_DEBUG_KMS("PSR Successfully started sink CRC\n");
>  	return 0;
>  }
>  
> @@ -3939,21 +3943,30 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
>  	u8 buf;
>  	int count, ret;
>  	int attempts = 6;
> +	u8 old_crc[6];
> +
> +	if (crc != NULL)
> +		memset(crc, 0, 6);
> +	else
> +		return -ENOMEM;
>  
>  	ret = intel_dp_sink_crc_start(intel_dp);
> -	if (ret)
> +	if (ret) {
> +		DRM_DEBUG_KMS("Could not start sink crc; ret %d\n", ret);
>  		return ret;
> +	}
>  
>  	do {
>  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> +		usleep_range(16700, 17000);
>  
>  		if (drm_dp_dpcd_readb(&intel_dp->aux,
>  				      DP_TEST_SINK_MISC, &buf) < 0) {
> +			DRM_DEBUG_KMS("Cound not read TEST_SINK_MISC\n");
>  			ret = -EIO;
>  			goto stop;
>  		}
>  		count = buf & DP_TEST_COUNT_MASK;
> -
>  	} while (--attempts && count == 0);
>  
>  	if (attempts == 0) {
> @@ -3962,11 +3975,41 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
>  		goto stop;
>  	}
>  
> -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
> -		ret = -EIO;
> -		goto stop;
> -	}
> +	attempts = 6;
> +	memset(old_crc, 0xFF, 6);
> +	do {
> +		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> +		usleep_range(16500, 17000);
> +		if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR,
> +				     crc, 6) < 0) {
> +			DRM_DEBUG_KMS("Could not read sink crc\n");
> +			ret = -EIO;
> +			goto stop;
> +		}
> +
> +		if (memcmp(old_crc, crc, 6) == 0) {
> +			DRM_DEBUG_KMS("PSR Active: %3s Matching crc values found:"
> +				      "%02x%02x%02x%02x%02x%02x\n",
> +				      yesno(dev_priv->psr.active),
> +				      crc[0], crc[1], crc[2],
> +				      crc[3], crc[4], crc[5]);
> +			ret = 0;
> +			goto stop;
> +		} else {
> +			DRM_DEBUG_KMS("PSR Active: %3s crc %02x%02x%02x%02x%02x%02x "
> +				      "doesn't match "
> +				      "previous %02x%02x%02x%02x%02x%02x\n",
> +				      yesno(dev_priv->psr.active),
> +				      crc[0], crc[1], crc[2],
> +				      crc[3], crc[4], crc[5],
> +				      old_crc[0], old_crc[1], old_crc[2],
> +				      old_crc[3], old_crc[4], old_crc[5]);
> +			memcpy(old_crc, crc, 6);
> +		}
> +	} while (--attempts);
>  
> +	DRM_DEBUG_KMS("Failed to get CRC after 6 attempts.\n");
> +	ret = -ETIMEDOUT;
>  stop:
>  	intel_dp_sink_crc_stop(intel_dp);
>  	return ret;

-- 
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] 16+ messages in thread

* Re: [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP
  2017-05-05 21:02 ` [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP Jim Bride
  2017-05-08  8:41   ` Jani Nikula
@ 2017-05-08 13:07   ` Mika Kahola
  1 sibling, 0 replies; 16+ messages in thread
From: Mika Kahola @ 2017-05-08 13:07 UTC (permalink / raw)
  To: Jim Bride, intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

On Fri, 2017-05-05 at 14:02 -0700, Jim Bride wrote:
> This set of changes has some history to them.  There were several
> attempts
> to add what was called "fast link training" to i915, which actually
> wasn't
> fast link training as per the DP spec.  These changes were
> 
> 5fa836a9d859 ("drm/i915: DP link training optimization")
> 4e96c97742f4 ("drm/i915: eDP link training optimization")
> 
> which were eventually hand-reverted by
> 
> 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
> 
> in kernel 4.7-rc4.  The eDP pieces of the above revert, however, had
> some
> very bad side-effects on PSR functionality on Skylake. The issue at
> hand is that when PSR exits i915 briefly emits TP1 followed by TP2/3
> (depending on the original link configuration) in order to quickly
> get
> the source and sink back in synchronization across the link before
> handing
> control back to the i915.  There's an assumption that none of the
> link
> configuration information has changed (and thus it's still valid)
> since the
> last full link training operation.  The revert above was identified
> via a
> bisect as the cause of some of Skylake's PSR woes.  This patch,
> largely
> based on
> 
> commit 4e96c97742f4201edf1b0f8e1b1b6b2ac6ff33e7
> Author: Mika Kahola <mika.kahola@intel.com>
> Date:   Wed Apr 29 09:17:39 2015 +0300
> drm/i915: eDP link training optimization
> 
> puts the eDP portions of this patch back in place.  None of the
> flickering
> issues that spurred the revert have been seen, and I suspect the real
> culprits here were addressed by some of the recent link training
> changes
> that Manasi has implemented, and PSR on Skylake is definitely more
> happy
> with these changes in-place.
We reverted this back in the day due to bug reports we received from
the community concerning flickering. However, you have to remember that
during that time also the watermark work was ongoing. We couldn't
pinpoint one issue or root cause that triggered these reported
flickering cases. Therefore we decided to revert these optimizations.
Personally, I feel that this would have been safe for eDP case.

Acked-by: Mika Kahola <mika.kahola@intel.com>

> 
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Manasi D Navare <manasi.d.navare@intel.com>
> Cc: Mika Kahola <mika.kahola@intel.com>
> Fixes: 34511dce4 ("drm/i915: Revert DisplayPort fast link training
> feature")
> Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c               |  4 +++-
>  drivers/gpu/drm/i915/intel_dp_link_training.c | 11 ++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h              |  2 ++
>  3 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c
> b/drivers/gpu/drm/i915/intel_dp.c
> index d46f72d..06b8bd4 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -106,7 +106,7 @@ static const int default_rates[] = { 162000,
> 270000, 540000 };
>   * If a CPU or PCH DP output is attached to an eDP panel, this
> function
>   * will return true, and false otherwise.
>   */
> -static bool is_edp(struct intel_dp *intel_dp)
> +bool is_edp(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port =
> dp_to_dig_port(intel_dp);
>  
> @@ -4690,6 +4690,7 @@ intel_dp_long_pulse(struct intel_connector
> *intel_connector)
>  		intel_dp->max_link_rate =
> intel_dp_max_common_rate(intel_dp);
>  
>  		intel_dp->reset_link_params = false;
> +		intel_dp->train_set_valid = false;
>  	}
>  
>  	intel_dp_print_rates(intel_dp);
> @@ -6052,6 +6053,7 @@ intel_dp_init_connector(struct
> intel_digital_port *intel_dig_port,
>  	intel_dp_set_source_rates(intel_dp);
>  
>  	intel_dp->reset_link_params = true;
> +	intel_dp->train_set_valid = false;
>  	intel_dp->pps_pipe = INVALID_PIPE;
>  	intel_dp->active_pipe = INVALID_PIPE;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c
> b/drivers/gpu/drm/i915/intel_dp_link_training.c
> index b79c1c0..60233e2 100644
> --- a/drivers/gpu/drm/i915/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
> @@ -94,7 +94,8 @@ static bool
>  intel_dp_reset_link_train(struct intel_dp *intel_dp,
>  			uint8_t dp_train_pat)
>  {
> -	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
> +	if (!intel_dp->train_set_valid)
> +		memset(intel_dp->train_set, 0, sizeof(intel_dp-
> >train_set));
>  	intel_dp_set_signal_levels(intel_dp);
>  	return intel_dp_set_link_train(intel_dp, dp_train_pat);
>  }
> @@ -162,6 +163,7 @@ intel_dp_link_training_clock_recovery(struct
> intel_dp *intel_dp)
>  				       DP_TRAINING_PATTERN_1 |
>  				       DP_LINK_SCRAMBLING_DISABLE))
> {
>  		DRM_ERROR("failed to enable link training\n");
> +		intel_dp->train_set_valid = false;
>  		return false;
>  	}
>  
> @@ -174,21 +176,25 @@ intel_dp_link_training_clock_recovery(struct
> intel_dp *intel_dp)
>  
>  		if (!intel_dp_get_link_status(intel_dp,
> link_status)) {
>  			DRM_ERROR("failed to get link status\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
>  		if (drm_dp_clock_recovery_ok(link_status, intel_dp-
> >lane_count)) {
>  			DRM_DEBUG_KMS("clock recovery OK\n");
> +			intel_dp->train_set_valid =
> is_edp(intel_dp);
>  			return true;
>  		}
>  
>  		if (voltage_tries == 5) {
>  			DRM_DEBUG_KMS("Same voltage tried 5
> times\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
>  		if (max_vswing_tries == 1) {
>  			DRM_DEBUG_KMS("Max Voltage Swing
> reached\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
> @@ -198,6 +204,7 @@ intel_dp_link_training_clock_recovery(struct
> intel_dp *intel_dp)
>  		intel_get_adjust_train(intel_dp, link_status);
>  		if (!intel_dp_update_link_train(intel_dp)) {
>  			DRM_ERROR("failed to update link
> training\n");
> +			intel_dp->train_set_valid = false;
>  			return false;
>  		}
>  
> @@ -256,6 +263,7 @@
> intel_dp_link_training_channel_equalization(struct intel_dp
> *intel_dp)
>  				     training_pattern |
>  				     DP_LINK_SCRAMBLING_DISABLE)) {
>  		DRM_ERROR("failed to start channel equalization\n");
> +		intel_dp->train_set_valid = false;
>  		return false;
>  	}
>  
> @@ -296,6 +304,7 @@
> intel_dp_link_training_channel_equalization(struct intel_dp
> *intel_dp)
>  	/* Try 5 times, else fail and try at lower BW */
>  	if (tries == 5) {
>  		intel_dp_dump_link_status(link_status);
> +		intel_dp->train_set_valid = false;
>  		DRM_DEBUG_KMS("Channel equalization failed 5
> times\n");
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 19d0c8f..149d4c9 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -977,6 +977,7 @@ struct intel_dp {
>  	struct drm_dp_aux aux;
>  	enum intel_display_power_domain aux_power_domain;
>  	uint8_t train_set[4];
> +	bool train_set_valid;
>  	int panel_power_up_delay;
>  	int panel_power_down_delay;
>  	int panel_power_cycle_delay;
> @@ -1551,6 +1552,7 @@ bool intel_dp_read_dpcd(struct intel_dp
> *intel_dp);
>  bool __intel_dp_read_desc(struct intel_dp *intel_dp,
>  			  struct intel_dp_desc *desc);
>  bool intel_dp_read_desc(struct intel_dp *intel_dp);
> +bool is_edp(struct intel_dp *intel_dp);
>  int intel_dp_link_required(int pixel_clock, int bpp);
>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>  bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
-- 
Mika Kahola - Intel OTC

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

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

* Re: [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available.
  2017-05-08  8:54   ` Jani Nikula
@ 2017-05-08 16:52     ` Jim Bride
  0 siblings, 0 replies; 16+ messages in thread
From: Jim Bride @ 2017-05-08 16:52 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni, Rodrigo Vivi

On Mon, May 08, 2017 at 11:54:15AM +0300, Jani Nikula wrote:
> On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> > Some fixed resolution panels actually support more than one mode,
> > with the only thing different being the refresh rate.  Having this
> > alternate mode available to us is desirable, because it allows us to
> > test PSR on panels whose setup time at the preferred mode is too long.
> > With this patch we allow the use of the alternate mode if it's
> > available and it was specifically requested.
> 
> All in all this feels like a hack. The generic solution would be to
> allow any mode to be set again.

To an extent, I agree with you.  I did things this way in an attempt
to change the current behavior as little as possible.  Personally,
I'd rather see us allow any supported mode to be set.

> A few specific comments inline.
> 
> BR,
> Jani.
> 
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c    | 34 +++++++++++++++++++++++++++++-----
> >  drivers/gpu/drm/i915/intel_drv.h   |  2 ++
> >  drivers/gpu/drm/i915/intel_dsi.c   |  2 +-
> >  drivers/gpu/drm/i915/intel_dvo.c   |  2 +-
> >  drivers/gpu/drm/i915/intel_lvds.c  |  3 ++-
> >  drivers/gpu/drm/i915/intel_panel.c |  2 ++
> >  6 files changed, 37 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 08834f7..d46f72d 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1637,6 +1637,19 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
> >  	return bpp;
> >  }
> >  
> > +static bool intel_edp_compare_alt_mode(struct drm_display_mode *m1,
> > +				       struct drm_display_mode *m2)
> > +{
> > +	return (m1->hdisplay == m2->hdisplay &&
> > +		m1->hsync_start == m2->hsync_start &&
> > +		m1->hsync_end == m2->hsync_end &&
> > +		m1->htotal == m2->htotal &&
> > +		m1->vdisplay == m2->vdisplay &&
> > +		m1->vsync_start == m2->vsync_start &&
> > +		m1->vsync_end == m2->vsync_end &&
> > +		m1->vtotal == m2->vtotal);
> > +}
> 
> See drm_mode_equal and friends.

I did.  The problem is that I needed a comparison without vscan being
involved (see drm_mode_equal_no_clocks_no_stereo(), where the actual
comparison happens.)  This seemed like the least disruptive way to do
that comparison.

> 
> > +
> >  bool
> >  intel_dp_compute_config(struct intel_encoder *encoder,
> >  			struct intel_crtc_state *pipe_config,
> > @@ -1674,8 +1687,16 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> >  	pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;
> >  
> >  	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
> > -		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
> > -				       adjusted_mode);
> > +		struct drm_display_mode *panel_mode =
> > +			intel_connector->panel.alt_fixed_mode;
> > +		struct drm_display_mode *req_mode = &pipe_config->base.mode;
> > +
> > +		if (!intel_edp_compare_alt_mode(req_mode, panel_mode))
> > +			panel_mode = intel_connector->panel.fixed_mode;
> > +
> > +		drm_mode_debug_printmodeline(panel_mode);
> > +
> > +		intel_fixed_panel_mode(panel_mode, adjusted_mode);
> >  
> >  		if (INTEL_GEN(dev_priv) >= 9) {
> >  			int ret;
> > @@ -5829,6 +5850,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >  	struct drm_device *dev = intel_encoder->base.dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct drm_display_mode *fixed_mode = NULL;
> > +	struct drm_display_mode *alt_fixed_mode = NULL;
> >  	struct drm_display_mode *downclock_mode = NULL;
> >  	bool has_dpcd;
> >  	struct drm_display_mode *scan;
> > @@ -5884,13 +5906,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >  	}
> >  	intel_connector->edid = edid;
> >  
> > -	/* prefer fixed mode from EDID if available */
> > +	/* prefer fixed mode from EDID if available, save an alt mode also */
> >  	list_for_each_entry(scan, &connector->probed_modes, head) {
> >  		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
> >  			fixed_mode = drm_mode_duplicate(dev, scan);
> >  			downclock_mode = intel_dp_drrs_init(
> >  						intel_connector, fixed_mode);
> > -			break;
> > +		} else {
> > +			alt_fixed_mode = drm_mode_duplicate(dev, scan);
> >  		}
> 
> This changes the fixed mode if there are more than one preferred
> mode. This will also leak all but the two modes.

I wasn't aware there can be more than one preferred mode.  I thought
the whole idea was to have a way of designating one mode of many
that would provide (at least in the opinion of the panel's makers)
the mode that will provide the best user experience.  FWIW, on the
panels I've tested with I haven't seen more than two modes supported
natively in any case.  If we follow your earlier suggestion about
just letting mode sets happen on all supported modes then all of this
stuff goes away.


Jim

> 
> >  	}
> >  
> > @@ -5927,7 +5950,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >  			      pipe_name(pipe));
> >  	}
> >  
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, alt_fixed_mode,
> > +			 downclock_mode);
> >  	intel_connector->panel.backlight.power = intel_edp_backlight_power;
> >  	intel_panel_setup_backlight(connector, pipe);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 54f3ff8..19d0c8f 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -265,6 +265,7 @@ struct intel_encoder {
> >  
> >  struct intel_panel {
> >  	struct drm_display_mode *fixed_mode;
> > +	struct drm_display_mode *alt_fixed_mode;
> >  	struct drm_display_mode *downclock_mode;
> >  	int fitting_mode;
> >  
> > @@ -1676,6 +1677,7 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
> >  /* intel_panel.c */
> >  int intel_panel_init(struct intel_panel *panel,
> >  		     struct drm_display_mode *fixed_mode,
> > +		     struct drm_display_mode *alt_fixed_mode,
> >  		     struct drm_display_mode *downclock_mode);
> >  void intel_panel_fini(struct intel_panel *panel);
> >  void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
> > diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> > index fc0ef49..a938f08 100644
> > --- a/drivers/gpu/drm/i915/intel_dsi.c
> > +++ b/drivers/gpu/drm/i915/intel_dsi.c
> > @@ -1852,7 +1852,7 @@ void intel_dsi_init(struct drm_i915_private *dev_priv)
> >  	connector->display_info.width_mm = fixed_mode->width_mm;
> >  	connector->display_info.height_mm = fixed_mode->height_mm;
> >  
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL, NULL);
> >  	intel_panel_setup_backlight(connector, INVALID_PIPE);
> >  
> >  	intel_dsi_add_properties(intel_connector);
> > diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> > index c1544a5..39fd4f3 100644
> > --- a/drivers/gpu/drm/i915/intel_dvo.c
> > +++ b/drivers/gpu/drm/i915/intel_dvo.c
> > @@ -554,7 +554,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
> >  			 */
> >  			intel_panel_init(&intel_connector->panel,
> >  					 intel_dvo_get_current_mode(connector),
> > -					 NULL);
> > +					 NULL, NULL);
> >  			intel_dvo->panel_wants_dither = true;
> >  		}
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index 8b942ef..b1e6743 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -1181,7 +1181,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
> >  out:
> >  	mutex_unlock(&dev->mode_config.mutex);
> >  
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
> > +			 downclock_mode);
> >  	intel_panel_setup_backlight(connector, INVALID_PIPE);
> >  
> >  	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > index cb50c52..41eb7b0 100644
> > --- a/drivers/gpu/drm/i915/intel_panel.c
> > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > @@ -1801,11 +1801,13 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
> >  
> >  int intel_panel_init(struct intel_panel *panel,
> >  		     struct drm_display_mode *fixed_mode,
> > +		     struct drm_display_mode *alt_fixed_mode,
> >  		     struct drm_display_mode *downclock_mode)
> >  {
> >  	intel_panel_init_backlight_funcs(panel);
> >  
> >  	panel->fixed_mode = fixed_mode;
> > +	panel->alt_fixed_mode = alt_fixed_mode;
> >  	panel->downclock_mode = downclock_mode;
> >  
> >  	return 0;
> 
> -- 
> 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] 16+ messages in thread

* Re: [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP
  2017-05-08  8:41   ` Jani Nikula
@ 2017-05-08 16:59     ` Jim Bride
  0 siblings, 0 replies; 16+ messages in thread
From: Jim Bride @ 2017-05-08 16:59 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni, Rodrigo Vivi

On Mon, May 08, 2017 at 11:41:25AM +0300, Jani Nikula wrote:
> On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> > This set of changes has some history to them.  There were several attempts
> > to add what was called "fast link training" to i915, which actually wasn't
> > fast link training as per the DP spec.  These changes were
> >
> > 5fa836a9d859 ("drm/i915: DP link training optimization")
> > 4e96c97742f4 ("drm/i915: eDP link training optimization")
> >
> > which were eventually hand-reverted by
> >
> > 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
> >
> > in kernel 4.7-rc4.  The eDP pieces of the above revert, however, had some
> > very bad side-effects on PSR functionality on Skylake. The issue at
> > hand is that when PSR exits i915 briefly emits TP1 followed by TP2/3
> > (depending on the original link configuration) in order to quickly get
> > the source and sink back in synchronization across the link before handing
> > control back to the i915.  There's an assumption that none of the link
> > configuration information has changed (and thus it's still valid) since the
> > last full link training operation.  The revert above was identified via a
> > bisect as the cause of some of Skylake's PSR woes.  This patch, largely
> > based on
> >
> > commit 4e96c97742f4201edf1b0f8e1b1b6b2ac6ff33e7
> > Author: Mika Kahola <mika.kahola@intel.com>
> > Date:   Wed Apr 29 09:17:39 2015 +0300
> > drm/i915: eDP link training optimization
> >
> > puts the eDP portions of this patch back in place.  None of the flickering
> > issues that spurred the revert have been seen, and I suspect the real
> > culprits here were addressed by some of the recent link training changes
> > that Manasi has implemented, and PSR on Skylake is definitely more happy
> > with these changes in-place.
> 
> I'm weary of all the back and forth wrt PSR and DP, and wary of creating
> new ones. Would it make sense to restrict this patch to PSR?

Honestly, although it could be limited to PSR, I think it's beneficial
to leave it in place as it is.  For eDP, where panels generally only
support a small number of native modes, I think we end up doing a lot
of extra work by re-calculating all of the link information every
time.  Mika seems think it's pretty safe as well.

Jim

> 
> BR,
> Jani.
> 
> 
> >
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: Manasi D Navare <manasi.d.navare@intel.com>
> > Cc: Mika Kahola <mika.kahola@intel.com>
> > Fixes: 34511dce4 ("drm/i915: Revert DisplayPort fast link training feature")
> > Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c               |  4 +++-
> >  drivers/gpu/drm/i915/intel_dp_link_training.c | 11 ++++++++++-
> >  drivers/gpu/drm/i915/intel_drv.h              |  2 ++
> >  3 files changed, 15 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index d46f72d..06b8bd4 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -106,7 +106,7 @@ static const int default_rates[] = { 162000, 270000, 540000 };
> >   * If a CPU or PCH DP output is attached to an eDP panel, this function
> >   * will return true, and false otherwise.
> >   */
> > -static bool is_edp(struct intel_dp *intel_dp)
> > +bool is_edp(struct intel_dp *intel_dp)
> >  {
> >  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> >  
> > @@ -4690,6 +4690,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
> >  		intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
> >  
> >  		intel_dp->reset_link_params = false;
> > +		intel_dp->train_set_valid = false;
> >  	}
> >  
> >  	intel_dp_print_rates(intel_dp);
> > @@ -6052,6 +6053,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
> >  	intel_dp_set_source_rates(intel_dp);
> >  
> >  	intel_dp->reset_link_params = true;
> > +	intel_dp->train_set_valid = false;
> >  	intel_dp->pps_pipe = INVALID_PIPE;
> >  	intel_dp->active_pipe = INVALID_PIPE;
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
> > index b79c1c0..60233e2 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_link_training.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
> > @@ -94,7 +94,8 @@ static bool
> >  intel_dp_reset_link_train(struct intel_dp *intel_dp,
> >  			uint8_t dp_train_pat)
> >  {
> > -	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
> > +	if (!intel_dp->train_set_valid)
> > +		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
> >  	intel_dp_set_signal_levels(intel_dp);
> >  	return intel_dp_set_link_train(intel_dp, dp_train_pat);
> >  }
> > @@ -162,6 +163,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
> >  				       DP_TRAINING_PATTERN_1 |
> >  				       DP_LINK_SCRAMBLING_DISABLE)) {
> >  		DRM_ERROR("failed to enable link training\n");
> > +		intel_dp->train_set_valid = false;
> >  		return false;
> >  	}
> >  
> > @@ -174,21 +176,25 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
> >  
> >  		if (!intel_dp_get_link_status(intel_dp, link_status)) {
> >  			DRM_ERROR("failed to get link status\n");
> > +			intel_dp->train_set_valid = false;
> >  			return false;
> >  		}
> >  
> >  		if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
> >  			DRM_DEBUG_KMS("clock recovery OK\n");
> > +			intel_dp->train_set_valid = is_edp(intel_dp);
> >  			return true;
> >  		}
> >  
> >  		if (voltage_tries == 5) {
> >  			DRM_DEBUG_KMS("Same voltage tried 5 times\n");
> > +			intel_dp->train_set_valid = false;
> >  			return false;
> >  		}
> >  
> >  		if (max_vswing_tries == 1) {
> >  			DRM_DEBUG_KMS("Max Voltage Swing reached\n");
> > +			intel_dp->train_set_valid = false;
> >  			return false;
> >  		}
> >  
> > @@ -198,6 +204,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
> >  		intel_get_adjust_train(intel_dp, link_status);
> >  		if (!intel_dp_update_link_train(intel_dp)) {
> >  			DRM_ERROR("failed to update link training\n");
> > +			intel_dp->train_set_valid = false;
> >  			return false;
> >  		}
> >  
> > @@ -256,6 +263,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
> >  				     training_pattern |
> >  				     DP_LINK_SCRAMBLING_DISABLE)) {
> >  		DRM_ERROR("failed to start channel equalization\n");
> > +		intel_dp->train_set_valid = false;
> >  		return false;
> >  	}
> >  
> > @@ -296,6 +304,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
> >  	/* Try 5 times, else fail and try at lower BW */
> >  	if (tries == 5) {
> >  		intel_dp_dump_link_status(link_status);
> > +		intel_dp->train_set_valid = false;
> >  		DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
> >  	}
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 19d0c8f..149d4c9 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -977,6 +977,7 @@ struct intel_dp {
> >  	struct drm_dp_aux aux;
> >  	enum intel_display_power_domain aux_power_domain;
> >  	uint8_t train_set[4];
> > +	bool train_set_valid;
> >  	int panel_power_up_delay;
> >  	int panel_power_down_delay;
> >  	int panel_power_cycle_delay;
> > @@ -1551,6 +1552,7 @@ bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
> >  bool __intel_dp_read_desc(struct intel_dp *intel_dp,
> >  			  struct intel_dp_desc *desc);
> >  bool intel_dp_read_desc(struct intel_dp *intel_dp);
> > +bool is_edp(struct intel_dp *intel_dp);
> >  int intel_dp_link_required(int pixel_clock, int bpp);
> >  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
> >  bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
> 
> -- 
> 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] 16+ messages in thread

* Re: [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels
  2017-05-08  9:12   ` Jani Nikula
@ 2017-05-08 17:29     ` Jim Bride
  2017-05-08 18:05       ` Jani Nikula
  0 siblings, 1 reply; 16+ messages in thread
From: Jim Bride @ 2017-05-08 17:29 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni, Rodrigo Vivi

On Mon, May 08, 2017 at 12:12:47PM +0300, Jani Nikula wrote:
> On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> > According to the eDP spec, when the count field in TEST_SINK_MISC
> > increments then the six bytes of sink CRC information in the DPCD
> > should be valid.  Unfortunately, this doesn't seem to be the case
> > on some panels, and as a result we get some incorrect and inconsistent
> > values from the sink CRC DPCD locations at times.  This problem exhibits
> > itself more on faster processors (relative failure rates HSW < SKL < KBL.)
> > In order to try and account for this, we try a lot harder to read the sink
> > CRC until we get consistent values twice in a row before returning what we
> > read and delay for a time before trying to read.  We still see some
> > occasional failures, but reading the sink CRC is much more reliable,
> > particularly on SKL and KBL, with these changes than without.
> 
> Retrying seems like a good idea. But this patch retries up to 36 times
> if the two consecutive reads don't match, which is excessive.

I don't see where you're getting 36 from; the loop runs through six times.

> The sleeps should probably be a separate change. Also not happy about
> the magic numbers there.

Looping w/o the sleeps doesn't make a ton of sense IMHO.  The numbers
were found experimentally on KBL, which seemed to more easily
exercise the race that this patch is meant to address.  Ideally the
panels would not increment the counter until they were sure that the
CRC data in the DPCD actually reflected reality.  Unfortunately, this
isn't what we're seeing.  I will create a couple of #defines for the
sleep values, at least, with some comments about them.  

> Also, there are plenty of what seem like unrelated changes. Whitespace,
> debug logging, error checking, etc.

I looked at this as refactoring the existing implementation, so I
went ahead and added some debugging info; the error checking is
part of the refactoring.  Given the history of problems with this
functionality that seemed warranted.  I did notice one line of
whitespace change that snuck in (where I missed that I removed a
blank line.)  I can take out the debug prints for the success
cases if they seem excessive (and I'll restore the deleted
blank line for the next version of the patch.)

Jim


> 
> BR,
> Jani.
> 
> 
> >
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++--
> >  drivers/gpu/drm/i915/intel_dp.c     | 57 ++++++++++++++++++++++++++++++++-----
> >  2 files changed, 61 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 870c470..4902473 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -2718,7 +2718,7 @@ static int i915_sink_crc(struct seq_file *m, void *data)
> >  	struct intel_connector *connector;
> >  	struct drm_connector_list_iter conn_iter;
> >  	struct intel_dp *intel_dp = NULL;
> > -	int ret;
> > +	int ret, tries = 6;
> >  	u8 crc[6];
> >  
> >  	drm_modeset_lock_all(dev);
> > @@ -2738,9 +2738,17 @@ static int i915_sink_crc(struct seq_file *m, void *data)
> >  
> >  		intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
> >  
> > -		ret = intel_dp_sink_crc(intel_dp, crc);
> > -		if (ret)
> > +		memset(crc, 0, 6);
> > +		do {
> > +			ret = intel_dp_sink_crc(intel_dp, crc);
> > +			if (ret == -ETIMEDOUT)
> > +				usleep_range(500, 700);
> > +		} while ((ret == -ETIMEDOUT) && --tries);
> > +
> > +		if (ret != 0) {
> > +			seq_printf(m, "000000000000\n");
> >  			goto out;
> > +		}
> >  
> >  		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
> >  			   crc[0], crc[1], crc[2],
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 06b8bd4..217bc06 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3877,13 +3877,15 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
> >  
> >  	do {
> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> > -
> > +		usleep_range(16700, 17000);
> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
> > +			DRM_DEBUG_KMS("Could not read TEST_SINK_MISC\n");
> >  			ret = -EIO;
> >  			goto out;
> >  		}
> >  		count = buf & DP_TEST_COUNT_MASK;
> > +		DRM_DEBUG_KMS("PSR count is %d\n", count);
> >  	} while (--attempts && count);
> >  
> >  	if (attempts == 0) {
> > @@ -3928,6 +3930,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
> >  	}
> >  
> >  	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> > +	usleep_range(16700, 17000);
> > +	DRM_DEBUG_KMS("PSR Successfully started sink CRC\n");
> >  	return 0;
> >  }
> >  
> > @@ -3939,21 +3943,30 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> >  	u8 buf;
> >  	int count, ret;
> >  	int attempts = 6;
> > +	u8 old_crc[6];
> > +
> > +	if (crc != NULL)
> > +		memset(crc, 0, 6);
> > +	else
> > +		return -ENOMEM;
> >  
> >  	ret = intel_dp_sink_crc_start(intel_dp);
> > -	if (ret)
> > +	if (ret) {
> > +		DRM_DEBUG_KMS("Could not start sink crc; ret %d\n", ret);
> >  		return ret;
> > +	}
> >  
> >  	do {
> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> > +		usleep_range(16700, 17000);
> >  
> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
> > +			DRM_DEBUG_KMS("Cound not read TEST_SINK_MISC\n");
> >  			ret = -EIO;
> >  			goto stop;
> >  		}
> >  		count = buf & DP_TEST_COUNT_MASK;
> > -
> >  	} while (--attempts && count == 0);
> >  
> >  	if (attempts == 0) {
> > @@ -3962,11 +3975,41 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> >  		goto stop;
> >  	}
> >  
> > -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
> > -		ret = -EIO;
> > -		goto stop;
> > -	}
> > +	attempts = 6;
> > +	memset(old_crc, 0xFF, 6);
> > +	do {
> > +		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> > +		usleep_range(16500, 17000);
> > +		if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR,
> > +				     crc, 6) < 0) {
> > +			DRM_DEBUG_KMS("Could not read sink crc\n");
> > +			ret = -EIO;
> > +			goto stop;
> > +		}
> > +
> > +		if (memcmp(old_crc, crc, 6) == 0) {
> > +			DRM_DEBUG_KMS("PSR Active: %3s Matching crc values found:"
> > +				      "%02x%02x%02x%02x%02x%02x\n",
> > +				      yesno(dev_priv->psr.active),
> > +				      crc[0], crc[1], crc[2],
> > +				      crc[3], crc[4], crc[5]);
> > +			ret = 0;
> > +			goto stop;
> > +		} else {
> > +			DRM_DEBUG_KMS("PSR Active: %3s crc %02x%02x%02x%02x%02x%02x "
> > +				      "doesn't match "
> > +				      "previous %02x%02x%02x%02x%02x%02x\n",
> > +				      yesno(dev_priv->psr.active),
> > +				      crc[0], crc[1], crc[2],
> > +				      crc[3], crc[4], crc[5],
> > +				      old_crc[0], old_crc[1], old_crc[2],
> > +				      old_crc[3], old_crc[4], old_crc[5]);
> > +			memcpy(old_crc, crc, 6);
> > +		}
> > +	} while (--attempts);
> >  
> > +	DRM_DEBUG_KMS("Failed to get CRC after 6 attempts.\n");
> > +	ret = -ETIMEDOUT;
> >  stop:
> >  	intel_dp_sink_crc_stop(intel_dp);
> >  	return ret;
> 
> -- 
> 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] 16+ messages in thread

* Re: [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels
  2017-05-08 17:29     ` Jim Bride
@ 2017-05-08 18:05       ` Jani Nikula
  2017-05-08 19:26         ` Jim Bride
  0 siblings, 1 reply; 16+ messages in thread
From: Jani Nikula @ 2017-05-08 18:05 UTC (permalink / raw)
  To: Jim Bride; +Cc: intel-gfx, Paulo Zanoni, Rodrigo Vivi

On Mon, 08 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> On Mon, May 08, 2017 at 12:12:47PM +0300, Jani Nikula wrote:
>> On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
>> > According to the eDP spec, when the count field in TEST_SINK_MISC
>> > increments then the six bytes of sink CRC information in the DPCD
>> > should be valid.  Unfortunately, this doesn't seem to be the case
>> > on some panels, and as a result we get some incorrect and inconsistent
>> > values from the sink CRC DPCD locations at times.  This problem exhibits
>> > itself more on faster processors (relative failure rates HSW < SKL < KBL.)
>> > In order to try and account for this, we try a lot harder to read the sink
>> > CRC until we get consistent values twice in a row before returning what we
>> > read and delay for a time before trying to read.  We still see some
>> > occasional failures, but reading the sink CRC is much more reliable,
>> > particularly on SKL and KBL, with these changes than without.
>> 
>> Retrying seems like a good idea. But this patch retries up to 36 times
>> if the two consecutive reads don't match, which is excessive.
>
> I don't see where you're getting 36 from; the loop runs through six times.

i915_sink_crc() calls intel_dp_sink_crc(), retrying on ETIMEDOUT. In
turn, intel_dp_sink_crc() reads CRC, retrying on mismatched CRC and
returning ETIMEDOUT to i915_sink_crc() on errors. Admittedly the loop in
intel_dp_sink_crc() will always run at least twice to get two results to
compare, so I guess it would be fair to say the combo tries CRC read up
to 6 * 5 = 30 times.

>> The sleeps should probably be a separate change. Also not happy about
>> the magic numbers there.
>
> Looping w/o the sleeps doesn't make a ton of sense IMHO.  The numbers
> were found experimentally on KBL, which seemed to more easily
> exercise the race that this patch is meant to address.  Ideally the
> panels would not increment the counter until they were sure that the
> CRC data in the DPCD actually reflected reality.  Unfortunately, this
> isn't what we're seeing.  I will create a couple of #defines for the
> sleep values, at least, with some comments about them.  

It's just that the magic sleeps are eerily close to a frame at 60
Hz. Did you try another vblank wait instead? Or maybe it's the sync to
vblank that is the issue.

>> Also, there are plenty of what seem like unrelated changes. Whitespace,
>> debug logging, error checking, etc.
>
> I looked at this as refactoring the existing implementation, so I
> went ahead and added some debugging info; the error checking is
> part of the refactoring.  Given the history of problems with this
> functionality that seemed warranted.  I did notice one line of
> whitespace change that snuck in (where I missed that I removed a
> blank line.)  I can take out the debug prints for the success
> cases if they seem excessive (and I'll restore the deleted
> blank line for the next version of the patch.)

The thing is, by now I'm looking at basically any sink visible
functional changes to eDP, and PSR in particular, with the thought that
this may have to be reverted due to regressions later. That has nothing
to do with these patches, but rather our track record with eDP and
PSR. (And that also says a lot about eDP sink quality in general.)

So I'd rather see the other changes split out so we have a smaller diff
to revert, in case we have to revert. The pessimist does not get
disappointed. And so far PSR hasn't given us any reasons for optimism.

BR,
Jani.



>
> Jim
>
>
>> 
>> BR,
>> Jani.
>> 
>> 
>> >
>> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
>> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> > Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++--
>> >  drivers/gpu/drm/i915/intel_dp.c     | 57 ++++++++++++++++++++++++++++++++-----
>> >  2 files changed, 61 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> > index 870c470..4902473 100644
>> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> > @@ -2718,7 +2718,7 @@ static int i915_sink_crc(struct seq_file *m, void *data)
>> >  	struct intel_connector *connector;
>> >  	struct drm_connector_list_iter conn_iter;
>> >  	struct intel_dp *intel_dp = NULL;
>> > -	int ret;
>> > +	int ret, tries = 6;
>> >  	u8 crc[6];
>> >  
>> >  	drm_modeset_lock_all(dev);
>> > @@ -2738,9 +2738,17 @@ static int i915_sink_crc(struct seq_file *m, void *data)
>> >  
>> >  		intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
>> >  
>> > -		ret = intel_dp_sink_crc(intel_dp, crc);
>> > -		if (ret)
>> > +		memset(crc, 0, 6);
>> > +		do {
>> > +			ret = intel_dp_sink_crc(intel_dp, crc);
>> > +			if (ret == -ETIMEDOUT)
>> > +				usleep_range(500, 700);
>> > +		} while ((ret == -ETIMEDOUT) && --tries);
>> > +
>> > +		if (ret != 0) {
>> > +			seq_printf(m, "000000000000\n");
>> >  			goto out;
>> > +		}
>> >  
>> >  		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
>> >  			   crc[0], crc[1], crc[2],
>> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> > index 06b8bd4..217bc06 100644
>> > --- a/drivers/gpu/drm/i915/intel_dp.c
>> > +++ b/drivers/gpu/drm/i915/intel_dp.c
>> > @@ -3877,13 +3877,15 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
>> >  
>> >  	do {
>> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
>> > -
>> > +		usleep_range(16700, 17000);
>> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
>> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
>> > +			DRM_DEBUG_KMS("Could not read TEST_SINK_MISC\n");
>> >  			ret = -EIO;
>> >  			goto out;
>> >  		}
>> >  		count = buf & DP_TEST_COUNT_MASK;
>> > +		DRM_DEBUG_KMS("PSR count is %d\n", count);
>> >  	} while (--attempts && count);
>> >  
>> >  	if (attempts == 0) {
>> > @@ -3928,6 +3930,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
>> >  	}
>> >  
>> >  	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
>> > +	usleep_range(16700, 17000);
>> > +	DRM_DEBUG_KMS("PSR Successfully started sink CRC\n");
>> >  	return 0;
>> >  }
>> >  
>> > @@ -3939,21 +3943,30 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
>> >  	u8 buf;
>> >  	int count, ret;
>> >  	int attempts = 6;
>> > +	u8 old_crc[6];
>> > +
>> > +	if (crc != NULL)
>> > +		memset(crc, 0, 6);
>> > +	else
>> > +		return -ENOMEM;
>> >  
>> >  	ret = intel_dp_sink_crc_start(intel_dp);
>> > -	if (ret)
>> > +	if (ret) {
>> > +		DRM_DEBUG_KMS("Could not start sink crc; ret %d\n", ret);
>> >  		return ret;
>> > +	}
>> >  
>> >  	do {
>> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
>> > +		usleep_range(16700, 17000);
>> >  
>> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
>> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
>> > +			DRM_DEBUG_KMS("Cound not read TEST_SINK_MISC\n");
>> >  			ret = -EIO;
>> >  			goto stop;
>> >  		}
>> >  		count = buf & DP_TEST_COUNT_MASK;
>> > -
>> >  	} while (--attempts && count == 0);
>> >  
>> >  	if (attempts == 0) {
>> > @@ -3962,11 +3975,41 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
>> >  		goto stop;
>> >  	}
>> >  
>> > -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
>> > -		ret = -EIO;
>> > -		goto stop;
>> > -	}
>> > +	attempts = 6;
>> > +	memset(old_crc, 0xFF, 6);
>> > +	do {
>> > +		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
>> > +		usleep_range(16500, 17000);
>> > +		if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR,
>> > +				     crc, 6) < 0) {
>> > +			DRM_DEBUG_KMS("Could not read sink crc\n");
>> > +			ret = -EIO;
>> > +			goto stop;
>> > +		}
>> > +
>> > +		if (memcmp(old_crc, crc, 6) == 0) {
>> > +			DRM_DEBUG_KMS("PSR Active: %3s Matching crc values found:"
>> > +				      "%02x%02x%02x%02x%02x%02x\n",
>> > +				      yesno(dev_priv->psr.active),
>> > +				      crc[0], crc[1], crc[2],
>> > +				      crc[3], crc[4], crc[5]);
>> > +			ret = 0;
>> > +			goto stop;
>> > +		} else {
>> > +			DRM_DEBUG_KMS("PSR Active: %3s crc %02x%02x%02x%02x%02x%02x "
>> > +				      "doesn't match "
>> > +				      "previous %02x%02x%02x%02x%02x%02x\n",
>> > +				      yesno(dev_priv->psr.active),
>> > +				      crc[0], crc[1], crc[2],
>> > +				      crc[3], crc[4], crc[5],
>> > +				      old_crc[0], old_crc[1], old_crc[2],
>> > +				      old_crc[3], old_crc[4], old_crc[5]);
>> > +			memcpy(old_crc, crc, 6);
>> > +		}
>> > +	} while (--attempts);
>> >  
>> > +	DRM_DEBUG_KMS("Failed to get CRC after 6 attempts.\n");
>> > +	ret = -ETIMEDOUT;
>> >  stop:
>> >  	intel_dp_sink_crc_stop(intel_dp);
>> >  	return ret;
>> 
>> -- 
>> Jani Nikula, Intel Open Source Technology Center

-- 
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] 16+ messages in thread

* Re: [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels
  2017-05-08 18:05       ` Jani Nikula
@ 2017-05-08 19:26         ` Jim Bride
  0 siblings, 0 replies; 16+ messages in thread
From: Jim Bride @ 2017-05-08 19:26 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni, Rodrigo Vivi

On Mon, May 08, 2017 at 09:05:08PM +0300, Jani Nikula wrote:
> On Mon, 08 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> > On Mon, May 08, 2017 at 12:12:47PM +0300, Jani Nikula wrote:
> >> On Sat, 06 May 2017, Jim Bride <jim.bride@linux.intel.com> wrote:
> >> > According to the eDP spec, when the count field in TEST_SINK_MISC
> >> > increments then the six bytes of sink CRC information in the DPCD
> >> > should be valid.  Unfortunately, this doesn't seem to be the case
> >> > on some panels, and as a result we get some incorrect and inconsistent
> >> > values from the sink CRC DPCD locations at times.  This problem exhibits
> >> > itself more on faster processors (relative failure rates HSW < SKL < KBL.)
> >> > In order to try and account for this, we try a lot harder to read the sink
> >> > CRC until we get consistent values twice in a row before returning what we
> >> > read and delay for a time before trying to read.  We still see some
> >> > occasional failures, but reading the sink CRC is much more reliable,
> >> > particularly on SKL and KBL, with these changes than without.
> >> 
> >> Retrying seems like a good idea. But this patch retries up to 36 times
> >> if the two consecutive reads don't match, which is excessive.
> >
> > I don't see where you're getting 36 from; the loop runs through six times.
> 
> i915_sink_crc() calls intel_dp_sink_crc(), retrying on ETIMEDOUT. In
> turn, intel_dp_sink_crc() reads CRC, retrying on mismatched CRC and
> returning ETIMEDOUT to i915_sink_crc() on errors. Admittedly the loop in
> intel_dp_sink_crc() will always run at least twice to get two results to
> compare, so I guess it would be fair to say the combo tries CRC read up
> to 6 * 5 = 30 times.

I'll play around with making i915_sink_crc() a little less
persistent and see what it does.  The loop in intel_dp_sink_crc()
frequently goes 3+ tries, so I'd prefer to keep that one as it is.


> >> The sleeps should probably be a separate change. Also not happy about
> >> the magic numbers there.
> >
> > Looping w/o the sleeps doesn't make a ton of sense IMHO.  The numbers
> > were found experimentally on KBL, which seemed to more easily
> > exercise the race that this patch is meant to address.  Ideally the
> > panels would not increment the counter until they were sure that the
> > CRC data in the DPCD actually reflected reality.  Unfortunately, this
> > isn't what we're seeing.  I will create a couple of #defines for the
> > sleep values, at least, with some comments about them.  
> 
> It's just that the magic sleeps are eerily close to a frame at 60
> Hz. Did you try another vblank wait instead? Or maybe it's the sync to
> vblank that is the issue.

This brings up an interesting point.  IMHO relying on vblanks for PSR
related stuff is a bad idea, at least while PSR is active.  The
reason I say this is that if PSR is active, then the link itself may
or may not be active.  We certainly shouldn't be sending frames of
data, vblanks,  or anything of that ilk.  There's a patch series that
Rodrigo wrote last August that I plan to write a IGT test case for (I
wanted to see IGT working right for PSR tests in general before doing
this) that basically makes sure that vblanks are disabled if PSR is
active, and that enabling vblanks causes PSR to exit.  Review
feedback on that series was that it needed an IGT test.  When thinking
about this series, I've been toying with the idea of doing a sleep
based on the time needed to render a frame + the appropriate blanking
intervals instead of doing all of the vblank waits anyhow, at least
for the sink CRC stuff since we need to get that data out while PSR
is active.  Now I'm wondering if we should go ahead and do that for
all but the PSR exit case now, perhaps.  Thoughts?

> >> Also, there are plenty of what seem like unrelated changes. Whitespace,
> >> debug logging, error checking, etc.
> >
> > I looked at this as refactoring the existing implementation, so I
> > went ahead and added some debugging info; the error checking is
> > part of the refactoring.  Given the history of problems with this
> > functionality that seemed warranted.  I did notice one line of
> > whitespace change that snuck in (where I missed that I removed a
> > blank line.)  I can take out the debug prints for the success
> > cases if they seem excessive (and I'll restore the deleted
> > blank line for the next version of the patch.)
> 
> The thing is, by now I'm looking at basically any sink visible
> functional changes to eDP, and PSR in particular, with the thought that
> this may have to be reverted due to regressions later. That has nothing
> to do with these patches, but rather our track record with eDP and
> PSR. (And that also says a lot about eDP sink quality in general.)
> 
> So I'd rather see the other changes split out so we have a smaller diff
> to revert, in case we have to revert. The pessimist does not get
> disappointed. And so far PSR hasn't given us any reasons for optimism.

Let me see what I can do.  I might be able to at least split out some
of the debug / error checking into a separate patch.

Jim

> BR,
> Jani.
> 
> 
> 
> >
> > Jim
> >
> >
> >> 
> >> BR,
> >> Jani.
> >> 
> >> 
> >> >
> >> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> >> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >> > Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> >> > ---
> >> >  drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++--
> >> >  drivers/gpu/drm/i915/intel_dp.c     | 57 ++++++++++++++++++++++++++++++++-----
> >> >  2 files changed, 61 insertions(+), 10 deletions(-)
> >> >
> >> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> >> > index 870c470..4902473 100644
> >> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> >> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> >> > @@ -2718,7 +2718,7 @@ static int i915_sink_crc(struct seq_file *m, void *data)
> >> >  	struct intel_connector *connector;
> >> >  	struct drm_connector_list_iter conn_iter;
> >> >  	struct intel_dp *intel_dp = NULL;
> >> > -	int ret;
> >> > +	int ret, tries = 6;
> >> >  	u8 crc[6];
> >> >  
> >> >  	drm_modeset_lock_all(dev);
> >> > @@ -2738,9 +2738,17 @@ static int i915_sink_crc(struct seq_file *m, void *data)
> >> >  
> >> >  		intel_dp = enc_to_intel_dp(connector->base.state->best_encoder);
> >> >  
> >> > -		ret = intel_dp_sink_crc(intel_dp, crc);
> >> > -		if (ret)
> >> > +		memset(crc, 0, 6);
> >> > +		do {
> >> > +			ret = intel_dp_sink_crc(intel_dp, crc);
> >> > +			if (ret == -ETIMEDOUT)
> >> > +				usleep_range(500, 700);
> >> > +		} while ((ret == -ETIMEDOUT) && --tries);
> >> > +
> >> > +		if (ret != 0) {
> >> > +			seq_printf(m, "000000000000\n");
> >> >  			goto out;
> >> > +		}
> >> >  
> >> >  		seq_printf(m, "%02x%02x%02x%02x%02x%02x\n",
> >> >  			   crc[0], crc[1], crc[2],
> >> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> >> > index 06b8bd4..217bc06 100644
> >> > --- a/drivers/gpu/drm/i915/intel_dp.c
> >> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> >> > @@ -3877,13 +3877,15 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
> >> >  
> >> >  	do {
> >> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> >> > -
> >> > +		usleep_range(16700, 17000);
> >> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
> >> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
> >> > +			DRM_DEBUG_KMS("Could not read TEST_SINK_MISC\n");
> >> >  			ret = -EIO;
> >> >  			goto out;
> >> >  		}
> >> >  		count = buf & DP_TEST_COUNT_MASK;
> >> > +		DRM_DEBUG_KMS("PSR count is %d\n", count);
> >> >  	} while (--attempts && count);
> >> >  
> >> >  	if (attempts == 0) {
> >> > @@ -3928,6 +3930,8 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
> >> >  	}
> >> >  
> >> >  	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> >> > +	usleep_range(16700, 17000);
> >> > +	DRM_DEBUG_KMS("PSR Successfully started sink CRC\n");
> >> >  	return 0;
> >> >  }
> >> >  
> >> > @@ -3939,21 +3943,30 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> >> >  	u8 buf;
> >> >  	int count, ret;
> >> >  	int attempts = 6;
> >> > +	u8 old_crc[6];
> >> > +
> >> > +	if (crc != NULL)
> >> > +		memset(crc, 0, 6);
> >> > +	else
> >> > +		return -ENOMEM;
> >> >  
> >> >  	ret = intel_dp_sink_crc_start(intel_dp);
> >> > -	if (ret)
> >> > +	if (ret) {
> >> > +		DRM_DEBUG_KMS("Could not start sink crc; ret %d\n", ret);
> >> >  		return ret;
> >> > +	}
> >> >  
> >> >  	do {
> >> >  		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> >> > +		usleep_range(16700, 17000);
> >> >  
> >> >  		if (drm_dp_dpcd_readb(&intel_dp->aux,
> >> >  				      DP_TEST_SINK_MISC, &buf) < 0) {
> >> > +			DRM_DEBUG_KMS("Cound not read TEST_SINK_MISC\n");
> >> >  			ret = -EIO;
> >> >  			goto stop;
> >> >  		}
> >> >  		count = buf & DP_TEST_COUNT_MASK;
> >> > -
> >> >  	} while (--attempts && count == 0);
> >> >  
> >> >  	if (attempts == 0) {
> >> > @@ -3962,11 +3975,41 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
> >> >  		goto stop;
> >> >  	}
> >> >  
> >> > -	if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
> >> > -		ret = -EIO;
> >> > -		goto stop;
> >> > -	}
> >> > +	attempts = 6;
> >> > +	memset(old_crc, 0xFF, 6);
> >> > +	do {
> >> > +		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
> >> > +		usleep_range(16500, 17000);
> >> > +		if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR,
> >> > +				     crc, 6) < 0) {
> >> > +			DRM_DEBUG_KMS("Could not read sink crc\n");
> >> > +			ret = -EIO;
> >> > +			goto stop;
> >> > +		}
> >> > +
> >> > +		if (memcmp(old_crc, crc, 6) == 0) {
> >> > +			DRM_DEBUG_KMS("PSR Active: %3s Matching crc values found:"
> >> > +				      "%02x%02x%02x%02x%02x%02x\n",
> >> > +				      yesno(dev_priv->psr.active),
> >> > +				      crc[0], crc[1], crc[2],
> >> > +				      crc[3], crc[4], crc[5]);
> >> > +			ret = 0;
> >> > +			goto stop;
> >> > +		} else {
> >> > +			DRM_DEBUG_KMS("PSR Active: %3s crc %02x%02x%02x%02x%02x%02x "
> >> > +				      "doesn't match "
> >> > +				      "previous %02x%02x%02x%02x%02x%02x\n",
> >> > +				      yesno(dev_priv->psr.active),
> >> > +				      crc[0], crc[1], crc[2],
> >> > +				      crc[3], crc[4], crc[5],
> >> > +				      old_crc[0], old_crc[1], old_crc[2],
> >> > +				      old_crc[3], old_crc[4], old_crc[5]);
> >> > +			memcpy(old_crc, crc, 6);
> >> > +		}
> >> > +	} while (--attempts);
> >> >  
> >> > +	DRM_DEBUG_KMS("Failed to get CRC after 6 attempts.\n");
> >> > +	ret = -ETIMEDOUT;
> >> >  stop:
> >> >  	intel_dp_sink_crc_stop(intel_dp);
> >> >  	return ret;
> >> 
> >> -- 
> >> Jani Nikula, Intel Open Source Technology Center
> 
> -- 
> 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] 16+ messages in thread

* Re: [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1()
  2017-05-05 21:02 ` [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1() Jim Bride
@ 2017-05-23 19:07   ` Rodrigo Vivi
  0 siblings, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2017-05-23 19:07 UTC (permalink / raw)
  To: Jim Bride; +Cc: intel-gfx, Rodrigo Vivi, Paulo Zanoni, Wayne Boyer

On Fri, May 5, 2017 at 2:02 PM, Jim Bride <jim.bride@linux.intel.com> wrote:
> On SKL+ there is a bit in SRD_CTL that software is not supposed to
> modify, but we currently clobber that bit when we enable PSR.  In
> order to preserve the value of that bit, go ahead and read SRD_CTL and
> do a field-wise setting of the various bits that we need to initialize
> before writing the register back out.  Additionally, go ahead and
> explicitly disable single-frame update since we aren't currently
> supporting it.
>
> v2: Do a field-wise init on EDP_PSR_MAX_SLEEP_TIME even though we
>     always set it to the max value. (Rodrigo)
>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Wayne Boyer <wayne.boyer@intel.com>
> Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h  |  4 ++++
>  drivers/gpu/drm/i915/intel_psr.c | 21 +++++++++++++++++++--
>  2 files changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index ee8170c..3a63555 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3584,18 +3584,22 @@ enum {
>  #define   EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES  (1<<25)
>  #define   EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES  (2<<25)
>  #define   EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES  (3<<25)
> +#define   EDP_PSR_MAX_SLEEP_TIME_MASK           (0x1f<<20)
>  #define   EDP_PSR_MAX_SLEEP_TIME_SHIFT         20
>  #define   EDP_PSR_SKIP_AUX_EXIT                        (1<<12)
>  #define   EDP_PSR_TP1_TP2_SEL                  (0<<11)
>  #define   EDP_PSR_TP1_TP3_SEL                  (1<<11)
> +#define   EDP_PSR_TP2_TP3_TIME_MASK             (3<<8)
>  #define   EDP_PSR_TP2_TP3_TIME_500us           (0<<8)
>  #define   EDP_PSR_TP2_TP3_TIME_100us           (1<<8)
>  #define   EDP_PSR_TP2_TP3_TIME_2500us          (2<<8)
>  #define   EDP_PSR_TP2_TP3_TIME_0us             (3<<8)
> +#define   EDP_PSR_TP1_TIME_MASK                 (0x3<<4)
>  #define   EDP_PSR_TP1_TIME_500us               (0<<4)
>  #define   EDP_PSR_TP1_TIME_100us               (1<<4)
>  #define   EDP_PSR_TP1_TIME_2500us              (2<<4)
>  #define   EDP_PSR_TP1_TIME_0us                 (3<<4)
> +#define   EDP_PSR_IDLE_FRAME_MASK               (0xf<<0)
>  #define   EDP_PSR_IDLE_FRAME_SHIFT             0
>
>  #define EDP_PSR_AUX_CTL                                _MMIO(dev_priv->psr_mmio_base + 0x10)
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index c3780d0..068c382 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -280,17 +280,32 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
>          * with the 5 or 6 idle patterns.
>          */
>         uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> -       uint32_t val = EDP_PSR_ENABLE;
> +       uint32_t val = I915_READ(EDP_PSR_CTL);
>
> +       val |= EDP_PSR_ENABLE;
> +
> +       val &= ~EDP_PSR_MAX_SLEEP_TIME_MASK;
>         val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
> +
> +       val &= ~EDP_PSR_IDLE_FRAME_MASK;
>         val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
>
> +       val &= ~EDP_PSR_MIN_LINK_ENTRY_TIME_MASK;
>         if (IS_HASWELL(dev_priv))
>                 val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
>
> -       if (dev_priv->psr.link_standby)
> +       if (dev_priv->psr.link_standby) {
>                 val |= EDP_PSR_LINK_STANDBY;
>
> +               /* SFU should only be enabled with link standby, but for
> +                * now we do not support it. */

/* goes to next line

> +               val &= ~BDW_PSR_SINGLE_FRAME;
> +       } else {
> +               val &= ~EDP_PSR_LINK_STANDBY;
> +               val &= ~BDW_PSR_SINGLE_FRAME;

probably better to do this out of the if to avoid duplication. Comment above
already explain it well.

with these feel free to use:
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

> +       }
> +
> +       val &= ~EDP_PSR_TP1_TIME_MASK;
>         if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
>                 val |= EDP_PSR_TP1_TIME_2500us;
>         else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
> @@ -300,6 +315,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
>         else
>                 val |= EDP_PSR_TP1_TIME_0us;
>
> +       val &= ~EDP_PSR_TP2_TP3_TIME_MASK;
>         if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
>                 val |= EDP_PSR_TP2_TP3_TIME_2500us;
>         else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
> @@ -309,6 +325,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp)
>         else
>                 val |= EDP_PSR_TP2_TP3_TIME_0us;
>
> +       val &= ~EDP_PSR_TP1_TP3_SEL;
>         if (intel_dp_source_supports_hbr2(intel_dp) &&
>             drm_dp_tps3_supported(intel_dp->dpcd))
>                 val |= EDP_PSR_TP1_TP3_SEL;
> --
> 2.7.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2017-05-23 19:07 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-05 21:02 [PATCH 0/4] Kernel PSR Fix-ups Jim Bride
2017-05-05 21:02 ` [PATCH 1/4] drm/i915/edp: Allow alternate fixed mode for eDP if available Jim Bride
2017-05-08  8:54   ` Jani Nikula
2017-05-08 16:52     ` Jim Bride
2017-05-05 21:02 ` [PATCH 2/4] drm/i915/psr: Clean-up intel_enable_source_psr1() Jim Bride
2017-05-23 19:07   ` Rodrigo Vivi
2017-05-05 21:02 ` [PATCH 3/4] drm/i915/edp: Be less aggressive about changing link config on eDP Jim Bride
2017-05-08  8:41   ` Jani Nikula
2017-05-08 16:59     ` Jim Bride
2017-05-08 13:07   ` Mika Kahola
2017-05-05 21:02 ` [PATCH 4/4] drm/i915/psr: Account for sink CRC raciness on some panels Jim Bride
2017-05-08  9:12   ` Jani Nikula
2017-05-08 17:29     ` Jim Bride
2017-05-08 18:05       ` Jani Nikula
2017-05-08 19:26         ` Jim Bride
2017-05-05 21:20 ` ✓ Fi.CI.BAT: success for Kernel PSR Fix-ups 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.