All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915: Control PSR at runtime through debugfs only
@ 2018-03-14 11:46 Maarten Lankhorst
  2018-03-14 12:32 ` ✗ Fi.CI.BAT: failure for " Patchwork
                   ` (10 more replies)
  0 siblings, 11 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-03-14 11:46 UTC (permalink / raw)
  To: intel-gfx

Allow controlling link status through i915_edp_psr_status, in the same way kernel does.
This replaces changing the module parameter at runtime, then forcing a modeset.

Writing -1 restores the original PSR mode set through the module parameter.
Writing 0 disables PSR.
Writing 1 enables PSR with default link standby mode.
Writing 2 enables PSR with link standby.
Writing 3 enables PSR with link standby disabled.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
This breaks kms_frontbuffer_tracking, and needs the following patch to work:
https://patchwork.freedesktop.org/patch/209956/

XXX: Make global_enable a tristate, to keep older versions of kms_frontbuffer_tracking working?

 drivers/gpu/drm/i915/i915_debugfs.c | 182 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_drv.h     |   2 +
 drivers/gpu/drm/i915/i915_params.c  |   2 +-
 drivers/gpu/drm/i915/intel_drv.h    |   7 ++
 drivers/gpu/drm/i915/intel_psr.c    | 139 ++++++++++++++++-----------
 5 files changed, 271 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 574fcf234007..534a3b04e6a3 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2546,16 +2546,13 @@ static const char *psr2_live_status(u32 val)
 
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	struct drm_i915_private *dev_priv = m->private;
 	u32 psrperf = 0;
 	u32 stat[3];
 	enum pipe pipe;
 	bool enabled = false;
 	bool sink_support;
 
-	if (!HAS_PSR(dev_priv))
-		return -ENODEV;
-
 	sink_support = dev_priv->psr.sink_support;
 	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
 	if (!sink_support)
@@ -2631,6 +2628,181 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	return 0;
 }
 
+static bool psr_needs_disable(struct drm_i915_private *dev_priv,
+			      bool enable, bool link_standby)
+{
+	if (!dev_priv->psr.global_enable)
+		return false;
+
+	if (!enable)
+		return true;
+
+	if (dev_priv->psr.link_standby != link_standby)
+		return true;
+
+	return false;
+}
+
+static bool psr_needs_enable(struct drm_i915_private *dev_priv,
+			     bool enable)
+{
+	if (!enable)
+		return false;
+
+	return !dev_priv->psr.global_enable;
+}
+
+static int __i915_edp_psr_write(struct drm_i915_private *dev_priv,
+				struct drm_modeset_acquire_ctx *ctx,
+				bool enable, bool link_standby)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	int ret;
+	bool needs_enable, found;
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev_priv->psr.lock);
+retry:
+	if (!dev_priv->psr.enabled) {
+		dev_priv->psr.global_enable = enable;
+		dev_priv->psr.link_standby = link_standby;
+		goto end;
+	}
+	encoder = &dp_to_dig_port(dev_priv->psr.enabled)->base.base;
+	mutex_unlock(&dev_priv->psr.lock);
+
+	found = false;
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter)
+		if (connector->state->best_encoder == encoder) {
+			found = true;
+			break;
+		}
+	drm_connector_list_iter_end(&conn_iter);
+
+	if (WARN_ON(!found))
+		return -EINVAL;
+
+	crtc = connector->state->crtc;
+	ret = drm_modeset_lock(&crtc->mutex, ctx);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev_priv->psr.lock);
+	if (dev_priv->psr.enabled != enc_to_intel_dp(encoder))
+		goto retry;
+
+	if ((connector->state->commit && !try_wait_for_completion(&connector->state->commit->hw_done)) ||
+	    (crtc->state->commit && !try_wait_for_completion(&crtc->state->commit->hw_done))) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	if (psr_needs_disable(dev_priv, enable, link_standby)) {
+		__intel_psr_disable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
+		dev_priv->psr.global_enable = false;
+	}
+
+	needs_enable = psr_needs_enable(dev_priv, enable);
+	dev_priv->psr.global_enable = enable;
+	dev_priv->psr.link_standby = link_standby;
+
+	if (needs_enable)
+		__intel_psr_enable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
+
+end:
+	mutex_unlock(&dev_priv->psr.lock);
+	return ret;
+}
+
+static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_i915_private *dev_priv = m->private;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret, val;
+	bool link_standby;
+
+	if (!dev_priv->psr.sink_support)
+		return -ENODEV;
+
+	ret = kstrtoint_from_user(ubuf, len, 10, &val);
+	if (ret < 0) {
+		bool enable;
+		ret = kstrtobool_from_user(ubuf, len, &enable);
+
+		if (ret < 0)
+			return ret;
+
+		val = enable;
+	}
+
+	/* -1 -> reset to default */
+	if (val == -1)
+		val = i915_modparams.enable_psr;
+
+	switch (val) {
+	case 0:
+	case 1:
+		link_standby = intel_psr_default_link_standby(dev_priv);
+		break;
+	case 2:
+		link_standby = true;
+		break;
+	case 3:
+		link_standby = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	intel_runtime_pm_get(dev_priv);
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+retry:
+	ret = __i915_edp_psr_write(dev_priv, &ctx, val, link_standby);
+	if (ret == -EBUSY) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	intel_runtime_pm_put(dev_priv);
+
+	return ret ?: len;
+}
+
+static int i915_edp_psr_open(struct inode *inode, struct file *file)
+{
+	struct drm_i915_private *dev_priv = inode->i_private;
+
+	if (!HAS_PSR(dev_priv))
+		return -ENODEV;
+
+	return single_open(file, i915_edp_psr_status, dev_priv);
+}
+
+static const struct file_operations i915_edp_psr_ops = {
+	.owner = THIS_MODULE,
+	.open = i915_edp_psr_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = i915_edp_psr_write
+};
+
 static int i915_sink_crc(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4734,7 +4906,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_llc", i915_llc, 0},
-	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
@@ -4761,6 +4932,7 @@ static const struct i915_debugfs_files {
 	{"i915_wedged", &i915_wedged_fops},
 	{"i915_max_freq", &i915_max_freq_fops},
 	{"i915_min_freq", &i915_min_freq_fops},
+	{"i915_edp_psr_status", &i915_edp_psr_ops},
 	{"i915_cache_sharing", &i915_cache_sharing_fops},
 	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
 	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b39c5f68efb2..dbc9c062c658 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -608,6 +608,8 @@ struct i915_psr {
 	bool alpm;
 	bool has_hw_tracking;
 
+	bool global_enable;
+
 	void (*enable_source)(struct intel_dp *,
 			      const struct intel_crtc_state *);
 	void (*disable_source)(struct intel_dp *,
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 08108ce5be21..0d02980b3a2c 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -90,7 +90,7 @@ i915_param_named_unsafe(enable_ppgtt, int, 0400,
 	"Override PPGTT usage. "
 	"(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
 
-i915_param_named_unsafe(enable_psr, int, 0600,
+i915_param_named_unsafe(enable_psr, int, 0400,
 	"Enable PSR "
 	"(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) "
 	"Default: -1 (use per-chip default)");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1f0e8f1e4594..c486090f4f52 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1871,11 +1871,18 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 
 /* intel_psr.c */
 #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
+bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv);
 void intel_psr_init_dpcd(struct intel_dp *intel_dp);
 void intel_psr_enable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *crtc_state);
+void __intel_psr_enable(struct drm_i915_private *dev_priv,
+			struct intel_dp *intel_dp,
+			const struct intel_crtc_state *crtc_state);
 void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state);
+void __intel_psr_disable(struct drm_i915_private *dev_priv,
+			 struct intel_dp *intel_dp,
+			 const struct intel_crtc_state *old_crtc_state);
 void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 			  unsigned frontbuffer_bits,
 			  enum fb_op_origin origin);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 317cb4a12693..7f59faef7ea7 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,36 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv)
+{
+	/* Override link_standby x link_off defaults */
+	if (i915_modparams.enable_psr == 2) {
+		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
+		return true;
+	}
+
+	if (i915_modparams.enable_psr == 3) {
+		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
+		return false;
+	}
+
+	/* Set link_standby x link_off defaults */
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		/* HSW and BDW require workarounds that we don't implement. */
+		return false;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		/* On VLV and CHV only standby mode is supported. */
+		return true;
+	else
+		/* For new platforms let's respect VBT back again */
+		return dev_priv->vbt.psr.full_link;
+}
+
+static bool intel_psr_enabled(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->psr.enabled && dev_priv->psr.global_enable;
+}
+
 static inline enum intel_display_power_domain
 psr_aux_domain(struct intel_dp *intel_dp)
 {
@@ -502,11 +532,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (!CAN_PSR(dev_priv))
 		return;
 
-	if (!i915_modparams.enable_psr) {
-		DRM_DEBUG_KMS("PSR disable by flag\n");
-		return;
-	}
-
 	/*
 	 * HSW spec explicitly says PSR is tied to port A.
 	 * BDW+ platforms with DDI implementation of PSR have different
@@ -559,7 +584,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
 	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+
+	if (dev_priv->psr.global_enable)
+		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+	else
+		DRM_DEBUG_KMS("PSR disable by flag\n");
 }
 
 static void intel_psr_activate(struct intel_dp *intel_dp)
@@ -617,6 +646,32 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
 	}
 }
 
+void __intel_psr_enable(struct drm_i915_private *dev_priv,
+			struct intel_dp *intel_dp,
+			const struct intel_crtc_state *crtc_state)
+{
+	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
+	dev_priv->psr.enable_sink(intel_dp);
+	dev_priv->psr.enable_source(intel_dp, crtc_state);
+
+	if (INTEL_GEN(dev_priv) >= 9) {
+		intel_psr_activate(intel_dp);
+	} else {
+		/*
+		 * FIXME: Activation should happen immediately since this
+		 * function is just called after pipe is fully trained and
+		 * enabled.
+		 * However on some platforms we face issues when first
+		 * activation follows a modeset so quickly.
+		 *     - On VLV/CHV we get bank screen on first activation
+		 *     - On HSW/BDW we get a recoverable frozen screen until
+		 *       next exit-activate sequence.
+		 */
+		schedule_delayed_work(&dev_priv->psr.work,
+				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+	}
+}
+
 /**
  * intel_psr_enable - Enable PSR
  * @intel_dp: Intel DP
@@ -647,27 +702,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 	dev_priv->psr.psr2_support = crtc_state->has_psr2;
 	dev_priv->psr.busy_frontbuffer_bits = 0;
 
-	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
-	dev_priv->psr.enable_sink(intel_dp);
-	dev_priv->psr.enable_source(intel_dp, crtc_state);
 	dev_priv->psr.enabled = intel_dp;
 
-	if (INTEL_GEN(dev_priv) >= 9) {
-		intel_psr_activate(intel_dp);
-	} else {
-		/*
-		 * FIXME: Activation should happen immediately since this
-		 * function is just called after pipe is fully trained and
-		 * enabled.
-		 * However on some platforms we face issues when first
-		 * activation follows a modeset so quickly.
-		 *     - On VLV/CHV we get bank screen on first activation
-		 *     - On HSW/BDW we get a recoverable frozen screen until
-		 *       next exit-activate sequence.
-		 */
-		schedule_delayed_work(&dev_priv->psr.work,
-				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
-	}
+	if (dev_priv->psr.global_enable)
+		__intel_psr_enable(dev_priv, intel_dp, crtc_state);
 
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
@@ -752,6 +790,16 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
 	psr_aux_io_power_put(intel_dp);
 }
 
+void __intel_psr_disable(struct drm_i915_private *dev_priv,
+			 struct intel_dp *intel_dp,
+			 const struct intel_crtc_state *old_crtc_state)
+{
+	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
+
+	/* Disable PSR on Sink */
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+}
+
 /**
  * intel_psr_disable - Disable PSR
  * @intel_dp: Intel DP
@@ -773,15 +821,13 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (intel_dp != dev_priv->psr.enabled) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
 
-	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
-
-	/* Disable PSR on Sink */
-	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+	if (intel_psr_enabled(dev_priv))
+		__intel_psr_disable(dev_priv, intel_dp, old_crtc_state);
 
 	dev_priv->psr.enabled = NULL;
 	mutex_unlock(&dev_priv->psr.lock);
@@ -833,11 +879,11 @@ static void intel_psr_work(struct work_struct *work)
 		}
 	}
 	mutex_lock(&dev_priv->psr.lock);
-	intel_dp = dev_priv->psr.enabled;
-
-	if (!intel_dp)
+	if (!intel_psr_enabled(dev_priv))
 		goto unlock;
 
+	intel_dp = dev_priv->psr.enabled;
+
 	/*
 	 * The delayed work can race with an invalidate hence we need to
 	 * recheck. Since psr_flush first clears this and then reschedules we
@@ -933,7 +979,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -979,7 +1025,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -1022,7 +1068,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -1081,26 +1127,9 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
 	if (i915_modparams.enable_psr == -1)
 		i915_modparams.enable_psr = 0;
 
-	/* Set link_standby x link_off defaults */
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		/* HSW and BDW require workarounds that we don't implement. */
-		dev_priv->psr.link_standby = false;
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		/* On VLV and CHV only standby mode is supported. */
-		dev_priv->psr.link_standby = true;
-	else
-		/* For new platforms let's respect VBT back again */
-		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
+	dev_priv->psr.link_standby = intel_psr_default_link_standby(dev_priv);
 
-	/* Override link_standby x link_off defaults */
-	if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
-		dev_priv->psr.link_standby = true;
-	}
-	if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
-		dev_priv->psr.link_standby = false;
-	}
+	dev_priv->psr.global_enable = i915_modparams.enable_psr;
 
 	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
 	mutex_init(&dev_priv->psr.lock);
-- 
2.16.2

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

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

* ✗ Fi.CI.BAT: failure for drm/i915: Control PSR at runtime through debugfs only
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
@ 2018-03-14 12:32 ` Patchwork
  2018-03-14 15:58 ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-03-14 12:32 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only
URL   : https://patchwork.freedesktop.org/series/39955/
State : failure

== Summary ==

Series 39955v1 drm/i915: Control PSR at runtime through debugfs only
https://patchwork.freedesktop.org/api/1.0/series/39955/revisions/1/mbox/

---- Possible new issues:

Test kms_psr_sink_crc:
        Subgroup psr_basic:
                skip       -> FAIL       (fi-bdw-5557u)
                skip       -> FAIL       (fi-bdw-gvtdvm)
                skip       -> FAIL       (fi-blb-e6850)
                skip       -> FAIL       (fi-bsw-n3050)
                skip       -> FAIL       (fi-bxt-dsi)
                skip       -> FAIL       (fi-bxt-j4205)
                skip       -> FAIL       (fi-byt-n2820)
                skip       -> FAIL       (fi-cfl-8700k)
                pass       -> FAIL       (fi-cfl-s2)
                pass       -> FAIL       (fi-cfl-u)
                pass       -> FAIL       (fi-cnl-y3)
                skip       -> FAIL       (fi-gdg-551)
                pass       -> FAIL       (fi-glk-1)
                skip       -> FAIL       (fi-hsw-4770)
                skip       -> FAIL       (fi-ilk-650)
                skip       -> FAIL       (fi-ivb-3520m)
                skip       -> FAIL       (fi-ivb-3770)
                skip       -> FAIL       (fi-kbl-7500u)
                skip       -> FAIL       (fi-kbl-7567u)
                pass       -> FAIL       (fi-kbl-r)
                skip       -> FAIL       (fi-pnv-d510)
                skip       -> FAIL       (fi-skl-6260u)
                pass       -> FAIL       (fi-skl-6600u)
                pass       -> FAIL       (fi-skl-6700hq)
                skip       -> FAIL       (fi-skl-6700k2)
                skip       -> FAIL       (fi-skl-6770hq)
                skip       -> FAIL       (fi-skl-guc)
                skip       -> FAIL       (fi-skl-gvtdvm)
                skip       -> FAIL       (fi-snb-2600)

---- Known issues:

Test gem_mmap_gtt:
        Subgroup basic-small-bo-tiledx:
                fail       -> PASS       (fi-gdg-551) fdo#102575
Test kms_psr_sink_crc:
        Subgroup psr_basic:
                skip       -> FAIL       (fi-elk-e7500) fdo#105053

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

fi-bdw-5557u     total:288  pass:267  dwarn:0   dfail:0   fail:1   skip:20  time:436s
fi-bdw-gvtdvm    total:288  pass:264  dwarn:0   dfail:0   fail:1   skip:23  time:438s
fi-blb-e6850     total:288  pass:223  dwarn:1   dfail:0   fail:1   skip:63  time:381s
fi-bsw-n3050     total:288  pass:242  dwarn:0   dfail:0   fail:1   skip:45  time:528s
fi-bxt-dsi       total:288  pass:258  dwarn:0   dfail:0   fail:1   skip:29  time:506s
fi-bxt-j4205     total:288  pass:259  dwarn:0   dfail:0   fail:1   skip:28  time:508s
fi-byt-n2820     total:288  pass:249  dwarn:0   dfail:0   fail:1   skip:38  time:498s
fi-cfl-8700k     total:288  pass:260  dwarn:0   dfail:0   fail:1   skip:27  time:413s
fi-cfl-s2        total:288  pass:261  dwarn:0   dfail:0   fail:1   skip:26  time:577s
fi-cfl-u         total:288  pass:261  dwarn:0   dfail:0   fail:1   skip:26  time:510s
fi-cnl-y3        total:288  pass:261  dwarn:0   dfail:0   fail:1   skip:26  time:591s
fi-elk-e7500     total:288  pass:229  dwarn:0   dfail:0   fail:1   skip:58  time:425s
fi-gdg-551       total:288  pass:180  dwarn:0   dfail:0   fail:1   skip:107 time:319s
fi-glk-1         total:288  pass:259  dwarn:0   dfail:0   fail:1   skip:28  time:527s
fi-hsw-4770      total:288  pass:261  dwarn:0   dfail:0   fail:1   skip:26  time:403s
fi-ilk-650       total:288  pass:228  dwarn:0   dfail:0   fail:1   skip:59  time:419s
fi-ivb-3520m     total:288  pass:259  dwarn:0   dfail:0   fail:1   skip:28  time:474s
fi-ivb-3770      total:288  pass:255  dwarn:0   dfail:0   fail:1   skip:32  time:428s
fi-kbl-7500u     total:288  pass:263  dwarn:1   dfail:0   fail:1   skip:23  time:474s
fi-kbl-7567u     total:288  pass:268  dwarn:0   dfail:0   fail:1   skip:19  time:472s
fi-kbl-r         total:288  pass:260  dwarn:0   dfail:0   fail:1   skip:27  time:513s
fi-pnv-d510      total:288  pass:222  dwarn:1   dfail:0   fail:1   skip:64  time:661s
fi-skl-6260u     total:288  pass:268  dwarn:0   dfail:0   fail:1   skip:19  time:441s
fi-skl-6600u     total:288  pass:260  dwarn:0   dfail:0   fail:1   skip:27  time:525s
fi-skl-6700hq    total:288  pass:261  dwarn:0   dfail:0   fail:1   skip:26  time:542s
fi-skl-6700k2    total:288  pass:264  dwarn:0   dfail:0   fail:1   skip:23  time:507s
fi-skl-6770hq    total:288  pass:268  dwarn:0   dfail:0   fail:1   skip:19  time:493s
fi-skl-guc       total:288  pass:260  dwarn:0   dfail:0   fail:1   skip:27  time:427s
fi-skl-gvtdvm    total:288  pass:265  dwarn:0   dfail:0   fail:1   skip:22  time:437s
fi-snb-2600      total:288  pass:248  dwarn:0   dfail:0   fail:1   skip:39  time:398s
Blacklisted hosts:
fi-cnl-drrs      total:288  pass:257  dwarn:3   dfail:0   fail:1   skip:27  time:520s

311e6b74462acb3a57c9730334c501a75f4bd064 drm-tip: 2018y-03m-14d-10h-51m-46s UTC integration manifest
1ba8b4014a4f drm/i915: Control PSR at runtime through debugfs only

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8342/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
  2018-03-14 12:32 ` ✗ Fi.CI.BAT: failure for " Patchwork
@ 2018-03-14 15:58 ` Maarten Lankhorst
  2018-03-14 16:07   ` Chris Wilson
  2018-03-14 16:27 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-03-14 15:58 UTC (permalink / raw)
  To: intel-gfx

Currently tests modify i915.enable_psr and then do a modeset cycle
to change PSR. We can write a value to i915_edp_psr_status to force
a certain value without a modeset.

To retain compatibility with older userspace, we also still allow
the override through the module parameter, and add some tracking
to check whether a debugfs mode is specified.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 193 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_drv.h     |   7 ++
 drivers/gpu/drm/i915/intel_drv.h    |   7 ++
 drivers/gpu/drm/i915/intel_psr.c    | 155 ++++++++++++++++++-----------
 4 files changed, 301 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 574fcf234007..4abf8034d5c7 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2546,16 +2546,13 @@ static const char *psr2_live_status(u32 val)
 
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	struct drm_i915_private *dev_priv = m->private;
 	u32 psrperf = 0;
 	u32 stat[3];
 	enum pipe pipe;
 	bool enabled = false;
 	bool sink_support;
 
-	if (!HAS_PSR(dev_priv))
-		return -ENODEV;
-
 	sink_support = dev_priv->psr.sink_support;
 	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
 	if (!sink_support)
@@ -2631,6 +2628,192 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	return 0;
 }
 
+static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
+{
+	switch (mode) {
+	case PSR_DEBUGFS_MODE_DEFAULT: return i915_modparams.enable_psr;
+	case PSR_DEBUGFS_MODE_DISABLED: return false;
+	case PSR_DEBUGFS_MODE_ENABLED: return true;
+	}
+
+	/* GCC is stupid. */
+	return false;
+}
+
+static bool psr_needs_disable(struct drm_i915_private *dev_priv,
+			      bool enable, bool link_standby)
+{
+	if (!dev_priv->psr.hw_configured)
+		return false;
+
+	if (!enable)
+		return true;
+
+	if (dev_priv->psr.link_standby != link_standby)
+		return true;
+
+	return false;
+}
+
+static bool psr_needs_enable(struct drm_i915_private *dev_priv,
+			     bool enable)
+{
+	return enable && !dev_priv->psr.hw_configured;
+}
+
+static int __i915_edp_psr_write(struct drm_i915_private *dev_priv,
+				struct drm_modeset_acquire_ctx *ctx,
+				enum i915_psr_debugfs_mode mode,
+				bool link_standby)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	int ret;
+	bool needs_enable, found, enable;
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev_priv->psr.lock);
+retry:
+	if (!dev_priv->psr.enabled) {
+		dev_priv->psr.debugfs_mode = mode;
+		dev_priv->psr.link_standby = link_standby;
+		goto end;
+	}
+	encoder = &dp_to_dig_port(dev_priv->psr.enabled)->base.base;
+	mutex_unlock(&dev_priv->psr.lock);
+
+	found = false;
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter)
+		if (connector->state->best_encoder == encoder) {
+			found = true;
+			break;
+		}
+	drm_connector_list_iter_end(&conn_iter);
+
+	if (WARN_ON(!found))
+		return -EINVAL;
+
+	crtc = connector->state->crtc;
+	ret = drm_modeset_lock(&crtc->mutex, ctx);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev_priv->psr.lock);
+	enable = psr_global_enabled(mode);
+
+	if (dev_priv->psr.enabled != enc_to_intel_dp(encoder))
+		goto retry;
+
+	if ((connector->state->commit && !try_wait_for_completion(&connector->state->commit->hw_done)) ||
+	    (crtc->state->commit && !try_wait_for_completion(&crtc->state->commit->hw_done))) {
+		ret = -EBUSY;
+		goto end;
+	}
+
+	if (psr_needs_disable(dev_priv, enable, link_standby))
+		__intel_psr_disable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
+
+	needs_enable = psr_needs_enable(dev_priv, enable);
+	dev_priv->psr.debugfs_mode = mode;
+	dev_priv->psr.link_standby = link_standby;
+
+	if (needs_enable)
+		__intel_psr_enable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
+
+end:
+	mutex_unlock(&dev_priv->psr.lock);
+	return ret;
+}
+
+static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_i915_private *dev_priv = m->private;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret, val;
+	bool link_standby;
+	enum i915_psr_debugfs_mode mode;
+
+	if (!dev_priv->psr.sink_support)
+		return -ENODEV;
+
+	ret = kstrtoint_from_user(ubuf, len, 10, &val);
+	if (ret < 0) {
+		bool enable;
+		ret = kstrtobool_from_user(ubuf, len, &enable);
+
+		if (ret < 0)
+			return ret;
+
+		val = enable;
+	}
+
+	switch (val) {
+	case -1:
+	case 0:
+	case 1:
+		link_standby = intel_psr_default_link_standby(dev_priv);
+		mode = val;
+		break;
+	case 2:
+		mode = PSR_DEBUGFS_MODE_ENABLED;
+		link_standby = true;
+		break;
+	case 3:
+		mode = PSR_DEBUGFS_MODE_ENABLED;
+		link_standby = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	intel_runtime_pm_get(dev_priv);
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+retry:
+	ret = __i915_edp_psr_write(dev_priv, &ctx, mode, link_standby);
+	if (ret == -EBUSY) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	intel_runtime_pm_put(dev_priv);
+
+	return ret ?: len;
+}
+
+static int i915_edp_psr_open(struct inode *inode, struct file *file)
+{
+	struct drm_i915_private *dev_priv = inode->i_private;
+
+	if (!HAS_PSR(dev_priv))
+		return -ENODEV;
+
+	return single_open(file, i915_edp_psr_status, dev_priv);
+}
+
+static const struct file_operations i915_edp_psr_ops = {
+	.owner = THIS_MODULE,
+	.open = i915_edp_psr_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = i915_edp_psr_write
+};
+
 static int i915_sink_crc(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4734,7 +4917,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_llc", i915_llc, 0},
-	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
@@ -4761,6 +4943,7 @@ static const struct i915_debugfs_files {
 	{"i915_wedged", &i915_wedged_fops},
 	{"i915_max_freq", &i915_max_freq_fops},
 	{"i915_min_freq", &i915_min_freq_fops},
+	{"i915_edp_psr_status", &i915_edp_psr_ops},
 	{"i915_cache_sharing", &i915_cache_sharing_fops},
 	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
 	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b39c5f68efb2..6bf1c6d43f7a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -607,6 +607,13 @@ struct i915_psr {
 	bool colorimetry_support;
 	bool alpm;
 	bool has_hw_tracking;
+	bool hw_configured;
+
+	enum i915_psr_debugfs_mode {
+		PSR_DEBUGFS_MODE_DEFAULT,
+		PSR_DEBUGFS_MODE_DISABLED,
+		PSR_DEBUGFS_MODE_ENABLED
+	} debugfs_mode;
 
 	void (*enable_source)(struct intel_dp *,
 			      const struct intel_crtc_state *);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1f0e8f1e4594..c486090f4f52 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1871,11 +1871,18 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 
 /* intel_psr.c */
 #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
+bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv);
 void intel_psr_init_dpcd(struct intel_dp *intel_dp);
 void intel_psr_enable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *crtc_state);
+void __intel_psr_enable(struct drm_i915_private *dev_priv,
+			struct intel_dp *intel_dp,
+			const struct intel_crtc_state *crtc_state);
 void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state);
+void __intel_psr_disable(struct drm_i915_private *dev_priv,
+			 struct intel_dp *intel_dp,
+			 const struct intel_crtc_state *old_crtc_state);
 void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 			  unsigned frontbuffer_bits,
 			  enum fb_op_origin origin);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 317cb4a12693..cfce5861b9ad 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,48 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv)
+{
+	/* Override link_standby x link_off defaults */
+	if (i915_modparams.enable_psr == 2) {
+		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
+		return true;
+	}
+
+	if (i915_modparams.enable_psr == 3) {
+		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
+		return false;
+	}
+
+	/* Set link_standby x link_off defaults */
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		/* HSW and BDW require workarounds that we don't implement. */
+		return false;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		/* On VLV and CHV only standby mode is supported. */
+		return true;
+	else
+		/* For new platforms let's respect VBT back again */
+		return dev_priv->vbt.psr.full_link;
+}
+
+static bool intel_psr_global_enabled(struct drm_i915_private *dev_priv)
+{
+	switch (dev_priv->psr.debugfs_mode) {
+	case PSR_DEBUGFS_MODE_DEFAULT: return i915_modparams.enable_psr;
+	case PSR_DEBUGFS_MODE_DISABLED: return false;
+	case PSR_DEBUGFS_MODE_ENABLED: return true;
+	}
+
+	/* GCC is stupid. */
+	return false;
+}
+
+static bool intel_psr_enabled(struct drm_i915_private *dev_priv)
+{
+	return dev_priv->psr.enabled && dev_priv->psr.hw_configured;
+}
+
 static inline enum intel_display_power_domain
 psr_aux_domain(struct intel_dp *intel_dp)
 {
@@ -502,11 +544,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (!CAN_PSR(dev_priv))
 		return;
 
-	if (!i915_modparams.enable_psr) {
-		DRM_DEBUG_KMS("PSR disable by flag\n");
-		return;
-	}
-
 	/*
 	 * HSW spec explicitly says PSR is tied to port A.
 	 * BDW+ platforms with DDI implementation of PSR have different
@@ -559,7 +596,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
 	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+
+	if (intel_psr_global_enabled(dev_priv))
+		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+	else
+		DRM_DEBUG_KMS("PSR disable by flag\n");
 }
 
 static void intel_psr_activate(struct intel_dp *intel_dp)
@@ -617,6 +658,34 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
 	}
 }
 
+void __intel_psr_enable(struct drm_i915_private *dev_priv,
+			struct intel_dp *intel_dp,
+			const struct intel_crtc_state *crtc_state)
+{
+	dev_priv->psr.hw_configured = true;
+
+	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
+	dev_priv->psr.enable_sink(intel_dp);
+	dev_priv->psr.enable_source(intel_dp, crtc_state);
+
+	if (INTEL_GEN(dev_priv) >= 9) {
+		intel_psr_activate(intel_dp);
+	} else {
+		/*
+		 * FIXME: Activation should happen immediately since this
+		 * function is just called after pipe is fully trained and
+		 * enabled.
+		 * However on some platforms we face issues when first
+		 * activation follows a modeset so quickly.
+		 *     - On VLV/CHV we get bank screen on first activation
+		 *     - On HSW/BDW we get a recoverable frozen screen until
+		 *       next exit-activate sequence.
+		 */
+		schedule_delayed_work(&dev_priv->psr.work,
+				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+	}
+}
+
 /**
  * intel_psr_enable - Enable PSR
  * @intel_dp: Intel DP
@@ -647,27 +716,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 	dev_priv->psr.psr2_support = crtc_state->has_psr2;
 	dev_priv->psr.busy_frontbuffer_bits = 0;
 
-	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
-	dev_priv->psr.enable_sink(intel_dp);
-	dev_priv->psr.enable_source(intel_dp, crtc_state);
 	dev_priv->psr.enabled = intel_dp;
 
-	if (INTEL_GEN(dev_priv) >= 9) {
-		intel_psr_activate(intel_dp);
-	} else {
-		/*
-		 * FIXME: Activation should happen immediately since this
-		 * function is just called after pipe is fully trained and
-		 * enabled.
-		 * However on some platforms we face issues when first
-		 * activation follows a modeset so quickly.
-		 *     - On VLV/CHV we get bank screen on first activation
-		 *     - On HSW/BDW we get a recoverable frozen screen until
-		 *       next exit-activate sequence.
-		 */
-		schedule_delayed_work(&dev_priv->psr.work,
-				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
-	}
+	if (intel_psr_global_enabled(dev_priv))
+		__intel_psr_enable(dev_priv, intel_dp, crtc_state);
 
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
@@ -752,6 +804,17 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
 	psr_aux_io_power_put(intel_dp);
 }
 
+void __intel_psr_disable(struct drm_i915_private *dev_priv,
+			 struct intel_dp *intel_dp,
+			 const struct intel_crtc_state *old_crtc_state)
+{
+	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
+
+	/* Disable PSR on Sink */
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+	dev_priv->psr.hw_configured = false;
+}
+
 /**
  * intel_psr_disable - Disable PSR
  * @intel_dp: Intel DP
@@ -773,15 +836,13 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (intel_dp != dev_priv->psr.enabled) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
 
-	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
-
-	/* Disable PSR on Sink */
-	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+	if (intel_psr_enabled(dev_priv))
+		__intel_psr_disable(dev_priv, intel_dp, old_crtc_state);
 
 	dev_priv->psr.enabled = NULL;
 	mutex_unlock(&dev_priv->psr.lock);
@@ -833,11 +894,11 @@ static void intel_psr_work(struct work_struct *work)
 		}
 	}
 	mutex_lock(&dev_priv->psr.lock);
-	intel_dp = dev_priv->psr.enabled;
-
-	if (!intel_dp)
+	if (!intel_psr_enabled(dev_priv))
 		goto unlock;
 
+	intel_dp = dev_priv->psr.enabled;
+
 	/*
 	 * The delayed work can race with an invalidate hence we need to
 	 * recheck. Since psr_flush first clears this and then reschedules we
@@ -933,7 +994,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -979,7 +1040,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -1022,7 +1083,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (!intel_psr_enabled(dev_priv)) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
@@ -1081,26 +1142,8 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
 	if (i915_modparams.enable_psr == -1)
 		i915_modparams.enable_psr = 0;
 
-	/* Set link_standby x link_off defaults */
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		/* HSW and BDW require workarounds that we don't implement. */
-		dev_priv->psr.link_standby = false;
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		/* On VLV and CHV only standby mode is supported. */
-		dev_priv->psr.link_standby = true;
-	else
-		/* For new platforms let's respect VBT back again */
-		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
-
-	/* Override link_standby x link_off defaults */
-	if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
-		dev_priv->psr.link_standby = true;
-	}
-	if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
-		dev_priv->psr.link_standby = false;
-	}
+	dev_priv->psr.link_standby = intel_psr_default_link_standby(dev_priv);
+	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
 
 	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
 	mutex_init(&dev_priv->psr.lock);
-- 
2.16.2

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

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-14 15:58 ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
@ 2018-03-14 16:07   ` Chris Wilson
  2018-03-14 16:11     ` Maarten Lankhorst
  0 siblings, 1 reply; 31+ messages in thread
From: Chris Wilson @ 2018-03-14 16:07 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx

Quoting Maarten Lankhorst (2018-03-14 15:58:32)
> Currently tests modify i915.enable_psr and then do a modeset cycle
> to change PSR. We can write a value to i915_edp_psr_status to force
> a certain value without a modeset.
> 
> To retain compatibility with older userspace, we also still allow
> the override through the module parameter, and add some tracking
> to check whether a debugfs mode is specified.

Is it possible for you to mandate that the process holds the file open
for as long as it wants its value to hold. Then we can automatically
clean up if the process dies; without requiring userspace to dig itself
out of a hole.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-14 16:07   ` Chris Wilson
@ 2018-03-14 16:11     ` Maarten Lankhorst
  0 siblings, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-03-14 16:11 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

Op 14-03-18 om 17:07 schreef Chris Wilson:
> Quoting Maarten Lankhorst (2018-03-14 15:58:32)
>> Currently tests modify i915.enable_psr and then do a modeset cycle
>> to change PSR. We can write a value to i915_edp_psr_status to force
>> a certain value without a modeset.
>>
>> To retain compatibility with older userspace, we also still allow
>> the override through the module parameter, and add some tracking
>> to check whether a debugfs mode is specified.
> Is it possible for you to mandate that the process holds the file open
> for as long as it wants its value to hold. Then we can automatically
> clean up if the process dies; without requiring userspace to dig itself
> out of a hole.
> -Chris

For testing PSR someone might directly echo values to the debugfs file, so I didn't want to keep the fd handle as reference count..

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

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

* ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev2)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
  2018-03-14 12:32 ` ✗ Fi.CI.BAT: failure for " Patchwork
  2018-03-14 15:58 ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
@ 2018-03-14 16:27 ` Patchwork
  2018-03-14 21:53 ` [PATCH] drm/i915: Control PSR at runtime through debugfs only Rodrigo Vivi
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-03-14 16:27 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev2)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

Series 39955v2 drm/i915: Control PSR at runtime through debugfs only
https://patchwork.freedesktop.org/api/1.0/series/39955/revisions/2/mbox/

fi-bdw-5557u     total:288  pass:267  dwarn:0   dfail:0   fail:0   skip:21  time:436s
fi-bdw-gvtdvm    total:288  pass:264  dwarn:0   dfail:0   fail:0   skip:24  time:448s
fi-blb-e6850     total:288  pass:223  dwarn:1   dfail:0   fail:0   skip:64  time:379s
fi-bsw-n3050     total:288  pass:242  dwarn:0   dfail:0   fail:0   skip:46  time:543s
fi-bwr-2160      total:288  pass:183  dwarn:0   dfail:0   fail:0   skip:105 time:298s
fi-bxt-j4205     total:288  pass:259  dwarn:0   dfail:0   fail:0   skip:29  time:508s
fi-byt-j1900     total:288  pass:253  dwarn:0   dfail:0   fail:0   skip:35  time:525s
fi-byt-n2820     total:288  pass:249  dwarn:0   dfail:0   fail:0   skip:39  time:506s
fi-cfl-8700k     total:288  pass:260  dwarn:0   dfail:0   fail:0   skip:28  time:413s
fi-cfl-u         total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:509s
fi-cnl-y3        total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:586s
fi-elk-e7500     total:288  pass:229  dwarn:0   dfail:0   fail:0   skip:59  time:427s
fi-gdg-551       total:288  pass:179  dwarn:0   dfail:0   fail:1   skip:108 time:319s
fi-hsw-4770      total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:402s
fi-ivb-3520m     total:288  pass:259  dwarn:0   dfail:0   fail:0   skip:29  time:476s
fi-ivb-3770      total:288  pass:255  dwarn:0   dfail:0   fail:0   skip:33  time:430s
fi-kbl-7567u     total:288  pass:268  dwarn:0   dfail:0   fail:0   skip:20  time:470s
fi-kbl-r         total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:515s
fi-pnv-d510      total:288  pass:222  dwarn:1   dfail:0   fail:0   skip:65  time:657s
fi-skl-6260u     total:288  pass:268  dwarn:0   dfail:0   fail:0   skip:20  time:438s
fi-skl-6600u     total:288  pass:261  dwarn:0   dfail:0   fail:0   skip:27  time:527s
fi-skl-6700hq    total:288  pass:262  dwarn:0   dfail:0   fail:0   skip:26  time:539s
fi-skl-6700k2    total:288  pass:264  dwarn:0   dfail:0   fail:0   skip:24  time:509s
fi-skl-guc       total:288  pass:260  dwarn:0   dfail:0   fail:0   skip:28  time:429s
fi-snb-2520m     total:288  pass:248  dwarn:0   dfail:0   fail:0   skip:40  time:596s
fi-snb-2600      total:288  pass:248  dwarn:0   dfail:0   fail:0   skip:40  time:399s
Blacklisted hosts:
fi-cnl-drrs      total:288  pass:257  dwarn:3   dfail:0   fail:0   skip:28  time:516s

f25b08dcf09c72da5a530dca49a4b93bd6d75395 drm-tip: 2018y-03m-14d-14h-33m-13s UTC integration manifest
0325fffb04c8 drm/i915: Allow control of PSR at runtime through debugfs.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8346/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Control PSR at runtime through debugfs only
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (2 preceding siblings ...)
  2018-03-14 16:27 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
@ 2018-03-14 21:53 ` Rodrigo Vivi
  2018-03-15 10:28   ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
  2018-03-15  0:58 ` ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 31+ messages in thread
From: Rodrigo Vivi @ 2018-03-14 21:53 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

On Wed, Mar 14, 2018 at 12:46:58PM +0100, Maarten Lankhorst wrote:
> Allow controlling link status through i915_edp_psr_status, in the same way kernel does.
> This replaces changing the module parameter at runtime, then forcing a modeset.
> 
> Writing -1 restores the original PSR mode set through the module parameter.
> Writing 0 disables PSR.
> Writing 1 enables PSR with default link standby mode.
> Writing 2 enables PSR with link standby.
> Writing 3 enables PSR with link standby disabled.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
> This breaks kms_frontbuffer_tracking, and needs the following patch to work:
> https://patchwork.freedesktop.org/patch/209956/
> 
> XXX: Make global_enable a tristate, to keep older versions of kms_frontbuffer_tracking working?
> 
>  drivers/gpu/drm/i915/i915_debugfs.c | 182 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/i915_drv.h     |   2 +
>  drivers/gpu/drm/i915/i915_params.c  |   2 +-
>  drivers/gpu/drm/i915/intel_drv.h    |   7 ++
>  drivers/gpu/drm/i915/intel_psr.c    | 139 ++++++++++++++++-----------
>  5 files changed, 271 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 574fcf234007..534a3b04e6a3 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2546,16 +2546,13 @@ static const char *psr2_live_status(u32 val)
>  
>  static int i915_edp_psr_status(struct seq_file *m, void *data)
>  {
> -	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> +	struct drm_i915_private *dev_priv = m->private;
>  	u32 psrperf = 0;
>  	u32 stat[3];
>  	enum pipe pipe;
>  	bool enabled = false;
>  	bool sink_support;
>  
> -	if (!HAS_PSR(dev_priv))
> -		return -ENODEV;
> -
>  	sink_support = dev_priv->psr.sink_support;
>  	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
>  	if (!sink_support)
> @@ -2631,6 +2628,181 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  	return 0;
>  }
>  
> +static bool psr_needs_disable(struct drm_i915_private *dev_priv,
> +			      bool enable, bool link_standby)
> +{
> +	if (!dev_priv->psr.global_enable)
> +		return false;
> +
> +	if (!enable)
> +		return true;
> +
> +	if (dev_priv->psr.link_standby != link_standby)
> +		return true;
> +
> +	return false;
> +}
> +
> +static bool psr_needs_enable(struct drm_i915_private *dev_priv,
> +			     bool enable)
> +{
> +	if (!enable)
> +		return false;
> +
> +	return !dev_priv->psr.global_enable;
> +}
> +
> +static int __i915_edp_psr_write(struct drm_i915_private *dev_priv,
> +				struct drm_modeset_acquire_ctx *ctx,
> +				bool enable, bool link_standby)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_connector *connector;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +	int ret;
> +	bool needs_enable, found;
> +
> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
> +	if (ret)
> +		return ret;
> +
> +	mutex_lock(&dev_priv->psr.lock);
> +retry:
> +	if (!dev_priv->psr.enabled) {
> +		dev_priv->psr.global_enable = enable;
> +		dev_priv->psr.link_standby = link_standby;
> +		goto end;
> +	}
> +	encoder = &dp_to_dig_port(dev_priv->psr.enabled)->base.base;
> +	mutex_unlock(&dev_priv->psr.lock);
> +
> +	found = false;
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter)
> +		if (connector->state->best_encoder == encoder) {
> +			found = true;
> +			break;
> +		}
> +	drm_connector_list_iter_end(&conn_iter);
> +
> +	if (WARN_ON(!found))
> +		return -EINVAL;
> +
> +	crtc = connector->state->crtc;
> +	ret = drm_modeset_lock(&crtc->mutex, ctx);
> +	if (ret)
> +		return ret;
> +
> +	mutex_lock(&dev_priv->psr.lock);
> +	if (dev_priv->psr.enabled != enc_to_intel_dp(encoder))
> +		goto retry;
> +
> +	if ((connector->state->commit && !try_wait_for_completion(&connector->state->commit->hw_done)) ||
> +	    (crtc->state->commit && !try_wait_for_completion(&crtc->state->commit->hw_done))) {
> +		ret = -EBUSY;
> +		goto end;
> +	}
> +
> +	if (psr_needs_disable(dev_priv, enable, link_standby)) {
> +		__intel_psr_disable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
> +		dev_priv->psr.global_enable = false;
> +	}
> +
> +	needs_enable = psr_needs_enable(dev_priv, enable);
> +	dev_priv->psr.global_enable = enable;
> +	dev_priv->psr.link_standby = link_standby;
> +
> +	if (needs_enable)
> +		__intel_psr_enable(dev_priv, dev_priv->psr.enabled, to_intel_crtc_state(crtc->state));
> +
> +end:
> +	mutex_unlock(&dev_priv->psr.lock);
> +	return ret;
> +}
> +
> +static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
> +				  size_t len, loff_t *offp)
> +{
> +	struct seq_file *m = file->private_data;
> +	struct drm_i915_private *dev_priv = m->private;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret, val;
> +	bool link_standby;
> +
> +	if (!dev_priv->psr.sink_support)
> +		return -ENODEV;
> +
> +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
> +	if (ret < 0) {
> +		bool enable;
> +		ret = kstrtobool_from_user(ubuf, len, &enable);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		val = enable;
> +	}
> +
> +	/* -1 -> reset to default */
> +	if (val == -1)
> +		val = i915_modparams.enable_psr;
> +
> +	switch (val) {
> +	case 0:
> +	case 1:
> +		link_standby = intel_psr_default_link_standby(dev_priv);
> +		break;
> +	case 2:
> +		link_standby = true;
> +		break;
> +	case 3:
> +		link_standby = false;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	intel_runtime_pm_get(dev_priv);
> +
> +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +retry:
> +	ret = __i915_edp_psr_write(dev_priv, &ctx, val, link_standby);
> +	if (ret == -EBUSY) {
> +		ret = drm_modeset_backoff(&ctx);
> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	intel_runtime_pm_put(dev_priv);
> +
> +	return ret ?: len;
> +}
> +
> +static int i915_edp_psr_open(struct inode *inode, struct file *file)
> +{
> +	struct drm_i915_private *dev_priv = inode->i_private;
> +
> +	if (!HAS_PSR(dev_priv))
> +		return -ENODEV;
> +
> +	return single_open(file, i915_edp_psr_status, dev_priv);
> +}
> +
> +static const struct file_operations i915_edp_psr_ops = {
> +	.owner = THIS_MODULE,
> +	.open = i915_edp_psr_open,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +	.write = i915_edp_psr_write
> +};
> +
>  static int i915_sink_crc(struct seq_file *m, void *data)
>  {
>  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> @@ -4734,7 +4906,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
>  	{"i915_swizzle_info", i915_swizzle_info, 0},
>  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
>  	{"i915_llc", i915_llc, 0},
> -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
>  	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
>  	{"i915_energy_uJ", i915_energy_uJ, 0},
>  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
> @@ -4761,6 +4932,7 @@ static const struct i915_debugfs_files {
>  	{"i915_wedged", &i915_wedged_fops},
>  	{"i915_max_freq", &i915_max_freq_fops},
>  	{"i915_min_freq", &i915_min_freq_fops},
> +	{"i915_edp_psr_status", &i915_edp_psr_ops},
>  	{"i915_cache_sharing", &i915_cache_sharing_fops},
>  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
>  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index b39c5f68efb2..dbc9c062c658 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -608,6 +608,8 @@ struct i915_psr {
>  	bool alpm;
>  	bool has_hw_tracking;
>  
> +	bool global_enable;
> +
>  	void (*enable_source)(struct intel_dp *,
>  			      const struct intel_crtc_state *);
>  	void (*disable_source)(struct intel_dp *,
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index 08108ce5be21..0d02980b3a2c 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -90,7 +90,7 @@ i915_param_named_unsafe(enable_ppgtt, int, 0400,
>  	"Override PPGTT usage. "
>  	"(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
>  
> -i915_param_named_unsafe(enable_psr, int, 0600,
> +i915_param_named_unsafe(enable_psr, int, 0400,
>  	"Enable PSR "
>  	"(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) "
>  	"Default: -1 (use per-chip default)");
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1f0e8f1e4594..c486090f4f52 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1871,11 +1871,18 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
>  
>  /* intel_psr.c */
>  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
> +bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv);
>  void intel_psr_init_dpcd(struct intel_dp *intel_dp);
>  void intel_psr_enable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state *crtc_state);
> +void __intel_psr_enable(struct drm_i915_private *dev_priv,
> +			struct intel_dp *intel_dp,
> +			const struct intel_crtc_state *crtc_state);
>  void intel_psr_disable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state *old_crtc_state);
> +void __intel_psr_disable(struct drm_i915_private *dev_priv,
> +			 struct intel_dp *intel_dp,
> +			 const struct intel_crtc_state *old_crtc_state);

I don't like exporting around functions with "_"

also I don't believe you need dev_priv and intel_dp.

But why don't simply add another function parameter for disable and enable?
something like:
void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state, bool block);

void intel_psr_enable(struct intel_dp *intel_dp,
  		      const struct intel_crtc_state *crtc_state, bool unblock);

And maybe we will need a sort for referrence count on this block
because the same mechanism could be used when we need to disable aux for mutex
transactions for instance.

>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  			  unsigned frontbuffer_bits,
>  			  enum fb_op_origin origin);
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index 317cb4a12693..7f59faef7ea7 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -56,6 +56,36 @@
>  #include "intel_drv.h"
>  #include "i915_drv.h"
>  
> +bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv)
> +{
> +	/* Override link_standby x link_off defaults */
> +	if (i915_modparams.enable_psr == 2) {
> +		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
> +		return true;
> +	}
> +
> +	if (i915_modparams.enable_psr == 3) {
> +		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
> +		return false;
> +	}
> +
> +	/* Set link_standby x link_off defaults */
> +	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> +		/* HSW and BDW require workarounds that we don't implement. */
> +		return false;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		/* On VLV and CHV only standby mode is supported. */
> +		return true;
> +	else
> +		/* For new platforms let's respect VBT back again */
> +		return dev_priv->vbt.psr.full_link;
> +}
> +
> +static bool intel_psr_enabled(struct drm_i915_private *dev_priv)
> +{
> +	return dev_priv->psr.enabled && dev_priv->psr.global_enable;
> +}
> +
>  static inline enum intel_display_power_domain
>  psr_aux_domain(struct intel_dp *intel_dp)
>  {
> @@ -502,11 +532,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
>  	if (!CAN_PSR(dev_priv))
>  		return;
>  
> -	if (!i915_modparams.enable_psr) {
> -		DRM_DEBUG_KMS("PSR disable by flag\n");
> -		return;
> -	}
> -
>  	/*
>  	 * HSW spec explicitly says PSR is tied to port A.
>  	 * BDW+ platforms with DDI implementation of PSR have different
> @@ -559,7 +584,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
>  
>  	crtc_state->has_psr = true;
>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
> +
> +	if (dev_priv->psr.global_enable)
> +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
> +	else
> +		DRM_DEBUG_KMS("PSR disable by flag\n");
>  }
>  
>  static void intel_psr_activate(struct intel_dp *intel_dp)
> @@ -617,6 +646,32 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
>  	}
>  }
>  
> +void __intel_psr_enable(struct drm_i915_private *dev_priv,
> +			struct intel_dp *intel_dp,
> +			const struct intel_crtc_state *crtc_state)
> +{
> +	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
> +	dev_priv->psr.enable_sink(intel_dp);
> +	dev_priv->psr.enable_source(intel_dp, crtc_state);
> +
> +	if (INTEL_GEN(dev_priv) >= 9) {
> +		intel_psr_activate(intel_dp);
> +	} else {
> +		/*
> +		 * FIXME: Activation should happen immediately since this
> +		 * function is just called after pipe is fully trained and
> +		 * enabled.
> +		 * However on some platforms we face issues when first
> +		 * activation follows a modeset so quickly.
> +		 *     - On VLV/CHV we get bank screen on first activation
> +		 *     - On HSW/BDW we get a recoverable frozen screen until
> +		 *       next exit-activate sequence.
> +		 */
> +		schedule_delayed_work(&dev_priv->psr.work,
> +				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
> +	}
> +}
> +
>  /**
>   * intel_psr_enable - Enable PSR
>   * @intel_dp: Intel DP
> @@ -647,27 +702,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  	dev_priv->psr.psr2_support = crtc_state->has_psr2;
>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>  
> -	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
> -	dev_priv->psr.enable_sink(intel_dp);
> -	dev_priv->psr.enable_source(intel_dp, crtc_state);
>  	dev_priv->psr.enabled = intel_dp;
>  
> -	if (INTEL_GEN(dev_priv) >= 9) {
> -		intel_psr_activate(intel_dp);
> -	} else {
> -		/*
> -		 * FIXME: Activation should happen immediately since this
> -		 * function is just called after pipe is fully trained and
> -		 * enabled.
> -		 * However on some platforms we face issues when first
> -		 * activation follows a modeset so quickly.
> -		 *     - On VLV/CHV we get bank screen on first activation
> -		 *     - On HSW/BDW we get a recoverable frozen screen until
> -		 *       next exit-activate sequence.
> -		 */
> -		schedule_delayed_work(&dev_priv->psr.work,
> -				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
> -	}
> +	if (dev_priv->psr.global_enable)
> +		__intel_psr_enable(dev_priv, intel_dp, crtc_state);
>  
>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
> @@ -752,6 +790,16 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
>  	psr_aux_io_power_put(intel_dp);
>  }
>  
> +void __intel_psr_disable(struct drm_i915_private *dev_priv,
> +			 struct intel_dp *intel_dp,
> +			 const struct intel_crtc_state *old_crtc_state)
> +{
> +	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
> +
> +	/* Disable PSR on Sink */
> +	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
> +}
> +
>  /**
>   * intel_psr_disable - Disable PSR
>   * @intel_dp: Intel DP
> @@ -773,15 +821,13 @@ void intel_psr_disable(struct intel_dp *intel_dp,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (!dev_priv->psr.enabled) {
> +	if (intel_dp != dev_priv->psr.enabled) {
>  		mutex_unlock(&dev_priv->psr.lock);
>  		return;
>  	}
>  
> -	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
> -
> -	/* Disable PSR on Sink */
> -	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
> +	if (intel_psr_enabled(dev_priv))
> +		__intel_psr_disable(dev_priv, intel_dp, old_crtc_state);
>  
>  	dev_priv->psr.enabled = NULL;
>  	mutex_unlock(&dev_priv->psr.lock);
> @@ -833,11 +879,11 @@ static void intel_psr_work(struct work_struct *work)
>  		}
>  	}
>  	mutex_lock(&dev_priv->psr.lock);
> -	intel_dp = dev_priv->psr.enabled;
> -
> -	if (!intel_dp)
> +	if (!intel_psr_enabled(dev_priv))
>  		goto unlock;
>  
> +	intel_dp = dev_priv->psr.enabled;
> +
>  	/*
>  	 * The delayed work can race with an invalidate hence we need to
>  	 * recheck. Since psr_flush first clears this and then reschedules we
> @@ -933,7 +979,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (!dev_priv->psr.enabled) {
> +	if (!intel_psr_enabled(dev_priv)) {
>  		mutex_unlock(&dev_priv->psr.lock);
>  		return;
>  	}
> @@ -979,7 +1025,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (!dev_priv->psr.enabled) {
> +	if (!intel_psr_enabled(dev_priv)) {
>  		mutex_unlock(&dev_priv->psr.lock);
>  		return;
>  	}
> @@ -1022,7 +1068,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (!dev_priv->psr.enabled) {
> +	if (!intel_psr_enabled(dev_priv)) {
>  		mutex_unlock(&dev_priv->psr.lock);
>  		return;
>  	}
> @@ -1081,26 +1127,9 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
>  	if (i915_modparams.enable_psr == -1)
>  		i915_modparams.enable_psr = 0;
>  
> -	/* Set link_standby x link_off defaults */
> -	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> -		/* HSW and BDW require workarounds that we don't implement. */
> -		dev_priv->psr.link_standby = false;
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		/* On VLV and CHV only standby mode is supported. */
> -		dev_priv->psr.link_standby = true;
> -	else
> -		/* For new platforms let's respect VBT back again */
> -		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
> +	dev_priv->psr.link_standby = intel_psr_default_link_standby(dev_priv);
>  
> -	/* Override link_standby x link_off defaults */
> -	if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) {
> -		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
> -		dev_priv->psr.link_standby = true;
> -	}
> -	if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) {
> -		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
> -		dev_priv->psr.link_standby = false;
> -	}
> +	dev_priv->psr.global_enable = i915_modparams.enable_psr;
>  
>  	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
>  	mutex_init(&dev_priv->psr.lock);
> -- 
> 2.16.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev2)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (3 preceding siblings ...)
  2018-03-14 21:53 ` [PATCH] drm/i915: Control PSR at runtime through debugfs only Rodrigo Vivi
@ 2018-03-15  0:58 ` Patchwork
  2018-03-15 11:01 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev3) Patchwork
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-03-15  0:58 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev2)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

---- Known issues:

Test gem_eio:
        Subgroup in-flight:
                incomplete -> PASS       (shard-apl) fdo#105341
Test kms_chv_cursor_fail:
        Subgroup pipe-c-128x128-bottom-edge:
                fail       -> PASS       (shard-apl) fdo#105185
Test kms_flip:
        Subgroup plain-flip-fb-recreate:
                pass       -> FAIL       (shard-hsw) fdo#100368 +2
Test perf:
        Subgroup polling:
                fail       -> PASS       (shard-hsw) fdo#102252

fdo#105341 https://bugs.freedesktop.org/show_bug.cgi?id=105341
fdo#105185 https://bugs.freedesktop.org/show_bug.cgi?id=105185
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#102252 https://bugs.freedesktop.org/show_bug.cgi?id=102252

shard-apl        total:3444 pass:1816 dwarn:1   dfail:0   fail:7   skip:1619 time:13096s
shard-hsw        total:3444 pass:1767 dwarn:1   dfail:0   fail:4   skip:1671 time:11950s
shard-snb        total:3444 pass:1360 dwarn:1   dfail:0   fail:2   skip:2081 time:7226s
Blacklisted hosts:
shard-kbl        total:3368 pass:1902 dwarn:1   dfail:0   fail:9   skip:1454 time:9437s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8346/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-14 21:53 ` [PATCH] drm/i915: Control PSR at runtime through debugfs only Rodrigo Vivi
@ 2018-03-15 10:28   ` Maarten Lankhorst
  2018-03-22  1:45     ` Pandiyan, Dhinakaran
  0 siblings, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-03-15 10:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi

Currently tests modify i915.enable_psr and then do a modeset cycle
to change PSR. We can write a value to i915_edp_psr_status to force
a certain value without a modeset.

To retain compatibility with older userspace, we also still allow
the override through the module parameter, and add some tracking
to check whether a debugfs mode is specified.

Changes since v1:
- Rename dev_priv->psr.enabled to .dp, and .hw_configured to .enabled.
- Fix i915_psr_debugfs_mode to match the writes to debugfs.
- Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
  it and move it to intel_psr.c. This keeps all internals in intel_psr.c
- Perform an interruptible wait for hw completion outside of the psr
  lock, instead of being forced to trywait and return -EBUSY.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  73 +++++++++-
 drivers/gpu/drm/i915/i915_drv.h     |  11 +-
 drivers/gpu/drm/i915/intel_drv.h    |   3 +
 drivers/gpu/drm/i915/intel_psr.c    | 262 +++++++++++++++++++++++++++---------
 4 files changed, 281 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 574fcf234007..98e169636f86 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2546,16 +2546,13 @@ static const char *psr2_live_status(u32 val)
 
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	struct drm_i915_private *dev_priv = m->private;
 	u32 psrperf = 0;
 	u32 stat[3];
 	enum pipe pipe;
 	bool enabled = false;
 	bool sink_support;
 
-	if (!HAS_PSR(dev_priv))
-		return -ENODEV;
-
 	sink_support = dev_priv->psr.sink_support;
 	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
 	if (!sink_support)
@@ -2564,7 +2561,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->psr.lock);
-	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
+	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
 	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
 		   dev_priv->psr.busy_frontbuffer_bits);
 	seq_printf(m, "Re-enable work scheduled: %s\n",
@@ -2631,6 +2628,70 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	return 0;
 }
 
+static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_i915_private *dev_priv = m->private;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret, val;
+
+	if (!dev_priv->psr.sink_support)
+		return -ENODEV;
+
+	ret = kstrtoint_from_user(ubuf, len, 10, &val);
+	if (ret < 0) {
+		bool enable;
+		ret = kstrtobool_from_user(ubuf, len, &enable);
+
+		if (ret < 0)
+			return ret;
+
+		val = enable;
+	}
+
+	if (val < -1 || val > 3)
+		return -EINVAL;
+
+	intel_runtime_pm_get(dev_priv);
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+retry:
+	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
+	if (ret == -EBUSY) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	intel_runtime_pm_put(dev_priv);
+
+	return ret ?: len;
+}
+
+static int i915_edp_psr_open(struct inode *inode, struct file *file)
+{
+	struct drm_i915_private *dev_priv = inode->i_private;
+
+	if (!HAS_PSR(dev_priv))
+		return -ENODEV;
+
+	return single_open(file, i915_edp_psr_status, dev_priv);
+}
+
+static const struct file_operations i915_edp_psr_ops = {
+	.owner = THIS_MODULE,
+	.open = i915_edp_psr_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = i915_edp_psr_write
+};
+
 static int i915_sink_crc(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4734,7 +4795,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_llc", i915_llc, 0},
-	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
@@ -4761,6 +4821,7 @@ static const struct i915_debugfs_files {
 	{"i915_wedged", &i915_wedged_fops},
 	{"i915_max_freq", &i915_max_freq_fops},
 	{"i915_min_freq", &i915_min_freq_fops},
+	{"i915_edp_psr_status", &i915_edp_psr_ops},
 	{"i915_cache_sharing", &i915_cache_sharing_fops},
 	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
 	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b39c5f68efb2..9262cfb8aac2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -596,7 +596,8 @@ struct i915_drrs {
 struct i915_psr {
 	struct mutex lock;
 	bool sink_support;
-	struct intel_dp *enabled;
+	bool enabled;
+	struct intel_dp *dp;
 	bool active;
 	struct delayed_work work;
 	unsigned busy_frontbuffer_bits;
@@ -608,6 +609,14 @@ struct i915_psr {
 	bool alpm;
 	bool has_hw_tracking;
 
+	enum i915_psr_debugfs_mode {
+		PSR_DEBUGFS_MODE_DEFAULT = -1,
+		PSR_DEBUGFS_MODE_DISABLED,
+		PSR_DEBUGFS_MODE_ENABLED,
+		PSR_DEBUGFS_MODE_ENABLED_FORCE_LINK_STANDBY,
+		PSR_DEBUGFS_MODE_ENABLED_NO_LINK_STANDBY
+	} debugfs_mode;
+
 	void (*enable_source)(struct intel_dp *,
 			      const struct intel_crtc_state *);
 	void (*disable_source)(struct intel_dp *,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1f0e8f1e4594..af3c5578d2ea 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1876,6 +1876,9 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *crtc_state);
 void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state);
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       enum i915_psr_debugfs_mode mode);
 void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 			  unsigned frontbuffer_bits,
 			  enum fb_op_origin origin);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 317cb4a12693..3dc0eda8efe0 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,52 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+static bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv)
+{
+	/* Override link_standby x link_off defaults */
+	if (i915_modparams.enable_psr == 2) {
+		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
+		return true;
+	}
+
+	if (i915_modparams.enable_psr == 3) {
+		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
+		return false;
+	}
+
+	/* Set link_standby x link_off defaults */
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		/* HSW and BDW require workarounds that we don't implement. */
+		return false;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		/* On VLV and CHV only standby mode is supported. */
+		return true;
+	else
+		/* For new platforms let's respect VBT back again */
+		return dev_priv->vbt.psr.full_link;
+}
+
+static bool get_link_standby_for_mode(struct drm_i915_private *dev_priv,
+				      enum i915_psr_debugfs_mode mode)
+{
+	if (mode == PSR_DEBUGFS_MODE_ENABLED_FORCE_LINK_STANDBY)
+		return true;
+	else if (mode == PSR_DEBUGFS_MODE_ENABLED_NO_LINK_STANDBY)
+		return false;
+	else
+		return intel_psr_default_link_standby(dev_priv);
+}
+
+static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
+{
+	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
+		return i915_modparams.enable_psr;
+	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
+		return false;
+	else
+		return true;
+}
+
 static inline enum intel_display_power_domain
 psr_aux_domain(struct intel_dp *intel_dp)
 {
@@ -502,11 +548,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (!CAN_PSR(dev_priv))
 		return;
 
-	if (!i915_modparams.enable_psr) {
-		DRM_DEBUG_KMS("PSR disable by flag\n");
-		return;
-	}
-
 	/*
 	 * HSW spec explicitly says PSR is tied to port A.
 	 * BDW+ platforms with DDI implementation of PSR have different
@@ -559,7 +600,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
 	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+
+	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
+		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+	else
+		DRM_DEBUG_KMS("PSR disable by flag\n");
 }
 
 static void intel_psr_activate(struct intel_dp *intel_dp)
@@ -617,6 +662,38 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
 	}
 }
 
+static void __intel_psr_enable(struct drm_i915_private *dev_priv,
+			       const struct intel_crtc_state *crtc_state)
+{
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
+
+	if (dev_priv->psr.enabled)
+		return;
+
+	dev_priv->psr.enabled = true;
+
+	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
+	dev_priv->psr.enable_sink(intel_dp);
+	dev_priv->psr.enable_source(intel_dp, crtc_state);
+
+	if (INTEL_GEN(dev_priv) >= 9) {
+		intel_psr_activate(intel_dp);
+	} else {
+		/*
+		 * FIXME: Activation should happen immediately since this
+		 * function is just called after pipe is fully trained and
+		 * enabled.
+		 * However on some platforms we face issues when first
+		 * activation follows a modeset so quickly.
+		 *     - On VLV/CHV we get bank screen on first activation
+		 *     - On HSW/BDW we get a recoverable frozen screen until
+		 *       next exit-activate sequence.
+		 */
+		schedule_delayed_work(&dev_priv->psr.work,
+				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+	}
+}
+
 /**
  * intel_psr_enable - Enable PSR
  * @intel_dp: Intel DP
@@ -639,7 +716,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 
 	WARN_ON(dev_priv->drrs.dp);
 	mutex_lock(&dev_priv->psr.lock);
-	if (dev_priv->psr.enabled) {
+	if (dev_priv->psr.dp) {
 		DRM_DEBUG_KMS("PSR already in use\n");
 		goto unlock;
 	}
@@ -647,27 +724,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 	dev_priv->psr.psr2_support = crtc_state->has_psr2;
 	dev_priv->psr.busy_frontbuffer_bits = 0;
 
-	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
-	dev_priv->psr.enable_sink(intel_dp);
-	dev_priv->psr.enable_source(intel_dp, crtc_state);
-	dev_priv->psr.enabled = intel_dp;
+	dev_priv->psr.dp = intel_dp;
 
-	if (INTEL_GEN(dev_priv) >= 9) {
-		intel_psr_activate(intel_dp);
-	} else {
-		/*
-		 * FIXME: Activation should happen immediately since this
-		 * function is just called after pipe is fully trained and
-		 * enabled.
-		 * However on some platforms we face issues when first
-		 * activation follows a modeset so quickly.
-		 *     - On VLV/CHV we get bank screen on first activation
-		 *     - On HSW/BDW we get a recoverable frozen screen until
-		 *       next exit-activate sequence.
-		 */
-		schedule_delayed_work(&dev_priv->psr.work,
-				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
-	}
+	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
+		__intel_psr_enable(dev_priv, crtc_state);
 
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
@@ -752,6 +812,21 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
 	psr_aux_io_power_put(intel_dp);
 }
 
+static void __intel_psr_disable(struct drm_i915_private *dev_priv,
+				const struct intel_crtc_state *old_crtc_state)
+{
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
+
+	if (!dev_priv->psr.enabled)
+		return;
+
+	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
+
+	/* Disable PSR on Sink */
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+	dev_priv->psr.enabled = false;
+}
+
 /**
  * intel_psr_disable - Disable PSR
  * @intel_dp: Intel DP
@@ -773,27 +848,110 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
-	if (!dev_priv->psr.enabled) {
+	if (intel_dp != dev_priv->psr.dp) {
 		mutex_unlock(&dev_priv->psr.lock);
 		return;
 	}
 
-	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
-
-	/* Disable PSR on Sink */
-	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+	__intel_psr_disable(dev_priv, old_crtc_state);
 
-	dev_priv->psr.enabled = NULL;
+	dev_priv->psr.dp = NULL;
 	mutex_unlock(&dev_priv->psr.lock);
 
 	cancel_delayed_work_sync(&dev_priv->psr.work);
 }
 
+static struct drm_crtc *
+find_idle_crtc_for_encoder(struct drm_encoder *encoder,
+			   struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_connector_list_iter conn_iter;
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
+	bool found = false;
+	int ret;
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter)
+		if (connector->state->best_encoder == encoder) {
+			found = true;
+			break;
+		}
+	drm_connector_list_iter_end(&conn_iter);
+
+	if (WARN_ON(!found))
+		return ERR_PTR(-EINVAL);
+
+	crtc = connector->state->crtc;
+	ret = drm_modeset_lock(&crtc->mutex, ctx);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (connector->state->commit)
+		ret = wait_for_completion_interruptible(&connector->state->commit->hw_done);
+	if (!ret && crtc->state->commit)
+		ret = wait_for_completion_interruptible(&crtc->state->commit->hw_done);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return crtc;
+}
+
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       enum i915_psr_debugfs_mode mode)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	int ret;
+	bool enable, link_standby;
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	link_standby = get_link_standby_for_mode(dev_priv, mode);
+	enable = psr_global_enabled(mode);
+
+	mutex_lock(&dev_priv->psr.lock);
+
+	do {
+		if (!dev_priv->psr.dp) {
+			dev_priv->psr.debugfs_mode = mode;
+			dev_priv->psr.link_standby = link_standby;
+			goto end;
+		}
+		encoder = &dp_to_dig_port(dev_priv->psr.dp)->base.base;
+		mutex_unlock(&dev_priv->psr.lock);
+
+		crtc = find_idle_crtc_for_encoder(encoder, ctx);
+		if (IS_ERR(crtc))
+			return PTR_ERR(crtc);
+
+		mutex_lock(&dev_priv->psr.lock);
+	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
+
+	if (!enable || dev_priv->psr.link_standby != link_standby)
+		__intel_psr_disable(dev_priv, to_intel_crtc_state(crtc->state));
+
+	dev_priv->psr.debugfs_mode = mode;
+	dev_priv->psr.link_standby = link_standby;
+
+	if (enable)
+		__intel_psr_enable(dev_priv, to_intel_crtc_state(crtc->state));
+
+end:
+	mutex_unlock(&dev_priv->psr.lock);
+	return ret;
+}
+
 static void intel_psr_work(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
 		container_of(work, typeof(*dev_priv), psr.work.work);
-	struct intel_dp *intel_dp = dev_priv->psr.enabled;
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
 	struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
 
@@ -833,11 +991,11 @@ static void intel_psr_work(struct work_struct *work)
 		}
 	}
 	mutex_lock(&dev_priv->psr.lock);
-	intel_dp = dev_priv->psr.enabled;
-
-	if (!intel_dp)
+	if (!dev_priv->psr.enabled)
 		goto unlock;
 
+	intel_dp = dev_priv->psr.dp;
+
 	/*
 	 * The delayed work can race with an invalidate hence we need to
 	 * recheck. Since psr_flush first clears this and then reschedules we
@@ -853,7 +1011,7 @@ static void intel_psr_work(struct work_struct *work)
 
 static void intel_psr_exit(struct drm_i915_private *dev_priv)
 {
-	struct intel_dp *intel_dp = dev_priv->psr.enabled;
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
 	struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
 	u32 val;
@@ -938,7 +1096,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	if (frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)) {
@@ -984,7 +1142,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -1027,7 +1185,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -1081,26 +1239,8 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
 	if (i915_modparams.enable_psr == -1)
 		i915_modparams.enable_psr = 0;
 
-	/* Set link_standby x link_off defaults */
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		/* HSW and BDW require workarounds that we don't implement. */
-		dev_priv->psr.link_standby = false;
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		/* On VLV and CHV only standby mode is supported. */
-		dev_priv->psr.link_standby = true;
-	else
-		/* For new platforms let's respect VBT back again */
-		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
-
-	/* Override link_standby x link_off defaults */
-	if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
-		dev_priv->psr.link_standby = true;
-	}
-	if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) {
-		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
-		dev_priv->psr.link_standby = false;
-	}
+	dev_priv->psr.link_standby = intel_psr_default_link_standby(dev_priv);
+	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
 
 	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
 	mutex_init(&dev_priv->psr.lock);
-- 
2.16.2

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

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

* ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev3)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (4 preceding siblings ...)
  2018-03-15  0:58 ` ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
@ 2018-03-15 11:01 ` Patchwork
  2018-03-15 12:17 ` ✓ Fi.CI.IGT: " Patchwork
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-03-15 11:01 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev3)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

Series 39955v3 drm/i915: Control PSR at runtime through debugfs only
https://patchwork.freedesktop.org/api/1.0/series/39955/revisions/3/mbox/

---- Known issues:

Test debugfs_test:
        Subgroup read_all_entries:
                pass       -> INCOMPLETE (fi-snb-2520m) fdo#103713
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-a:
                pass       -> DMESG-WARN (fi-skl-6700k2) fdo#103191
        Subgroup suspend-read-crc-pipe-c:
                pass       -> INCOMPLETE (fi-bxt-dsi) fdo#103927
                pass       -> DMESG-WARN (fi-cnl-y3) fdo#104951

fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
fdo#103927 https://bugs.freedesktop.org/show_bug.cgi?id=103927
fdo#104951 https://bugs.freedesktop.org/show_bug.cgi?id=104951

fi-bdw-5557u     total:285  pass:264  dwarn:0   dfail:0   fail:0   skip:21  time:430s
fi-bdw-gvtdvm    total:285  pass:261  dwarn:0   dfail:0   fail:0   skip:24  time:442s
fi-blb-e6850     total:285  pass:220  dwarn:1   dfail:0   fail:0   skip:64  time:379s
fi-bsw-n3050     total:285  pass:239  dwarn:0   dfail:0   fail:0   skip:46  time:535s
fi-bwr-2160      total:285  pass:180  dwarn:0   dfail:0   fail:0   skip:105 time:295s
fi-bxt-dsi       total:243  pass:216  dwarn:0   dfail:0   fail:0   skip:26 
fi-bxt-j4205     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:509s
fi-byt-j1900     total:285  pass:250  dwarn:0   dfail:0   fail:0   skip:35  time:514s
fi-byt-n2820     total:285  pass:246  dwarn:0   dfail:0   fail:0   skip:39  time:509s
fi-cfl-8700k     total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:408s
fi-cfl-s2        total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:580s
fi-cfl-u         total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:509s
fi-cnl-y3        total:285  pass:258  dwarn:1   dfail:0   fail:0   skip:26  time:593s
fi-elk-e7500     total:285  pass:226  dwarn:0   dfail:0   fail:0   skip:59  time:423s
fi-gdg-551       total:285  pass:176  dwarn:0   dfail:0   fail:1   skip:108 time:315s
fi-glk-1         total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:533s
fi-hsw-4770      total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:403s
fi-ilk-650       total:285  pass:225  dwarn:0   dfail:0   fail:0   skip:60  time:418s
fi-ivb-3520m     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:471s
fi-ivb-3770      total:285  pass:252  dwarn:0   dfail:0   fail:0   skip:33  time:430s
fi-kbl-7500u     total:285  pass:260  dwarn:1   dfail:0   fail:0   skip:24  time:470s
fi-kbl-7567u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:467s
fi-kbl-r         total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:511s
fi-pnv-d510      total:285  pass:219  dwarn:1   dfail:0   fail:0   skip:65  time:658s
fi-skl-6260u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:439s
fi-skl-6600u     total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:526s
fi-skl-6700hq    total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:540s
fi-skl-6700k2    total:285  pass:260  dwarn:1   dfail:0   fail:0   skip:24  time:504s
fi-skl-6770hq    total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:489s
fi-skl-guc       total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:437s
fi-skl-gvtdvm    total:285  pass:262  dwarn:0   dfail:0   fail:0   skip:23  time:446s
fi-snb-2520m     total:3    pass:2    dwarn:0   dfail:0   fail:0   skip:0  
fi-snb-2600      total:285  pass:245  dwarn:0   dfail:0   fail:0   skip:40  time:405s
Blacklisted hosts:
fi-cnl-drrs      total:285  pass:254  dwarn:3   dfail:0   fail:0   skip:28  time:549s

14df0879a821a6f47e949c73c4d8300211c7f0b6 drm-tip: 2018y-03m-15d-09h-04m-49s UTC integration manifest
27f70bd75c2a drm/i915: Allow control of PSR at runtime through debugfs.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8360/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev3)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (5 preceding siblings ...)
  2018-03-15 11:01 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev3) Patchwork
@ 2018-03-15 12:17 ` Patchwork
  2018-07-26 10:10 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Control PSR at runtime through debugfs only (rev4) Patchwork
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-03-15 12:17 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev3)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

---- Known issues:

Test gem_eio:
        Subgroup in-flight-contexts:
                pass       -> INCOMPLETE (shard-apl) fdo#105341
Test kms_flip:
        Subgroup 2x-flip-vs-expired-vblank-interruptible:
                fail       -> PASS       (shard-hsw) fdo#102887
Test kms_plane_lowres:
        Subgroup pipe-b-tiling-none:
                pass       -> FAIL       (shard-apl) fdo#105185

fdo#105341 https://bugs.freedesktop.org/show_bug.cgi?id=105341
fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
fdo#105185 https://bugs.freedesktop.org/show_bug.cgi?id=105185

shard-apl        total:3407 pass:1801 dwarn:1   dfail:0   fail:8   skip:1595 time:12580s
shard-hsw        total:3442 pass:1768 dwarn:1   dfail:0   fail:1   skip:1671 time:11804s
shard-snb        total:3442 pass:1358 dwarn:1   dfail:0   fail:2   skip:2081 time:7203s
Blacklisted hosts:
shard-kbl        total:3367 pass:1900 dwarn:1   dfail:1   fail:9   skip:1454 time:9259s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8360/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-15 10:28   ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
@ 2018-03-22  1:45     ` Pandiyan, Dhinakaran
  2018-03-22  9:41       ` Maarten Lankhorst
  0 siblings, 1 reply; 31+ messages in thread
From: Pandiyan, Dhinakaran @ 2018-03-22  1:45 UTC (permalink / raw)
  To: maarten.lankhorst; +Cc: intel-gfx, Vivi, Rodrigo

On Thu, 2018-03-15 at 11:28 +0100, Maarten Lankhorst wrote:
> Currently tests modify i915.enable_psr and then do a modeset cycle
> to change PSR. We can write a value to i915_edp_psr_status to force
> a certain value without a modeset.
> 
> To retain compatibility with older userspace, we also still allow
> the override through the module parameter, and add some tracking
> to check whether a debugfs mode is specified.
> 

While this is something we want to be able to do, I am concerned about
adding more complexity to a feature that has barely been tested.

How about doing a modeset before frontbuffer_tracking PSR subtests and
one at the end? I'm assuming all of them are grouped together.

Comments on this patch itself.
1) please split intel_psr_default_link_standby() into a separate patch.
2) how does the user know what values to write without looking at the
code?
3) Can the connector and crtc be stored somewhere to avoid loops?
4) Has this been tested on any platforms with PSR?
5) Do subtests need a finer control of PSR i.e., psr_exit() and
psr_activate() instead of enable and disable

> Changes since v1:
> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to .enabled.
> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>   it and move it to intel_psr.c. This keeps all internals in intel_psr.c
> - Perform an interruptible wait for hw completion outside of the psr
>   lock, instead of being forced to trywait and return -EBUSY.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |  73 +++++++++-
>  drivers/gpu/drm/i915/i915_drv.h     |  11 +-
>  drivers/gpu/drm/i915/intel_drv.h    |   3 +
>  drivers/gpu/drm/i915/intel_psr.c    | 262 +++++++++++++++++++++++++++---------
>  4 files changed, 281 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 574fcf234007..98e169636f86 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2546,16 +2546,13 @@ static const char *psr2_live_status(u32 val)
>  
>  static int i915_edp_psr_status(struct seq_file *m, void *data)
>  {
> -	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> +	struct drm_i915_private *dev_priv = m->private;
>  	u32 psrperf = 0;
>  	u32 stat[3];
>  	enum pipe pipe;
>  	bool enabled = false;
>  	bool sink_support;
>  
> -	if (!HAS_PSR(dev_priv))
> -		return -ENODEV;
> -
>  	sink_support = dev_priv->psr.sink_support;
>  	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
>  	if (!sink_support)
> @@ -2564,7 +2561,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  	intel_runtime_pm_get(dev_priv);
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>  		   dev_priv->psr.busy_frontbuffer_bits);
>  	seq_printf(m, "Re-enable work scheduled: %s\n",
> @@ -2631,6 +2628,70 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  	return 0;
>  }
>  
> +static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
> +				  size_t len, loff_t *offp)
> +{
> +	struct seq_file *m = file->private_data;
> +	struct drm_i915_private *dev_priv = m->private;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret, val;
> +
> +	if (!dev_priv->psr.sink_support)
> +		return -ENODEV;
> +
> +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
> +	if (ret < 0) {
> +		bool enable;
> +		ret = kstrtobool_from_user(ubuf, len, &enable);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		val = enable;
> +	}
> +
> +	if (val < -1 || val > 3)
> +		return -EINVAL;
> +
> +	intel_runtime_pm_get(dev_priv);
> +
> +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +retry:
> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
> +	if (ret == -EBUSY) {
> +		ret = drm_modeset_backoff(&ctx);
> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	intel_runtime_pm_put(dev_priv);
> +
> +	return ret ?: len;
> +}
> +
> +static int i915_edp_psr_open(struct inode *inode, struct file *file)
> +{
> +	struct drm_i915_private *dev_priv = inode->i_private;
> +
> +	if (!HAS_PSR(dev_priv))
> +		return -ENODEV;
> +
> +	return single_open(file, i915_edp_psr_status, dev_priv);
> +}
> +
> +static const struct file_operations i915_edp_psr_ops = {
> +	.owner = THIS_MODULE,
> +	.open = i915_edp_psr_open,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +	.write = i915_edp_psr_write
> +};
> +
>  static int i915_sink_crc(struct seq_file *m, void *data)
>  {
>  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> @@ -4734,7 +4795,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
>  	{"i915_swizzle_info", i915_swizzle_info, 0},
>  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
>  	{"i915_llc", i915_llc, 0},
> -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
>  	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
>  	{"i915_energy_uJ", i915_energy_uJ, 0},
>  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
> @@ -4761,6 +4821,7 @@ static const struct i915_debugfs_files {
>  	{"i915_wedged", &i915_wedged_fops},
>  	{"i915_max_freq", &i915_max_freq_fops},
>  	{"i915_min_freq", &i915_min_freq_fops},
> +	{"i915_edp_psr_status", &i915_edp_psr_ops},
>  	{"i915_cache_sharing", &i915_cache_sharing_fops},
>  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
>  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index b39c5f68efb2..9262cfb8aac2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -596,7 +596,8 @@ struct i915_drrs {
>  struct i915_psr {
>  	struct mutex lock;
>  	bool sink_support;
> -	struct intel_dp *enabled;
> +	bool enabled;
> +	struct intel_dp *dp;
>  	bool active;
>  	struct delayed_work work;
>  	unsigned busy_frontbuffer_bits;
> @@ -608,6 +609,14 @@ struct i915_psr {
>  	bool alpm;
>  	bool has_hw_tracking;
>  
> +	enum i915_psr_debugfs_mode {
> +		PSR_DEBUGFS_MODE_DEFAULT = -1,
> +		PSR_DEBUGFS_MODE_DISABLED,
> +		PSR_DEBUGFS_MODE_ENABLED,
> +		PSR_DEBUGFS_MODE_ENABLED_FORCE_LINK_STANDBY,
> +		PSR_DEBUGFS_MODE_ENABLED_NO_LINK_STANDBY
> +	} debugfs_mode;
> +
>  	void (*enable_source)(struct intel_dp *,
>  			      const struct intel_crtc_state *);
>  	void (*disable_source)(struct intel_dp *,
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1f0e8f1e4594..af3c5578d2ea 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1876,6 +1876,9 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state *crtc_state);
>  void intel_psr_disable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state *old_crtc_state);
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       enum i915_psr_debugfs_mode mode);
>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  			  unsigned frontbuffer_bits,
>  			  enum fb_op_origin origin);
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index 317cb4a12693..3dc0eda8efe0 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -56,6 +56,52 @@
>  #include "intel_drv.h"
>  #include "i915_drv.h"
>  
> +static bool intel_psr_default_link_standby(struct drm_i915_private *dev_priv)
> +{
> +	/* Override link_standby x link_off defaults */
> +	if (i915_modparams.enable_psr == 2) {
> +		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
> +		return true;
> +	}
> +
> +	if (i915_modparams.enable_psr == 3) {
> +		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
> +		return false;
> +	}
> +
> +	/* Set link_standby x link_off defaults */
> +	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> +		/* HSW and BDW require workarounds that we don't implement. */
> +		return false;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		/* On VLV and CHV only standby mode is supported. */
> +		return true;
> +	else
> +		/* For new platforms let's respect VBT back again */
> +		return dev_priv->vbt.psr.full_link;
> +}
> +
> +static bool get_link_standby_for_mode(struct drm_i915_private *dev_priv,
> +				      enum i915_psr_debugfs_mode mode)
> +{
> +	if (mode == PSR_DEBUGFS_MODE_ENABLED_FORCE_LINK_STANDBY)
> +		return true;
> +	else if (mode == PSR_DEBUGFS_MODE_ENABLED_NO_LINK_STANDBY)
> +		return false;
> +	else
> +		return intel_psr_default_link_standby(dev_priv);
> +}
> +
> +static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
> +{
> +	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
> +		return i915_modparams.enable_psr;
> +	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
> +		return false;
> +	else
> +		return true;
> +}
> +
>  static inline enum intel_display_power_domain
>  psr_aux_domain(struct intel_dp *intel_dp)
>  {
> @@ -502,11 +548,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
>  	if (!CAN_PSR(dev_priv))
>  		return;
>  
> -	if (!i915_modparams.enable_psr) {
> -		DRM_DEBUG_KMS("PSR disable by flag\n");
> -		return;
> -	}
> -
>  	/*
>  	 * HSW spec explicitly says PSR is tied to port A.
>  	 * BDW+ platforms with DDI implementation of PSR have different
> @@ -559,7 +600,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
>  
>  	crtc_state->has_psr = true;
>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
> +
> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
> +	else
> +		DRM_DEBUG_KMS("PSR disable by flag\n");
>  }
>  
>  static void intel_psr_activate(struct intel_dp *intel_dp)
> @@ -617,6 +662,38 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
>  	}
>  }
>  
> +static void __intel_psr_enable(struct drm_i915_private *dev_priv,
> +			       const struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
> +
> +	if (dev_priv->psr.enabled)
> +		return;
> +
> +	dev_priv->psr.enabled = true;
> +
> +	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
> +	dev_priv->psr.enable_sink(intel_dp);
> +	dev_priv->psr.enable_source(intel_dp, crtc_state);
> +
> +	if (INTEL_GEN(dev_priv) >= 9) {
> +		intel_psr_activate(intel_dp);
> +	} else {
> +		/*
> +		 * FIXME: Activation should happen immediately since this
> +		 * function is just called after pipe is fully trained and
> +		 * enabled.
> +		 * However on some platforms we face issues when first
> +		 * activation follows a modeset so quickly.
> +		 *     - On VLV/CHV we get bank screen on first activation
> +		 *     - On HSW/BDW we get a recoverable frozen screen until
> +		 *       next exit-activate sequence.
> +		 */
> +		schedule_delayed_work(&dev_priv->psr.work,
> +				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
> +	}
> +}
> +
>  /**
>   * intel_psr_enable - Enable PSR
>   * @intel_dp: Intel DP
> @@ -639,7 +716,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  
>  	WARN_ON(dev_priv->drrs.dp);
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (dev_priv->psr.enabled) {
> +	if (dev_priv->psr.dp) {
>  		DRM_DEBUG_KMS("PSR already in use\n");
>  		goto unlock;
>  	}
> @@ -647,27 +724,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  	dev_priv->psr.psr2_support = crtc_state->has_psr2;
>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>  
> -	dev_priv->psr.setup_vsc(intel_dp, crtc_state);
> -	dev_priv->psr.enable_sink(intel_dp);
> -	dev_priv->psr.enable_source(intel_dp, crtc_state);
> -	dev_priv->psr.enabled = intel_dp;
> +	dev_priv->psr.dp = intel_dp;
>  
> -	if (INTEL_GEN(dev_priv) >= 9) {
> -		intel_psr_activate(intel_dp);
> -	} else {
> -		/*
> -		 * FIXME: Activation should happen immediately since this
> -		 * function is just called after pipe is fully trained and
> -		 * enabled.
> -		 * However on some platforms we face issues when first
> -		 * activation follows a modeset so quickly.
> -		 *     - On VLV/CHV we get bank screen on first activation
> -		 *     - On HSW/BDW we get a recoverable frozen screen until
> -		 *       next exit-activate sequence.
> -		 */
> -		schedule_delayed_work(&dev_priv->psr.work,
> -				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
> -	}
> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> +		__intel_psr_enable(dev_priv, crtc_state);
>  
>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
> @@ -752,6 +812,21 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
>  	psr_aux_io_power_put(intel_dp);
>  }
>  
> +static void __intel_psr_disable(struct drm_i915_private *dev_priv,
> +				const struct intel_crtc_state *old_crtc_state)
> +{
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
> +
> +	if (!dev_priv->psr.enabled)
> +		return;
> +
> +	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
> +
> +	/* Disable PSR on Sink */
> +	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
> +	dev_priv->psr.enabled = false;
> +}
> +
>  /**
>   * intel_psr_disable - Disable PSR
>   * @intel_dp: Intel DP
> @@ -773,27 +848,110 @@ void intel_psr_disable(struct intel_dp *intel_dp,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (!dev_priv->psr.enabled) {
> +	if (intel_dp != dev_priv->psr.dp) {
>  		mutex_unlock(&dev_priv->psr.lock);
>  		return;
>  	}
>  
> -	dev_priv->psr.disable_source(intel_dp, old_crtc_state);
> -
> -	/* Disable PSR on Sink */
> -	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
> +	__intel_psr_disable(dev_priv, old_crtc_state);
>  
> -	dev_priv->psr.enabled = NULL;
> +	dev_priv->psr.dp = NULL;
>  	mutex_unlock(&dev_priv->psr.lock);
>  
>  	cancel_delayed_work_sync(&dev_priv->psr.work);
>  }
>  
> +static struct drm_crtc *
> +find_idle_crtc_for_encoder(struct drm_encoder *encoder,
> +			   struct drm_modeset_acquire_ctx *ctx)
> +{
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_device *dev = encoder->dev;
> +	struct drm_connector *connector;
> +	struct drm_crtc *crtc;
> +	bool found = false;
> +	int ret;
> +
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter)
> +		if (connector->state->best_encoder == encoder) {
> +			found = true;
> +			break;
> +		}
> +	drm_connector_list_iter_end(&conn_iter);
> +
> +	if (WARN_ON(!found))
> +		return ERR_PTR(-EINVAL);
> +
> +	crtc = connector->state->crtc;
> +	ret = drm_modeset_lock(&crtc->mutex, ctx);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	if (connector->state->commit)
> +		ret = wait_for_completion_interruptible(&connector->state->commit->hw_done);
> +	if (!ret && crtc->state->commit)
> +		ret = wait_for_completion_interruptible(&crtc->state->commit->hw_done);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return crtc;
> +}
> +
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       enum i915_psr_debugfs_mode mode)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +	int ret;
> +	bool enable, link_standby;
> +
> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
> +	if (ret)
> +		return ret;
> +
> +	link_standby = get_link_standby_for_mode(dev_priv, mode);
> +	enable = psr_global_enabled(mode);
> +
> +	mutex_lock(&dev_priv->psr.lock);
> +
> +	do {
> +		if (!dev_priv->psr.dp) {
> +			dev_priv->psr.debugfs_mode = mode;
> +			dev_priv->psr.link_standby = link_standby;
> +			goto end;
> +		}
> +		encoder = &dp_to_dig_port(dev_priv->psr.dp)->base.base;
> +		mutex_unlock(&dev_priv->psr.lock);
> +
> +		crtc = find_idle_crtc_for_encoder(encoder, ctx);
> +		if (IS_ERR(crtc))
> +			return PTR_ERR(crtc);
> +
> +		mutex_lock(&dev_priv->psr.lock);
> +	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
> +
> +	if (!enable || dev_priv->psr.link_standby != link_standby)
> +		__intel_psr_disable(dev_priv, to_intel_crtc_state(crtc->state));
> +
> +	dev_priv->psr.debugfs_mode = mode;
> +	dev_priv->psr.link_standby = link_standby;
> +
> +	if (enable)
> +		__intel_psr_enable(dev_priv, to_intel_crtc_state(crtc->state));
> +
> +end:
> +	mutex_unlock(&dev_priv->psr.lock);
> +	return ret;
> +}
> +
>  static void intel_psr_work(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
>  		container_of(work, typeof(*dev_priv), psr.work.work);
> -	struct intel_dp *intel_dp = dev_priv->psr.enabled;
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
>  	struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
>  	enum pipe pipe = to_intel_crtc(crtc)->pipe;
>  
> @@ -833,11 +991,11 @@ static void intel_psr_work(struct work_struct *work)
>  		}
>  	}
>  	mutex_lock(&dev_priv->psr.lock);
> -	intel_dp = dev_priv->psr.enabled;
> -
> -	if (!intel_dp)
> +	if (!dev_priv->psr.enabled)
>  		goto unlock;
>  
> +	intel_dp = dev_priv->psr.dp;
> +
>  	/*
>  	 * The delayed work can race with an invalidate hence we need to
>  	 * recheck. Since psr_flush first clears this and then reschedules we
> @@ -853,7 +1011,7 @@ static void intel_psr_work(struct work_struct *work)
>  
>  static void intel_psr_exit(struct drm_i915_private *dev_priv)
>  {
> -	struct intel_dp *intel_dp = dev_priv->psr.enabled;
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
>  	struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
>  	enum pipe pipe = to_intel_crtc(crtc)->pipe;
>  	u32 val;
> @@ -938,7 +1096,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	if (frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)) {
> @@ -984,7 +1142,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -1027,7 +1185,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -1081,26 +1239,8 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
>  	if (i915_modparams.enable_psr == -1)
>  		i915_modparams.enable_psr = 0;
>  
> -	/* Set link_standby x link_off defaults */
> -	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
> -		/* HSW and BDW require workarounds that we don't implement. */
> -		dev_priv->psr.link_standby = false;
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		/* On VLV and CHV only standby mode is supported. */
> -		dev_priv->psr.link_standby = true;
> -	else
> -		/* For new platforms let's respect VBT back again */
> -		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
> -
> -	/* Override link_standby x link_off defaults */
> -	if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) {
> -		DRM_DEBUG_KMS("PSR: Forcing link standby\n");
> -		dev_priv->psr.link_standby = true;
> -	}
> -	if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) {
> -		DRM_DEBUG_KMS("PSR: Forcing main link off\n");
> -		dev_priv->psr.link_standby = false;
> -	}
> +	dev_priv->psr.link_standby = intel_psr_default_link_standby(dev_priv);
> +	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
>  
>  	INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
>  	mutex_init(&dev_priv->psr.lock);
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-22  1:45     ` Pandiyan, Dhinakaran
@ 2018-03-22  9:41       ` Maarten Lankhorst
  2018-07-26  6:32         ` Dhinakaran Pandiyan
  0 siblings, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-03-22  9:41 UTC (permalink / raw)
  To: Pandiyan, Dhinakaran; +Cc: intel-gfx, Vivi, Rodrigo

Op 22-03-18 om 02:45 schreef Pandiyan, Dhinakaran:
> On Thu, 2018-03-15 at 11:28 +0100, Maarten Lankhorst wrote:
>> Currently tests modify i915.enable_psr and then do a modeset cycle
>> to change PSR. We can write a value to i915_edp_psr_status to force
>> a certain value without a modeset.
>>
>> To retain compatibility with older userspace, we also still allow
>> the override through the module parameter, and add some tracking
>> to check whether a debugfs mode is specified.
>>
> While this is something we want to be able to do, I am concerned about
> adding more complexity to a feature that has barely been tested.
>
> How about doing a modeset before frontbuffer_tracking PSR subtests and
> one at the end? I'm assuming all of them are grouped together.

Currently we run all subtests individually, this means that we also need to do
some extra modesets per test. One to disable PSR and collect the reference CRC, the
other to enable PSR for the actual test.

With these changes, we don't need to do so.


> Comments on this patch itself.
> 1) please split intel_psr_default_link_standby() into a separate patch.
Will do.
> 2) how does the user know what values to write without looking at the
> code?
We match the modparam options for i915.enable_psr, but in general
user shouldn't touch it unless asked to. :) This is mostly meant for IGT tests,
could also be useful for debugging i915 in general though.

But if you really want, perhaps if we someone writes an invalid value, we could also
output the possible values to debugfs? Though I don't think we ought to. debugfs
doesn't always have documentation.
> 3) Can the connector and crtc be stored somewhere to avoid loops?
intel_psr_set_debugfs mode checks for idleness and waits for all atomic commits to complete.
We need the HW state to toggle PSR, and this is the only way to guarantee that crtc->state matches
the actual hw state.

If we don't drop the psr lock, we would get a deadlock when intel_psr_enable/disable is called from .crtc_disable,
because we wait for hw_done with psr lock already taken.
> 4) Has this been tested on any platforms with PSR?
I've had someone test v1 on a PSR capable system. It hung in the same way as enabling PSR during boot did,
so that part is the same.

For the later patches I used f2-cnl-alpha, but that system hangs a few seconds / half a minute after loading i915.
Still gave me enough time to check we can write any value to debugfs.

> 5) Do subtests need a finer control of PSR i.e., psr_exit() and
> psr_activate() instead of enable and disable
Not afaict. We sometimes invalidate the FB with dirtyfb, but that's all the control we need I think.

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

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-03-22  9:41       ` Maarten Lankhorst
@ 2018-07-26  6:32         ` Dhinakaran Pandiyan
  2018-07-26  9:06           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3 Maarten Lankhorst
  2018-07-26 12:54           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
  0 siblings, 2 replies; 31+ messages in thread
From: Dhinakaran Pandiyan @ 2018-07-26  6:32 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx, Vivi, Rodrigo

On Thu, 2018-03-22 at 10:41 +0100, Maarten Lankhorst wrote:
> Op 22-03-18 om 02:45 schreef Pandiyan, Dhinakaran:
> > 
> > On Thu, 2018-03-15 at 11:28 +0100, Maarten Lankhorst wrote:
> > > 
> > > Currently tests modify i915.enable_psr and then do a modeset
> > > cycle
> > > to change PSR. We can write a value to i915_edp_psr_status to
> > > force
> > > a certain value without a modeset.
> > > 
> > > To retain compatibility with older userspace, we also still allow
> > > the override through the module parameter, and add some tracking
> > > to check whether a debugfs mode is specified.
> > > 
> > While this is something we want to be able to do, I am concerned
> > about
> > adding more complexity to a feature that has barely been tested.
> > 
> > How about doing a modeset before frontbuffer_tracking PSR subtests
> > and
> > one at the end? I'm assuming all of them are grouped together.
> Currently we run all subtests individually, this means that we also
> need to do
> some extra modesets per test. One to disable PSR and collect the
> reference CRC, the
> other to enable PSR for the actual test.
> 
> With these changes, we don't need to do so.
> 
> 
> > 
> > Comments on this patch itself.
> > 1) please split intel_psr_default_link_standby() into a separate
> > patch.
> Will do.

Maarten, do you plan to rebase this patch? I would like to use this in
the IGTs to enable PSR1 on PSR2 panels.


-DK

> > 
> > 2) how does the user know what values to write without looking at
> > the
> > code?
> We match the modparam options for i915.enable_psr, but in general
> user shouldn't touch it unless asked to. :) This is mostly meant for
> IGT tests,
> could also be useful for debugging i915 in general though.
> 
> But if you really want, perhaps if we someone writes an invalid
> value, we could also
> output the possible values to debugfs? Though I don't think we ought
> to. debugfs
> doesn't always have documentation.
> > 
> > 3) Can the connector and crtc be stored somewhere to avoid loops?
> intel_psr_set_debugfs mode checks for idleness and waits for all
> atomic commits to complete.
> We need the HW state to toggle PSR, and this is the only way to
> guarantee that crtc->state matches
> the actual hw state.
> 
> If we don't drop the psr lock, we would get a deadlock when
> intel_psr_enable/disable is called from .crtc_disable,
> because we wait for hw_done with psr lock already taken.
> > 
> > 4) Has this been tested on any platforms with PSR?
> I've had someone test v1 on a PSR capable system. It hung in the same
> way as enabling PSR during boot did,
> so that part is the same.
> 
> For the later patches I used f2-cnl-alpha, but that system hangs a
> few seconds / half a minute after loading i915.
> Still gave me enough time to check we can write any value to debugfs.
> 
> > 
> > 5) Do subtests need a finer control of PSR i.e., psr_exit() and
> > psr_activate() instead of enable and disable
> Not afaict. We sometimes invalidate the FB with dirtyfb, but that's
> all the control we need I think.
> 
> ~Maarten
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3.
  2018-07-26  6:32         ` Dhinakaran Pandiyan
@ 2018-07-26  9:06           ` Maarten Lankhorst
  2018-07-27  3:27             ` Dhinakaran Pandiyan
  2018-07-26 12:54           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
  1 sibling, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-26  9:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Dhinakaran Pandiyan, Rodrigo Vivi

Currently tests modify i915.enable_psr and then do a modeset cycle
to change PSR. We can write a value to i915_edp_psr_status to force
a certain value without a modeset.

To retain compatibility with older userspace, we also still allow
the override through the module parameter, and add some tracking
to check whether a debugfs mode is specified.

Changes since v1:
- Rename dev_priv->psr.enabled to .dp, and .hw_configured to .enabled.
- Fix i915_psr_debugfs_mode to match the writes to debugfs.
- Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
  it and move it to intel_psr.c. This keeps all internals in intel_psr.c
- Perform an interruptible wait for hw completion outside of the psr
  lock, instead of being forced to trywait and return -EBUSY.
Changes since v2:
- Rebase on top of intel_psr changes.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  75 ++++++++++++--
 drivers/gpu/drm/i915/i915_drv.h     |   9 +-
 drivers/gpu/drm/i915/intel_drv.h    |   3 +
 drivers/gpu/drm/i915/intel_psr.c    | 154 ++++++++++++++++++++++++----
 4 files changed, 214 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 59dc0610ea44..b2904bb2be49 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2689,14 +2689,11 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
 
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	struct drm_i915_private *dev_priv = m->private;
 	u32 psrperf = 0;
 	bool enabled = false;
 	bool sink_support;
 
-	if (!HAS_PSR(dev_priv))
-		return -ENODEV;
-
 	sink_support = dev_priv->psr.sink_support;
 	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
 	if (!sink_support)
@@ -2705,7 +2702,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->psr.lock);
-	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
+	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
 	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
 		   dev_priv->psr.busy_frontbuffer_bits);
 
@@ -2776,6 +2773,72 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
 			i915_edp_psr_debug_get, i915_edp_psr_debug_set,
 			"%llu\n");
 
+static ssize_t i915_edp_psr_write(struct file *file, const char __user *ubuf,
+				  size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_i915_private *dev_priv = m->private;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret, val;
+
+	if (!dev_priv->psr.sink_support)
+		return -ENODEV;
+
+	ret = kstrtoint_from_user(ubuf, len, 10, &val);
+	if (ret < 0) {
+		bool enable;
+		ret = kstrtobool_from_user(ubuf, len, &enable);
+
+		if (ret < 0)
+			return ret;
+
+		val = enable;
+	}
+
+	if (val != PSR_DEBUGFS_MODE_DEFAULT &&
+	    val != PSR_DEBUGFS_MODE_DISABLED &&
+	    val != PSR_DEBUGFS_MODE_ENABLED)
+		return -EINVAL;
+
+	intel_runtime_pm_get(dev_priv);
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+retry:
+	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
+	if (ret == -EBUSY) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	intel_runtime_pm_put(dev_priv);
+
+	return ret ?: len;
+}
+
+static int i915_edp_psr_open(struct inode *inode, struct file *file)
+{
+	struct drm_i915_private *dev_priv = inode->i_private;
+
+	if (!HAS_PSR(dev_priv))
+		return -ENODEV;
+
+	return single_open(file, i915_edp_psr_status, dev_priv);
+}
+
+static const struct file_operations i915_edp_psr_ops = {
+	.owner = THIS_MODULE,
+	.open = i915_edp_psr_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = i915_edp_psr_write
+};
+
 static int i915_energy_uJ(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4720,7 +4783,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_llc", i915_llc, 0},
-	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
@@ -4744,6 +4806,7 @@ static const struct i915_debugfs_files {
 	const struct file_operations *fops;
 } i915_debugfs_files[] = {
 	{"i915_wedged", &i915_wedged_fops},
+	{"i915_edp_psr_status", &i915_edp_psr_ops},
 	{"i915_cache_sharing", &i915_cache_sharing_fops},
 	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
 	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0f49f9988dfa..d8583770e8a6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -612,7 +612,8 @@ struct i915_drrs {
 struct i915_psr {
 	struct mutex lock;
 	bool sink_support;
-	struct intel_dp *enabled;
+	bool enabled;
+	struct intel_dp *dp;
 	bool active;
 	struct work_struct work;
 	unsigned busy_frontbuffer_bits;
@@ -625,6 +626,12 @@ struct i915_psr {
 	bool debug;
 	ktime_t last_entry_attempt;
 	ktime_t last_exit;
+
+	enum i915_psr_debugfs_mode {
+		PSR_DEBUGFS_MODE_DEFAULT = -1,
+		PSR_DEBUGFS_MODE_DISABLED,
+		PSR_DEBUGFS_MODE_ENABLED
+	} debugfs_mode;
 };
 
 enum intel_pch {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c275f91244a6..751ed257fbba 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1926,6 +1926,9 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *crtc_state);
 void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state);
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       enum i915_psr_debugfs_mode mode);
 void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 			  unsigned frontbuffer_bits,
 			  enum fb_op_origin origin);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 4bd5768731ee..97424ae769f3 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,16 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
+{
+	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
+		return i915_modparams.enable_psr;
+	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
+		return false;
+	else
+		return true;
+}
+
 void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug)
 {
 	u32 debug_mask, mask;
@@ -471,11 +481,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (!CAN_PSR(dev_priv))
 		return;
 
-	if (!i915_modparams.enable_psr) {
-		DRM_DEBUG_KMS("PSR disable by flag\n");
-		return;
-	}
-
 	/*
 	 * HSW spec explicitly says PSR is tied to port A.
 	 * BDW+ platforms with DDI implementation of PSR have different
@@ -517,7 +522,11 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
 	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+
+	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
+		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
+	else
+		DRM_DEBUG_KMS("PSR disable by flag\n");
 }
 
 static void intel_psr_activate(struct intel_dp *intel_dp)
@@ -589,6 +598,22 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
 	}
 }
 
+static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
+				    const struct intel_crtc_state *crtc_state)
+{
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
+
+	if (dev_priv->psr.enabled)
+		return;
+
+	intel_psr_setup_vsc(intel_dp, crtc_state);
+	intel_psr_enable_sink(intel_dp);
+	intel_psr_enable_source(intel_dp, crtc_state);
+	dev_priv->psr.enabled = true;
+
+	intel_psr_activate(intel_dp);
+}
+
 /**
  * intel_psr_enable - Enable PSR
  * @intel_dp: Intel DP
@@ -611,7 +636,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 
 	WARN_ON(dev_priv->drrs.dp);
 	mutex_lock(&dev_priv->psr.lock);
-	if (dev_priv->psr.enabled) {
+	if (dev_priv->psr.dp) {
 		DRM_DEBUG_KMS("PSR already in use\n");
 		goto unlock;
 	}
@@ -619,12 +644,10 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
 	dev_priv->psr.busy_frontbuffer_bits = 0;
 
-	intel_psr_setup_vsc(intel_dp, crtc_state);
-	intel_psr_enable_sink(intel_dp);
-	intel_psr_enable_source(intel_dp, crtc_state);
-	dev_priv->psr.enabled = intel_dp;
+	dev_priv->psr.dp = intel_dp;
 
-	intel_psr_activate(intel_dp);
+	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
+		intel_psr_enable_locked(dev_priv, crtc_state);
 
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
@@ -688,7 +711,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
 	/* Disable PSR on Sink */
 	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
 
-	dev_priv->psr.enabled = NULL;
+	dev_priv->psr.enabled = false;
 }
 
 /**
@@ -712,7 +735,14 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
+	if (intel_dp != dev_priv->psr.dp) {
+		mutex_unlock(&dev_priv->psr.lock);
+		return;
+	}
+
 	intel_psr_disable_locked(intel_dp);
+
+	dev_priv->psr.dp = NULL;
 	mutex_unlock(&dev_priv->psr.lock);
 	cancel_work_sync(&dev_priv->psr.work);
 }
@@ -756,13 +786,11 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
 
 static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
 {
-	struct intel_dp *intel_dp;
 	i915_reg_t reg;
 	u32 mask;
 	int err;
 
-	intel_dp = dev_priv->psr.enabled;
-	if (!intel_dp)
+	if (!dev_priv->psr.enabled)
 		return false;
 
 	if (dev_priv->psr.psr2_enabled) {
@@ -784,6 +812,89 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
 	return err == 0 && dev_priv->psr.enabled;
 }
 
+static struct drm_crtc *
+find_idle_crtc_for_encoder(struct drm_encoder *encoder,
+			   struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_connector_list_iter conn_iter;
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
+	bool found = false;
+	int ret;
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter)
+		if (connector->state->best_encoder == encoder) {
+			found = true;
+			break;
+		}
+	drm_connector_list_iter_end(&conn_iter);
+
+	if (WARN_ON(!found))
+		return ERR_PTR(-EINVAL);
+
+	crtc = connector->state->crtc;
+	ret = drm_modeset_lock(&crtc->mutex, ctx);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (connector->state->commit)
+		ret = wait_for_completion_interruptible(&connector->state->commit->hw_done);
+	if (!ret && crtc->state->commit)
+		ret = wait_for_completion_interruptible(&crtc->state->commit->hw_done);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return crtc;
+}
+
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       enum i915_psr_debugfs_mode mode)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	int ret;
+	bool enable;
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	enable = psr_global_enabled(mode);
+
+	mutex_lock(&dev_priv->psr.lock);
+
+	do {
+		if (!dev_priv->psr.dp) {
+			dev_priv->psr.debugfs_mode = mode;
+			goto end;
+		}
+		encoder = &dp_to_dig_port(dev_priv->psr.dp)->base.base;
+		mutex_unlock(&dev_priv->psr.lock);
+
+		crtc = find_idle_crtc_for_encoder(encoder, ctx);
+		if (IS_ERR(crtc))
+			return PTR_ERR(crtc);
+
+		mutex_lock(&dev_priv->psr.lock);
+	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
+
+	if (!enable)
+		intel_psr_disable_locked(enc_to_intel_dp(encoder));
+
+	dev_priv->psr.debugfs_mode = mode;
+
+	if (enable)
+		intel_psr_enable_locked(dev_priv, to_intel_crtc_state(crtc->state));
+
+end:
+	mutex_unlock(&dev_priv->psr.lock);
+	return ret;
+}
+
 static void intel_psr_work(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
@@ -811,7 +922,8 @@ static void intel_psr_work(struct work_struct *work)
 	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv->psr.active)
 		goto unlock;
 
-	intel_psr_activate(dev_priv->psr.enabled);
+	intel_psr_activate(dev_priv->psr.dp
+);
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
 }
@@ -866,7 +978,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -909,7 +1021,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -971,6 +1083,8 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
 		/* For new platforms let's respect VBT back again */
 		dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
 
+	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
+
 	INIT_WORK(&dev_priv->psr.work, intel_psr_work);
 	mutex_init(&dev_priv->psr.lock);
 }
@@ -991,7 +1105,7 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp)
 
 	mutex_lock(&psr->lock);
 
-	if (psr->enabled != intel_dp)
+	if (!psr->enabled || psr->dp != intel_dp)
 		goto exit;
 
 	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) {
-- 
2.18.0

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

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

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Control PSR at runtime through debugfs only (rev4)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (6 preceding siblings ...)
  2018-03-15 12:17 ` ✓ Fi.CI.IGT: " Patchwork
@ 2018-07-26 10:10 ` Patchwork
  2018-07-26 10:11 ` ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-07-26 10:10 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev4)
URL   : https://patchwork.freedesktop.org/series/39955/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
7f03d7801144 drm/i915: Allow control of PSR at runtime through debugfs, v3.
-:76: WARNING:LINE_SPACING: Missing a blank line after declarations
#76: FILE: drivers/gpu/drm/i915/i915_debugfs.c:2790:
+		bool enable;
+		ret = kstrtobool_from_user(ubuf, len, &enable);

total: 0 errors, 1 warnings, 0 checks, 389 lines checked

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

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

* ✗ Fi.CI.SPARSE: warning for drm/i915: Control PSR at runtime through debugfs only (rev4)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (7 preceding siblings ...)
  2018-07-26 10:10 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Control PSR at runtime through debugfs only (rev4) Patchwork
@ 2018-07-26 10:11 ` Patchwork
  2018-07-26 10:30 ` ✓ Fi.CI.BAT: success " Patchwork
  2018-07-26 11:57 ` ✓ Fi.CI.IGT: " Patchwork
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-07-26 10:11 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev4)
URL   : https://patchwork.freedesktop.org/series/39955/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Commit: drm/i915: Allow control of PSR at runtime through debugfs, v3.
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3645:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3652:16: warning: expression using sizeof(void)

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

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

* ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev4)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (8 preceding siblings ...)
  2018-07-26 10:11 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2018-07-26 10:30 ` Patchwork
  2018-07-26 11:57 ` ✓ Fi.CI.IGT: " Patchwork
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-07-26 10:30 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev4)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

= CI Bug Log - changes from CI_DRM_4548 -> Patchwork_9778 =

== Summary - SUCCESS ==

  No regressions found.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/39955/revisions/4/mbox/

== Known issues ==

  Here are the changes found in Patchwork_9778 that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@drv_selftest@live_workarounds:
      {fi-cfl-8109u}:     PASS -> DMESG-FAIL (fdo#107292)

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c:
      fi-bxt-dsi:         PASS -> INCOMPLETE (fdo#103927)

    
    ==== Possible fixes ====

    igt@drv_module_reload@basic-reload:
      fi-glk-j4005:       DMESG-WARN (fdo#106725, fdo#106248) -> PASS

    igt@drv_module_reload@basic-reload-inject:
      fi-glk-j4005:       DMESG-WARN (fdo#105719) -> PASS

    igt@drv_selftest@live_workarounds:
      {fi-bsw-kefka}:     DMESG-FAIL (fdo#107292) -> PASS

    igt@kms_flip@basic-flip-vs-wf_vblank:
      fi-glk-j4005:       FAIL (fdo#100368) -> PASS

    
    ==== Warnings ====

    igt@drv_selftest@live_workarounds:
      fi-cnl-psr:         DMESG-WARN (fdo#105395) -> DMESG-FAIL (fdo#107292)

    
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
  fdo#103927 https://bugs.freedesktop.org/show_bug.cgi?id=103927
  fdo#105395 https://bugs.freedesktop.org/show_bug.cgi?id=105395
  fdo#105719 https://bugs.freedesktop.org/show_bug.cgi?id=105719
  fdo#106248 https://bugs.freedesktop.org/show_bug.cgi?id=106248
  fdo#106725 https://bugs.freedesktop.org/show_bug.cgi?id=106725
  fdo#107292 https://bugs.freedesktop.org/show_bug.cgi?id=107292


== Participating hosts (51 -> 43) ==

  Missing    (8): fi-ilk-m540 fi-hsw-4200u fi-skl-guc fi-byt-squawks fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus 


== Build changes ==

    * Linux: CI_DRM_4548 -> Patchwork_9778

  CI_DRM_4548: 1ccdb8d0bf55621006a4ac04e8e5e964480382ef @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4576: bcb37a9b20eeec97f15fac2222408cc2e0b77631 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_9778: 7f03d78011441561773a4cf0a4c795d0437b58fa @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

7f03d7801144 drm/i915: Allow control of PSR at runtime through debugfs, v3.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9778/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev4)
  2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
                   ` (9 preceding siblings ...)
  2018-07-26 10:30 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-07-26 11:57 ` Patchwork
  10 siblings, 0 replies; 31+ messages in thread
From: Patchwork @ 2018-07-26 11:57 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Control PSR at runtime through debugfs only (rev4)
URL   : https://patchwork.freedesktop.org/series/39955/
State : success

== Summary ==

= CI Bug Log - changes from CI_DRM_4548_full -> Patchwork_9778_full =

== Summary - WARNING ==

  Minor unknown changes coming with Patchwork_9778_full need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_9778_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

== Possible new issues ==

  Here are the unknown changes that may have been introduced in Patchwork_9778_full:

  === IGT changes ===

    ==== Warnings ====

    igt@gem_mocs_settings@mocs-rc6-ctx-dirty-render:
      shard-kbl:          PASS -> SKIP

    
== Known issues ==

  Here are the changes found in Patchwork_9778_full that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@drv_suspend@shrink:
      shard-snb:          PASS -> FAIL (fdo#106886)

    igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes:
      shard-kbl:          PASS -> INCOMPLETE (fdo#103665)

    igt@kms_setmode@basic:
      shard-apl:          PASS -> FAIL (fdo#99912)
      shard-glk:          PASS -> FAIL (fdo#99912)

    igt@kms_vblank@pipe-b-ts-continuation-dpms-suspend:
      shard-glk:          PASS -> FAIL (fdo#103375)

    
    ==== Possible fixes ====

    igt@kms_flip@2x-flip-vs-expired-vblank-interruptible:
      shard-hsw:          FAIL (fdo#102887) -> PASS

    igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes:
      shard-apl:          FAIL (fdo#103375) -> PASS

    
  fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
  fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375
  fdo#103665 https://bugs.freedesktop.org/show_bug.cgi?id=103665
  fdo#106886 https://bugs.freedesktop.org/show_bug.cgi?id=106886
  fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912


== Participating hosts (5 -> 5) ==

  No changes in participating hosts


== Build changes ==

    * Linux: CI_DRM_4548 -> Patchwork_9778

  CI_DRM_4548: 1ccdb8d0bf55621006a4ac04e8e5e964480382ef @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4576: bcb37a9b20eeec97f15fac2222408cc2e0b77631 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_9778: 7f03d78011441561773a4cf0a4c795d0437b58fa @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_9778/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs.
  2018-07-26  6:32         ` Dhinakaran Pandiyan
  2018-07-26  9:06           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3 Maarten Lankhorst
@ 2018-07-26 12:54           ` Maarten Lankhorst
  1 sibling, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-26 12:54 UTC (permalink / raw)
  To: dhinakaran.pandiyan; +Cc: intel-gfx, Vivi, Rodrigo

Op 26-07-18 om 08:32 schreef Dhinakaran Pandiyan:
> On Thu, 2018-03-22 at 10:41 +0100, Maarten Lankhorst wrote:
>> Op 22-03-18 om 02:45 schreef Pandiyan, Dhinakaran:
>>> On Thu, 2018-03-15 at 11:28 +0100, Maarten Lankhorst wrote:
>>>> Currently tests modify i915.enable_psr and then do a modeset
>>>> cycle
>>>> to change PSR. We can write a value to i915_edp_psr_status to
>>>> force
>>>> a certain value without a modeset.
>>>>
>>>> To retain compatibility with older userspace, we also still allow
>>>> the override through the module parameter, and add some tracking
>>>> to check whether a debugfs mode is specified.
>>>>
>>> While this is something we want to be able to do, I am concerned
>>> about
>>> adding more complexity to a feature that has barely been tested.
>>>
>>> How about doing a modeset before frontbuffer_tracking PSR subtests
>>> and
>>> one at the end? I'm assuming all of them are grouped together.
>> Currently we run all subtests individually, this means that we also
>> need to do
>> some extra modesets per test. One to disable PSR and collect the
>> reference CRC, the
>> other to enable PSR for the actual test.
>>
>> With these changes, we don't need to do so.
>>
>>
>>> Comments on this patch itself.
>>> 1) please split intel_psr_default_link_standby() into a separate
>>> patch.
>> Will do.
> Maarten, do you plan to rebase this patch? I would like to use this in
> the IGTs to enable PSR1 on PSR2 panels.
I've rebased, can you check it works as intended?

~Maarten

IGT patch below.

----
commit 2ba09dc60dd00c474566fc3d0bb4e550a2c7fcca
Author: Maarten Lankhorst 
Date:   Mon Mar 12 17:49:40 2018 +0100

    tests/kms_frontbuffer_tracking: Add support for toggling edp psr through debugfs, v2.
    
    It's harmful to write to enable_psr at runtime, and the patch that allows
    us to change i915_edp_psr_status with the panel running will require us
    to abandon the module parameter. Hence the userspace change needs to be
    put in IGT first before we can change it at kernel time.
    
    Toggling it to debugfs will mean we can skip a modeset when changing our
    feature set.
    
    Changes since v1:
    - Rebase with the previous patches dropped.
    
    Signed-off-by: Maarten Lankhorst 

diff --git a/tests/kms_frontbuffer_tracking.c b/tests/kms_frontbuffer_tracking.c
index 1dfd7c1cee8d..a043230d150a 100644
--- a/tests/kms_frontbuffer_tracking.c
+++ b/tests/kms_frontbuffer_tracking.c
@@ -775,6 +775,38 @@ static void drrs_set(unsigned int val)
 		igt_assert_f(ret == (sizeof(buf) - 1), "debugfs_write failed");
 }
 
+static void restore_psr_debugfs(int sig)
+{
+	debugfs_write("i915_edp_psr_status", "-1");
+}
+
+static bool psr_set(unsigned int val)
+{
+	static int oldval = -1;
+	char buf[4];
+	int ret;
+
+	snprintf(buf, sizeof(buf), "%i\n", val);
+
+	ret = debugfs_write("i915_edp_psr_status", buf);
+	if (ret != -EINVAL) {
+		igt_assert(ret > 0 || val <= 0);
+
+		if (ret > 0)
+			igt_install_exit_handler(restore_psr_debugfs);
+
+		return false;
+	}
+
+	igt_set_module_param_int("enable_psr", val);
+
+	if (val == oldval)
+		return false;
+
+	oldval = val;
+	return true;
+}
+
 static bool is_drrs_high(void)
 {
 	char buf[MAX_DRRS_STATUS_BUF_LEN];
@@ -941,8 +973,8 @@ static bool drrs_wait_until_rr_switch_to_low(void)
 
 #define fbc_enable() igt_set_module_param_int("enable_fbc", 1)
 #define fbc_disable() igt_set_module_param_int("enable_fbc", 0)
-#define psr_enable() igt_set_module_param_int("enable_psr", 1)
-#define psr_disable() igt_set_module_param_int("enable_psr", 0)
+#define psr_enable()	psr_set(1)
+#define psr_disable()	psr_set(0)
 #define drrs_enable()	drrs_set(1)
 #define drrs_disable()	drrs_set(0)
 

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

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3.
  2018-07-26  9:06           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3 Maarten Lankhorst
@ 2018-07-27  3:27             ` Dhinakaran Pandiyan
  2018-07-27  8:41               ` Maarten Lankhorst
  0 siblings, 1 reply; 31+ messages in thread
From: Dhinakaran Pandiyan @ 2018-07-27  3:27 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx; +Cc: Rodrigo Vivi

On Thu, 2018-07-26 at 11:06 +0200, Maarten Lankhorst wrote:
> Currently tests modify i915.enable_psr and then do a modeset cycle
> to change PSR. We can write a value to i915_edp_psr_status to force
> a certain value without a modeset.
> 
> To retain compatibility with older userspace, we also still allow
> the override through the module parameter, and add some tracking
> to check whether a debugfs mode is specified.
> 
> Changes since v1:
> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
> .enabled.
> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>   it and move it to intel_psr.c. This keeps all internals in
> intel_psr.c
> - Perform an interruptible wait for hw completion outside of the psr
>   lock, instead of being forced to trywait and return -EBUSY.
> Changes since v2:
> - Rebase on top of intel_psr changes.

Thanks for resending this, I have some questions to understand the
patch better.

> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |  75 ++++++++++++--
>  drivers/gpu/drm/i915/i915_drv.h     |   9 +-
>  drivers/gpu/drm/i915/intel_drv.h    |   3 +
>  drivers/gpu/drm/i915/intel_psr.c    | 154 ++++++++++++++++++++++++
> ----
>  4 files changed, 214 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 59dc0610ea44..b2904bb2be49 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2689,14 +2689,11 @@ psr_source_status(struct drm_i915_private
> *dev_priv, struct seq_file *m)
>  
>  static int i915_edp_psr_status(struct seq_file *m, void *data)
>  {
> -	struct drm_i915_private *dev_priv = node_to_i915(m-
> >private);
> +	struct drm_i915_private *dev_priv = m->private;
>  	u32 psrperf = 0;
>  	bool enabled = false;
>  	bool sink_support;
>  
> -	if (!HAS_PSR(dev_priv))
> -		return -ENODEV;
> -
>  	sink_support = dev_priv->psr.sink_support;
>  	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
>  	if (!sink_support)
> @@ -2705,7 +2702,7 @@ static int i915_edp_psr_status(struct seq_file
> *m, void *data)
>  	intel_runtime_pm_get(dev_priv);
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
> >psr.enabled));
> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
> >psr.enabled));
>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>  		   dev_priv->psr.busy_frontbuffer_bits);
>  
> @@ -2776,6 +2773,72 @@
> DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
>  			i915_edp_psr_debug_get,
> i915_edp_psr_debug_set,
>  			"%llu\n");
>  
> +static ssize_t i915_edp_psr_write(struct file *file, const char
> __user *ubuf,
> +				  size_t len, loff_t *offp)
> +{
> +	struct seq_file *m = file->private_data;
> +	struct drm_i915_private *dev_priv = m->private;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret, val;
> +
> +	if (!dev_priv->psr.sink_support)
> +		return -ENODEV;
> +
> +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
> +	if (ret < 0) {
> +		bool enable;
> +		ret = kstrtobool_from_user(ubuf, len, &enable);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		val = enable;
> +	}
> +
> +	if (val != PSR_DEBUGFS_MODE_DEFAULT &&
> +	    val != PSR_DEBUGFS_MODE_DISABLED &&
> +	    val != PSR_DEBUGFS_MODE_ENABLED)
> +		return -EINVAL;
> +
> +	intel_runtime_pm_get(dev_priv);
> +
> +	drm_modeset_acquire_init(&ctx,
> DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +retry:
> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
> +	if (ret == -EBUSY) {
> +		ret = drm_modeset_backoff(&ctx);
> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);

Deadlocked here during testing

$ echo 0 >  /sys/kernel/debug/dri/0/i915_edp_psr_status
bash: echo: write error: Resource deadlock avoided

[ 1248.856671] WARNING: CPU: 2 PID: 1788 at
drivers/gpu/drm/drm_modeset_lock.c:223 drm_modeset_drop_locks+0x56/0x60
[drm]
[ 1248.856757] Modules linked in: rfcomm cmac bnep arc4 iwlmvm
nls_iso8859_1 mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek
snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep
snd_hda_core iwlwifi snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi intel_rapl btusb btrtl snd_seq btbcm x86_pkg_temp_thermal
btintel intel_powerclamp bluetooth coretemp crct10dif_pclmul
crc32_pclmul snd_timer snd_seq_device ghash_clmulni_intel cfg80211
aesni_intel snd aes_x86_64 crypto_simd cryptd soundcore ecdh_generic
glue_helper input_leds mei_me mei intel_pch_thermal mac_hid parport_pc
ppdev lp parport autofs4 i915 i2c_algo_bit drm_kms_helper syscopyarea
sysfillrect sysimgblt fb_sys_fops drm e1000e psmouse ahci libahci video
[ 1248.857288] CPU: 2 PID: 1788 Comm: bash Not tainted 4.18.0-rc6drm-
tip #138
[ 1248.857297] Hardware name: LENOVO 20F6CTO1WW/20F6CTO1WW, BIOS
R02ET48W (1.21 ) 06/01/2016
[ 1248.857354] RIP: 0010:drm_modeset_drop_locks+0x56/0x60 [drm]
[ 1248.857363] Code: 50 08 48 8d b8 50 ff ff ff 48 89 51 08 48 89 0a 48
89 00 48 89 40 08 e8 a8 90 7d c9 48 8b 43 70 49 39 c4 75 d2 5b 41 5c 5d
c3 <0f> 0b eb bc 66 0f 1f 44 00 00 0f 1f 44 00 00 48 8b 97 d0 0a 00 00
[ 1248.857860] RSP: 0018:ffffa4dd01fabcf8 EFLAGS: 00010286
[ 1248.857878] RAX: 00000000ffffffdd RBX: ffffa4dd01fabd28 RCX:
0000000000000000
[ 1248.857889] RDX: 0000000000000000 RSI: ffff97bb88476898 RDI:
ffffa4dd01fabd28
[ 1248.857898] RBP: ffffa4dd01fabd08 R08: 0000000000000000 R09:
0000000000000001
[ 1248.857908] R10: 0000000000000001 R11: 0000000000000000 R12:
0000000000000002
[ 1248.857918] R13: 00005603cdb60880 R14: 0000000000000002 R15:
ffffa4dd01fabee8
[ 1248.857930] FS:  00007f83b1dea740(0000) GS:ffff97bb99a00000(0000)
knlGS:0000000000000000
[ 1248.857940] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1248.857950] CR2: 00005603cdb60880 CR3: 0000000214338003 CR4:
00000000003606e0
[ 1248.857959] Call Trace:
[ 1248.858094]  i915_edp_psr_write+0xd5/0x180 [i915]
[ 1248.858172]  full_proxy_write+0x5f/0x90
[ 1248.858207]  __vfs_write+0x3a/0x1a0
[ 1248.858227]  ? rcu_read_lock_sched_held+0x79/0x80
[ 1248.858243]  ? rcu_sync_lockdep_assert+0x32/0x60
[ 1248.858260]  ? __sb_start_write+0x135/0x190
[ 1248.858275]  ? vfs_write+0x193/0x1c0
[ 1248.858306]  vfs_write+0xc6/0x1c0
[ 1248.858335]  ksys_write+0x58/0xc0
[ 1248.858370]  __x64_sys_write+0x1a/0x20
[ 1248.858387]  do_syscall_64+0x65/0x1b0
[ 1248.858409]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 1248.858423] RIP: 0033:0x7f83b14f2154
[ 1248.858430] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00
00 00 00 66 90 48 8d 05 b1 07 2e 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f
05 <48> 3d 00 f0 ff ff 77 54 f3 c3 66 90 41 54 55 49 89 d4 53 48 89 f5
[ 1248.858928] RSP: 002b:00007ffee7320168 EFLAGS: 00000246 ORIG_RAX:
0000000000000001
[ 1248.858946] RAX: ffffffffffffffda RBX: 0000000000000002 RCX:
00007f83b14f2154
[ 1248.858956] RDX: 0000000000000002 RSI: 00005603cdb60880 RDI:
0000000000000001
[ 1248.858965] RBP: 00005603cdb60880 R08: 000000000000000a R09:
0000000000000001
[ 1248.858975] R10: 000000000000000a R11: 0000000000000246 R12:
00007f83b17ce760
[ 1248.858984] R13: 0000000000000002 R14: 00007f83b17ca2a0 R15:
00007f83b17c9760
[ 1248.859043] irq event stamp: 59768
[ 1248.859058] hardirqs last  enabled at (59767): [<ffffffff89a31dc6>]
_raw_spin_unlock_irqrestore+0x36/0x60
[ 1248.859072] hardirqs last disabled at (59768): [<ffffffff89c01309>]
error_entry+0x89/0x110
[ 1248.859087] softirqs last  enabled at (59724): [<ffffffff89e00378>]
__do_softirq+0x378/0x4e3
[ 1248.859100] softirqs last disabled at (59711): [<ffffffff89098e0d>]
irq_exit+0xcd/0xe0
[ 1248.859156] WARNING: CPU: 2 PID: 1788 at
drivers/gpu/drm/drm_modeset_lock.c:223 drm_modeset_drop_locks+0x56/0x60
[drm]
[ 1248.859166] ---[ end trace b7222f9239d3065b ]--


> +
> +	intel_runtime_pm_put(dev_priv);
> +
> +	return ret ?: len;
> +}
> +
> +static int i915_edp_psr_open(struct inode *inode, struct file *file)
> +{
> +	struct drm_i915_private *dev_priv = inode->i_private;
> +
> +	if (!HAS_PSR(dev_priv))
> +		return -ENODEV;
> +
> +	return single_open(file, i915_edp_psr_status, dev_priv);

What do you think of using "i915_edp_psr_debug" instead?

> +}
> +
> +static const struct file_operations i915_edp_psr_ops = {
> +	.owner = THIS_MODULE,
> +	.open = i915_edp_psr_open,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +	.write = i915_edp_psr_write
> +};
> +
>  static int i915_energy_uJ(struct seq_file *m, void *data)
>  {
>  	struct drm_i915_private *dev_priv = node_to_i915(m-
> >private);
> @@ -4720,7 +4783,6 @@ static const struct drm_info_list
> i915_debugfs_list[] = {
>  	{"i915_swizzle_info", i915_swizzle_info, 0},
>  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
>  	{"i915_llc", i915_llc, 0},
> -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
>  	{"i915_energy_uJ", i915_energy_uJ, 0},
>  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
>  	{"i915_power_domain_info", i915_power_domain_info, 0},
> @@ -4744,6 +4806,7 @@ static const struct i915_debugfs_files {
>  	const struct file_operations *fops;
>  } i915_debugfs_files[] = {
>  	{"i915_wedged", &i915_wedged_fops},
> +	{"i915_edp_psr_status", &i915_edp_psr_ops},
>  	{"i915_cache_sharing", &i915_cache_sharing_fops},
>  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
>  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h
> index 0f49f9988dfa..d8583770e8a6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -612,7 +612,8 @@ struct i915_drrs {
>  struct i915_psr {
>  	struct mutex lock;
>  	bool sink_support;
> -	struct intel_dp *enabled;
> +	bool enabled;
> +	struct intel_dp *dp;
Separate patch for this change? How about keeping i915_psr.dp always
valid?

>  	bool active;
>  	struct work_struct work;
>  	unsigned busy_frontbuffer_bits;
> @@ -625,6 +626,12 @@ struct i915_psr {
>  	bool debug;
>  	ktime_t last_entry_attempt;
>  	ktime_t last_exit;
> +
> +	enum i915_psr_debugfs_mode {
> +		PSR_DEBUGFS_MODE_DEFAULT = -1,
> +		PSR_DEBUGFS_MODE_DISABLED,
> +		PSR_DEBUGFS_MODE_ENABLED

If we add another enum, we can write tests to enable PSR1 on PSR2
panels.
		PSR_DEBUGFS_MODE_PSR1
		PSR_DEBUGFS_MODE_PSR2
> +	} debugfs_mode;
>  };
>  
>  enum intel_pch {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index c275f91244a6..751ed257fbba 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1926,6 +1926,9 @@ void intel_psr_enable(struct intel_dp
> *intel_dp,
>  		      const struct intel_crtc_state *crtc_state);
>  void intel_psr_disable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state
> *old_crtc_state);
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       enum i915_psr_debugfs_mode mode);
>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  			  unsigned frontbuffer_bits,
>  			  enum fb_op_origin origin);
> diff --git a/drivers/gpu/drm/i915/intel_psr.c
> b/drivers/gpu/drm/i915/intel_psr.c
> index 4bd5768731ee..97424ae769f3 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -56,6 +56,16 @@
>  #include "intel_drv.h"
>  #include "i915_drv.h"
>  
> +static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
> +{
> +	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
> +		return i915_modparams.enable_psr;
> +	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
> +		return false;
> +	else
> +		return true;
> +}
> +
>  void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool
> debug)
>  {
>  	u32 debug_mask, mask;
> @@ -471,11 +481,6 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>  	if (!CAN_PSR(dev_priv))
>  		return;
>  
> -	if (!i915_modparams.enable_psr) {
> -		DRM_DEBUG_KMS("PSR disable by flag\n");
> -		return;
> -	}
> -
>  	/*
>  	 * HSW spec explicitly says PSR is tied to port A.
>  	 * BDW+ platforms with DDI implementation of PSR have
> different
> @@ -517,7 +522,11 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>  
>  	crtc_state->has_psr = true;
>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
> crtc_state);
> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2"
> : "");
> +
> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state-
> >has_psr2 ? "2" : "");
This gets printed during a modeset that is shutting down the crtc.

> +	else
> +		DRM_DEBUG_KMS("PSR disable by flag\n");


>  }

So, neither debugfs nor modparam has any effect on crtc_state->has_psr
or crtc_state->has_psr2. Why was this check moved to the end? 

We could also rewrite the debug message to look similar to the other
compute_config functions

>  
>  static void intel_psr_activate(struct intel_dp *intel_dp)
> @@ -589,6 +598,22 @@ static void intel_psr_enable_source(struct
> intel_dp *intel_dp,
>  	}
>  }
>  
> +static void intel_psr_enable_locked(struct drm_i915_private
> *dev_priv,
> +				    const struct intel_crtc_state
> *crtc_state)
> +{
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
> +
> +	if (dev_priv->psr.enabled)
> +		return;
> +
This function gets called from intel_psr_set_debugfs_mode() Doesn't
this allow debugfs to enable PSR even if mode related checks in
psr_compute_config() had failed? For e.g., crtc_state->has_psr was
false.

> +	intel_psr_setup_vsc(intel_dp, crtc_state);
> +	intel_psr_enable_sink(intel_dp);
> +	intel_psr_enable_source(intel_dp, crtc_state);
> +	dev_priv->psr.enabled = true;
> +
> +	intel_psr_activate(intel_dp);
> +}
> +
>  /**
>   * intel_psr_enable - Enable PSR
>   * @intel_dp: Intel DP
> @@ -611,7 +636,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  
>  	WARN_ON(dev_priv->drrs.dp);
>  	mutex_lock(&dev_priv->psr.lock);
> -	if (dev_priv->psr.enabled) {
> +	if (dev_priv->psr.dp) {

Check for dev_priv->psr.enabled instead?

>  		DRM_DEBUG_KMS("PSR already in use\n");
>  		goto unlock;
>  	}
> @@ -619,12 +644,10 @@ void intel_psr_enable(struct intel_dp
> *intel_dp,
>  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>  
> -	intel_psr_setup_vsc(intel_dp, crtc_state);
> -	intel_psr_enable_sink(intel_dp);
> -	intel_psr_enable_source(intel_dp, crtc_state);
> -	dev_priv->psr.enabled = intel_dp;
> +	dev_priv->psr.dp = intel_dp;

Now that there is psr.enabled, should we always keep this pointer
valid? 

>  
> -	intel_psr_activate(intel_dp);
> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))

Okay, now I see why you have psr_global_enabled() as the last check in
psr_compute_config().

> +		intel_psr_enable_locked(dev_priv, crtc_state);
>  
>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
> @@ -688,7 +711,7 @@ static void intel_psr_disable_locked(struct
> intel_dp *intel_dp)
>  	/* Disable PSR on Sink */
>  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
>  
> -	dev_priv->psr.enabled = NULL;
> +	dev_priv->psr.enabled = false;
>  }
>  
>  /**
> @@ -712,7 +735,14 @@ void intel_psr_disable(struct intel_dp
> *intel_dp,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> +	if (intel_dp != dev_priv->psr.dp) {
> +		mutex_unlock(&dev_priv->psr.lock);
> +		return;
> +	}
> +
>  	intel_psr_disable_locked(intel_dp);
> +
> +	dev_priv->psr.dp = NULL;
Is there still a need to use this field as flag?

>  	mutex_lunlock(&dev_priv->psr.lock);
>  	cancel_work_sync(&dev_priv->psr.work);
>  }
> @@ -756,13 +786,11 @@ int intel_psr_wait_for_idle(const struct
> intel_crtc_state *new_crtc_state)
>  
>  static bool __psr_wait_for_idle_locked(struct drm_i915_private
> *dev_priv)
>  {
> -	struct intel_dp *intel_dp;
>  	i915_reg_t reg;
>  	u32 mask;
>  	int err;
>  
> -	intel_dp = dev_priv->psr.enabled;
> -	if (!intel_dp)
> +	if (!dev_priv->psr.enabled)
>  		return false;
>  
>  	if (dev_priv->psr.psr2_enabled) {
> @@ -784,6 +812,89 @@ static bool __psr_wait_for_idle_locked(struct
> drm_i915_private *dev_priv)
>  	return err == 0 && dev_priv->psr.enabled;
>  }
>  
> +static struct drm_crtc *
> +find_idle_crtc_for_encoder(struct drm_encoder *encoder,
> +			   struct drm_modeset_acquire_ctx *ctx)
> +{
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_device *dev = encoder->dev;
> +	struct drm_connector *connector;
> +	struct drm_crtc *crtc;
> +	bool found = false;
> +	int ret;
> +
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter)
> +		if (connector->state->best_encoder == encoder) {
> +			found = true;
> +			break;
> +		}
> +	drm_connector_list_iter_end(&conn_iter);
> +
> +	if (WARN_ON(!found))
> +		return ERR_PTR(-EINVAL);
> +
> +	crtc = connector->state->crtc;
> +	ret = drm_modeset_lock(&crtc->mutex, ctx);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	if (connector->state->commit)
> +		ret = wait_for_completion_interruptible(&connector-
> >state->commit->hw_done);
> +	if (!ret && crtc->state->commit)
> +		ret = wait_for_completion_interruptible(&crtc-
> >state->commit->hw_done);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return crtc;
> +}
> +
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       enum i915_psr_debugfs_mode mode)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct drm_encoder *encoder;
> +	struct drm_crtc *crtc;
> +	int ret;
> +	bool enable;
> +
> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
> ctx);
> +	if (ret)
> +		return ret;
> +
> +	enable = psr_global_enabled(mode);
> +
> +	mutex_lock(&dev_priv->psr.lock);
> +
> +	do {
> +		if (!dev_priv->psr.dp) {
> +			dev_priv->psr.debugfs_mode = mode;
> +			goto end;
> +		}
> +		encoder = &dp_to_dig_port(dev_priv->psr.dp)-
> >base.base;
> +		mutex_unlock(&dev_priv->psr.lock);
> +
> +		crtc = find_idle_crtc_for_encoder(encoder, ctx);
> +		if (IS_ERR(crtc))
> +			return PTR_ERR(crtc);
> +
> +		mutex_lock(&dev_priv->psr.lock);
> +	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
When will this not be true?

> +
> +	if (!enable)
> +		intel_psr_disable_locked(enc_to_intel_dp(encoder));
> +
> +	dev_priv->psr.debugfs_mode = mode;
> +
> +	if (enable)
bspec says PSR enable sequence requires ": The associated transcoder
and port are running and Aux channel associated with this port has IO
power enabled" Shouldn't crtc_state->active be checked.

> +		intel_psr_enable_locked(dev_priv,
> to_intel_crtc_state(crtc->state));
> +
> +end:
> +	mutex_unlock(&dev_priv->psr.lock);
> +	return ret;
> +}
> +
>  static void intel_psr_work(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -811,7 +922,8 @@ static void intel_psr_work(struct work_struct
> *work)
>  	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv-
> >psr.active)
>  		goto unlock;
>  
> -	intel_psr_activate(dev_priv->psr.enabled);
> +	intel_psr_activate(dev_priv->psr.dp
> +);
Spurious new line.

>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
>  }
> @@ -866,7 +978,7 @@ void intel_psr_invalidate(struct drm_i915_private
> *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> >base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -909,7 +1021,7 @@ void intel_psr_flush(struct drm_i915_private
> *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> >base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -971,6 +1083,8 @@ void intel_psr_init(struct drm_i915_private
> *dev_priv)
>  		/* For new platforms let's respect VBT back again */
>  		dev_priv->psr.link_standby = dev_priv-
> >vbt.psr.full_link;
>  
> +	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
> +
>  	INIT_WORK(&dev_priv->psr.work, intel_psr_work);
>  	mutex_init(&dev_priv->psr.lock);
>  }
> @@ -991,7 +1105,7 @@ void intel_psr_short_pulse(struct intel_dp
> *intel_dp)
>  
>  	mutex_lock(&psr->lock);
>  
> -	if (psr->enabled != intel_dp)
> +	if (!psr->enabled || psr->dp != intel_dp)
>  		goto exit;
>  
>  	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val)
> != 1) {
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3.
  2018-07-27  3:27             ` Dhinakaran Pandiyan
@ 2018-07-27  8:41               ` Maarten Lankhorst
  2018-07-28  5:23                 ` Dhinakaran Pandiyan
  0 siblings, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-27  8:41 UTC (permalink / raw)
  To: dhinakaran.pandiyan, intel-gfx; +Cc: Rodrigo Vivi

Op 27-07-18 om 05:27 schreef Dhinakaran Pandiyan:
> On Thu, 2018-07-26 at 11:06 +0200, Maarten Lankhorst wrote:
>> Currently tests modify i915.enable_psr and then do a modeset cycle
>> to change PSR. We can write a value to i915_edp_psr_status to force
>> a certain value without a modeset.
>>
>> To retain compatibility with older userspace, we also still allow
>> the override through the module parameter, and add some tracking
>> to check whether a debugfs mode is specified.
>>
>> Changes since v1:
>> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
>> .enabled.
>> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
>> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>>   it and move it to intel_psr.c. This keeps all internals in
>> intel_psr.c
>> - Perform an interruptible wait for hw completion outside of the psr
>>   lock, instead of being forced to trywait and return -EBUSY.
>> Changes since v2:
>> - Rebase on top of intel_psr changes.
> Thanks for resending this, I have some questions to understand the
> patch better.
>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
>> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c |  75 ++++++++++++--
>>  drivers/gpu/drm/i915/i915_drv.h     |   9 +-
>>  drivers/gpu/drm/i915/intel_drv.h    |   3 +
>>  drivers/gpu/drm/i915/intel_psr.c    | 154 ++++++++++++++++++++++++
>> ----
>>  4 files changed, 214 insertions(+), 27 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>> b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 59dc0610ea44..b2904bb2be49 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -2689,14 +2689,11 @@ psr_source_status(struct drm_i915_private
>> *dev_priv, struct seq_file *m)
>>  
>>  static int i915_edp_psr_status(struct seq_file *m, void *data)
>>  {
>> -	struct drm_i915_private *dev_priv = node_to_i915(m-
>>> private);
>> +	struct drm_i915_private *dev_priv = m->private;
>>  	u32 psrperf = 0;
>>  	bool enabled = false;
>>  	bool sink_support;
>>  
>> -	if (!HAS_PSR(dev_priv))
>> -		return -ENODEV;
>> -
>>  	sink_support = dev_priv->psr.sink_support;
>>  	seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
>>  	if (!sink_support)
>> @@ -2705,7 +2702,7 @@ static int i915_edp_psr_status(struct seq_file
>> *m, void *data)
>>  	intel_runtime_pm_get(dev_priv);
>>  
>>  	mutex_lock(&dev_priv->psr.lock);
>> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
>>> psr.enabled));
>> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
>>> psr.enabled));
>>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>>  		   dev_priv->psr.busy_frontbuffer_bits);
>>  
>> @@ -2776,6 +2773,72 @@
>> DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
>>  			i915_edp_psr_debug_get,
>> i915_edp_psr_debug_set,
>>  			"%llu\n");
>>  
>> +static ssize_t i915_edp_psr_write(struct file *file, const char
>> __user *ubuf,
>> +				  size_t len, loff_t *offp)
>> +{
>> +	struct seq_file *m = file->private_data;
>> +	struct drm_i915_private *dev_priv = m->private;
>> +	struct drm_modeset_acquire_ctx ctx;
>> +	int ret, val;
>> +
>> +	if (!dev_priv->psr.sink_support)
>> +		return -ENODEV;
>> +
>> +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
>> +	if (ret < 0) {
>> +		bool enable;
>> +		ret = kstrtobool_from_user(ubuf, len, &enable);
>> +
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		val = enable;
>> +	}
>> +
>> +	if (val != PSR_DEBUGFS_MODE_DEFAULT &&
>> +	    val != PSR_DEBUGFS_MODE_DISABLED &&
>> +	    val != PSR_DEBUGFS_MODE_ENABLED)
>> +		return -EINVAL;
>> +
>> +	intel_runtime_pm_get(dev_priv);
>> +
>> +	drm_modeset_acquire_init(&ctx,
>> DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
>> +
>> +retry:
>> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
>> +	if (ret == -EBUSY) {
>> +		ret = drm_modeset_backoff(&ctx);
>> +		if (!ret)
>> +			goto retry;
>> +	}
>> +
>> +	drm_modeset_drop_locks(&ctx);
>> +	drm_modeset_acquire_fini(&ctx);
> Deadlocked here during testing
>
> $ echo 0 >  /sys/kernel/debug/dri/0/i915_edp_psr_status
> bash: echo: write error: Resource deadlock avoided
Oops, that check should be: "if (ret == -EDEADLK)"

That should fix your error. :)
> [ 1248.856671] WARNING: CPU: 2 PID: 1788 at
> drivers/gpu/drm/drm_modeset_lock.c:223 drm_modeset_drop_locks+0x56/0x60
> [drm]
> [ 1248.856757] Modules linked in: rfcomm cmac bnep arc4 iwlmvm
> nls_iso8859_1 mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek
> snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep
> snd_hda_core iwlwifi snd_pcm snd_seq_midi snd_seq_midi_event
> snd_rawmidi intel_rapl btusb btrtl snd_seq btbcm x86_pkg_temp_thermal
> btintel intel_powerclamp bluetooth coretemp crct10dif_pclmul
> crc32_pclmul snd_timer snd_seq_device ghash_clmulni_intel cfg80211
> aesni_intel snd aes_x86_64 crypto_simd cryptd soundcore ecdh_generic
> glue_helper input_leds mei_me mei intel_pch_thermal mac_hid parport_pc
> ppdev lp parport autofs4 i915 i2c_algo_bit drm_kms_helper syscopyarea
> sysfillrect sysimgblt fb_sys_fops drm e1000e psmouse ahci libahci video
> [ 1248.857288] CPU: 2 PID: 1788 Comm: bash Not tainted 4.18.0-rc6drm-
> tip #138
> [ 1248.857297] Hardware name: LENOVO 20F6CTO1WW/20F6CTO1WW, BIOS
> R02ET48W (1.21 ) 06/01/2016
> [ 1248.857354] RIP: 0010:drm_modeset_drop_locks+0x56/0x60 [drm]
> [ 1248.857363] Code: 50 08 48 8d b8 50 ff ff ff 48 89 51 08 48 89 0a 48
> 89 00 48 89 40 08 e8 a8 90 7d c9 48 8b 43 70 49 39 c4 75 d2 5b 41 5c 5d
> c3 <0f> 0b eb bc 66 0f 1f 44 00 00 0f 1f 44 00 00 48 8b 97 d0 0a 00 00
> [ 1248.857860] RSP: 0018:ffffa4dd01fabcf8 EFLAGS: 00010286
> [ 1248.857878] RAX: 00000000ffffffdd RBX: ffffa4dd01fabd28 RCX:
> 0000000000000000
> [ 1248.857889] RDX: 0000000000000000 RSI: ffff97bb88476898 RDI:
> ffffa4dd01fabd28
> [ 1248.857898] RBP: ffffa4dd01fabd08 R08: 0000000000000000 R09:
> 0000000000000001
> [ 1248.857908] R10: 0000000000000001 R11: 0000000000000000 R12:
> 0000000000000002
> [ 1248.857918] R13: 00005603cdb60880 R14: 0000000000000002 R15:
> ffffa4dd01fabee8
> [ 1248.857930] FS:  00007f83b1dea740(0000) GS:ffff97bb99a00000(0000)
> knlGS:0000000000000000
> [ 1248.857940] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 1248.857950] CR2: 00005603cdb60880 CR3: 0000000214338003 CR4:
> 00000000003606e0
> [ 1248.857959] Call Trace:
> [ 1248.858094]  i915_edp_psr_write+0xd5/0x180 [i915]
> [ 1248.858172]  full_proxy_write+0x5f/0x90
> [ 1248.858207]  __vfs_write+0x3a/0x1a0
> [ 1248.858227]  ? rcu_read_lock_sched_held+0x79/0x80
> [ 1248.858243]  ? rcu_sync_lockdep_assert+0x32/0x60
> [ 1248.858260]  ? __sb_start_write+0x135/0x190
> [ 1248.858275]  ? vfs_write+0x193/0x1c0
> [ 1248.858306]  vfs_write+0xc6/0x1c0
> [ 1248.858335]  ksys_write+0x58/0xc0
> [ 1248.858370]  __x64_sys_write+0x1a/0x20
> [ 1248.858387]  do_syscall_64+0x65/0x1b0
> [ 1248.858409]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
> [ 1248.858423] RIP: 0033:0x7f83b14f2154
> [ 1248.858430] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00
> 00 00 00 66 90 48 8d 05 b1 07 2e 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f
> 05 <48> 3d 00 f0 ff ff 77 54 f3 c3 66 90 41 54 55 49 89 d4 53 48 89 f5
> [ 1248.858928] RSP: 002b:00007ffee7320168 EFLAGS: 00000246 ORIG_RAX:
> 0000000000000001
> [ 1248.858946] RAX: ffffffffffffffda RBX: 0000000000000002 RCX:
> 00007f83b14f2154
> [ 1248.858956] RDX: 0000000000000002 RSI: 00005603cdb60880 RDI:
> 0000000000000001
> [ 1248.858965] RBP: 00005603cdb60880 R08: 000000000000000a R09:
> 0000000000000001
> [ 1248.858975] R10: 000000000000000a R11: 0000000000000246 R12:
> 00007f83b17ce760
> [ 1248.858984] R13: 0000000000000002 R14: 00007f83b17ca2a0 R15:
> 00007f83b17c9760
> [ 1248.859043] irq event stamp: 59768
> [ 1248.859058] hardirqs last  enabled at (59767): [<ffffffff89a31dc6>]
> _raw_spin_unlock_irqrestore+0x36/0x60
> [ 1248.859072] hardirqs last disabled at (59768): [<ffffffff89c01309>]
> error_entry+0x89/0x110
> [ 1248.859087] softirqs last  enabled at (59724): [<ffffffff89e00378>]
> __do_softirq+0x378/0x4e3
> [ 1248.859100] softirqs last disabled at (59711): [<ffffffff89098e0d>]
> irq_exit+0xcd/0xe0
> [ 1248.859156] WARNING: CPU: 2 PID: 1788 at
> drivers/gpu/drm/drm_modeset_lock.c:223 drm_modeset_drop_locks+0x56/0x60
> [drm]
> [ 1248.859166] ---[ end trace b7222f9239d3065b ]--
And this warning.
>
>> +
>> +	intel_runtime_pm_put(dev_priv);
>> +
>> +	return ret ?: len;
>> +}
>> +
>> +static int i915_edp_psr_open(struct inode *inode, struct file *file)
>> +{
>> +	struct drm_i915_private *dev_priv = inode->i_private;
>> +
>> +	if (!HAS_PSR(dev_priv))
>> +		return -ENODEV;
>> +
>> +	return single_open(file, i915_edp_psr_status, dev_priv);
> What do you think of using "i915_edp_psr_debug" instead?
All for it.
>> +}
>> +
>> +static const struct file_operations i915_edp_psr_ops = {
>> +	.owner = THIS_MODULE,
>> +	.open = i915_edp_psr_open,
>> +	.read = seq_read,
>> +	.llseek = seq_lseek,
>> +	.release = single_release,
>> +	.write = i915_edp_psr_write
>> +};
>> +
>>  static int i915_energy_uJ(struct seq_file *m, void *data)
>>  {
>>  	struct drm_i915_private *dev_priv = node_to_i915(m-
>>> private);
>> @@ -4720,7 +4783,6 @@ static const struct drm_info_list
>> i915_debugfs_list[] = {
>>  	{"i915_swizzle_info", i915_swizzle_info, 0},
>>  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
>>  	{"i915_llc", i915_llc, 0},
>> -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
>>  	{"i915_energy_uJ", i915_energy_uJ, 0},
>>  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
>>  	{"i915_power_domain_info", i915_power_domain_info, 0},
>> @@ -4744,6 +4806,7 @@ static const struct i915_debugfs_files {
>>  	const struct file_operations *fops;
>>  } i915_debugfs_files[] = {
>>  	{"i915_wedged", &i915_wedged_fops},
>> +	{"i915_edp_psr_status", &i915_edp_psr_ops},
>>  	{"i915_cache_sharing", &i915_cache_sharing_fops},
>>  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
>>  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h
>> b/drivers/gpu/drm/i915/i915_drv.h
>> index 0f49f9988dfa..d8583770e8a6 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -612,7 +612,8 @@ struct i915_drrs {
>>  struct i915_psr {
>>  	struct mutex lock;
>>  	bool sink_support;
>> -	struct intel_dp *enabled;
>> +	bool enabled;
>> +	struct intel_dp *dp;
> Separate patch for this change? How about keeping i915_psr.dp always
> valid?
I'm keeping i915_psr.dp only valid when the modeset calls intel_psr_enable, until the modeset disable calls intel_psr_disable()
i915_psr.dp is used to also indicate that we can currently enable PSR. .enabled is used to determine it's currently enabled.

>>  	bool active;
>>  	struct work_struct work;
>>  	unsigned busy_frontbuffer_bits;
>> @@ -625,6 +626,12 @@ struct i915_psr {
>>  	bool debug;
>>  	ktime_t last_entry_attempt;
>>  	ktime_t last_exit;
>> +
>> +	enum i915_psr_debugfs_mode {
>> +		PSR_DEBUGFS_MODE_DEFAULT = -1,
>> +		PSR_DEBUGFS_MODE_DISABLED,
>> +		PSR_DEBUGFS_MODE_ENABLED
> If we add another enum, we can write tests to enable PSR1 on PSR2
> panels.
> 		PSR_DEBUGFS_MODE_PSR1
> 		PSR_DEBUGFS_MODE_PSR2
Should be easy to add, but annoying to toggle.

Maybe some followup?
>> +	} debugfs_mode;
>>  };
>>  
>>  enum intel_pch {
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>> b/drivers/gpu/drm/i915/intel_drv.h
>> index c275f91244a6..751ed257fbba 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1926,6 +1926,9 @@ void intel_psr_enable(struct intel_dp
>> *intel_dp,
>>  		      const struct intel_crtc_state *crtc_state);
>>  void intel_psr_disable(struct intel_dp *intel_dp,
>>  		      const struct intel_crtc_state
>> *old_crtc_state);
>> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>> +			       struct drm_modeset_acquire_ctx *ctx,
>> +			       enum i915_psr_debugfs_mode mode);
>>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>>  			  unsigned frontbuffer_bits,
>>  			  enum fb_op_origin origin);
>> diff --git a/drivers/gpu/drm/i915/intel_psr.c
>> b/drivers/gpu/drm/i915/intel_psr.c
>> index 4bd5768731ee..97424ae769f3 100644
>> --- a/drivers/gpu/drm/i915/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/intel_psr.c
>> @@ -56,6 +56,16 @@
>>  #include "intel_drv.h"
>>  #include "i915_drv.h"
>>  
>> +static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
>> +{
>> +	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
>> +		return i915_modparams.enable_psr;
>> +	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
>> +		return false;
>> +	else
>> +		return true;
>> +}
>> +
>>  void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool
>> debug)
>>  {
>>  	u32 debug_mask, mask;
>> @@ -471,11 +481,6 @@ void intel_psr_compute_config(struct intel_dp
>> *intel_dp,
>>  	if (!CAN_PSR(dev_priv))
>>  		return;
>>  
>> -	if (!i915_modparams.enable_psr) {
>> -		DRM_DEBUG_KMS("PSR disable by flag\n");
>> -		return;
>> -	}
>> -
>>  	/*
>>  	 * HSW spec explicitly says PSR is tied to port A.
>>  	 * BDW+ platforms with DDI implementation of PSR have
>> different
>> @@ -517,7 +522,11 @@ void intel_psr_compute_config(struct intel_dp
>> *intel_dp,
>>  
>>  	crtc_state->has_psr = true;
>>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
>> crtc_state);
>> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2"
>> : "");
>> +
>> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
>> +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state-
>>> has_psr2 ? "2" : "");
> This gets printed during a modeset that is shutting down the crtc.
>
>> +	else
>> +		DRM_DEBUG_KMS("PSR disable by flag\n");
>
>>  }
> So, neither debugfs nor modparam has any effect on crtc_state->has_psr
> or crtc_state->has_psr2. Why was this check moved to the end? 
We calculate crtc_state->has_psr(2) to see if PSR can be enabled hardware wise.

This will make sure that the state is correctly written in intel_psr_enable, even if we may not enable PSR by default.
> We could also rewrite the debug message to look similar to the other
> compute_config functions
The debug message could be removed, or moved to intel_psr_enable.
>>  
>>  static void intel_psr_activate(struct intel_dp *intel_dp)
>> @@ -589,6 +598,22 @@ static void intel_psr_enable_source(struct
>> intel_dp *intel_dp,
>>  	}
>>  }
>>  
>> +static void intel_psr_enable_locked(struct drm_i915_private
>> *dev_priv,
>> +				    const struct intel_crtc_state
>> *crtc_state)
>> +{
>> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
>> +
>> +	if (dev_priv->psr.enabled)
>> +		return;
>> +
> This function gets called from intel_psr_set_debugfs_mode() Doesn't
> this allow debugfs to enable PSR even if mode related checks in
> psr_compute_config() had failed? For e.g., crtc_state->has_psr was
> false.
No, see intel_psr_enable. It only sets up state when crtc_state->has_psr is true. This is also why the check in intel_psr_compute_config is moved.
>> +	intel_psr_setup_vsc(intel_dp, crtc_state);
>> +	intel_psr_enable_sink(intel_dp);
>> +	intel_psr_enable_source(intel_dp, crtc_state);
>> +	dev_priv->psr.enabled = true;
>> +
>> +	intel_psr_activate(intel_dp);
>> +}
>> +
>>  /**
>>   * intel_psr_enable - Enable PSR
>>   * @intel_dp: Intel DP
>> @@ -611,7 +636,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>>  
>>  	WARN_ON(dev_priv->drrs.dp);
>>  	mutex_lock(&dev_priv->psr.lock);
>> -	if (dev_priv->psr.enabled) {
>> +	if (dev_priv->psr.dp) {
> Check for dev_priv->psr.enabled instead?
This is handled in intel_psr_enable_locked().

intel_psr_enable configures the state, but may not enable PSR right away if disabled by modparam or debugfs.
>
>>  		DRM_DEBUG_KMS("PSR already in use\n");
>>  		goto unlock;
>>  	}
>> @@ -619,12 +644,10 @@ void intel_psr_enable(struct intel_dp
>> *intel_dp,
>>  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
>>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>>  
>> -	intel_psr_setup_vsc(intel_dp, crtc_state);
>> -	intel_psr_enable_sink(intel_dp);
>> -	intel_psr_enable_source(intel_dp, crtc_state);
>> -	dev_priv->psr.enabled = intel_dp;
>> +	dev_priv->psr.dp = intel_dp;
> Now that there is psr.enabled, should we always keep this pointer
> valid? 
No.
>>  
>> -	intel_psr_activate(intel_dp);
>> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> Okay, now I see why you have psr_global_enabled() as the last check in
> psr_compute_config().
:)
>> +		intel_psr_enable_locked(dev_priv, crtc_state);
>>  
>>  unlock:
>>  	mutex_unlock(&dev_priv->psr.lock);
>> @@ -688,7 +711,7 @@ static void intel_psr_disable_locked(struct
>> intel_dp *intel_dp)
>>  	/* Disable PSR on Sink */
>>  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
>>  
>> -	dev_priv->psr.enabled = NULL;
>> +	dev_priv->psr.enabled = false;
>>  }
>>  
>>  /**
>> @@ -712,7 +735,14 @@ void intel_psr_disable(struct intel_dp
>> *intel_dp,
>>  		return;
>>  
>>  	mutex_lock(&dev_priv->psr.lock);
>> +	if (intel_dp != dev_priv->psr.dp) {
>> +		mutex_unlock(&dev_priv->psr.lock);
>> +		return;
>> +	}
>> +
>>  	intel_psr_disable_locked(intel_dp);
>> +
>> +	dev_priv->psr.dp = NULL;
> Is there still a need to use this field as flag?
Yes.
>>  	mutex_lunlock(&dev_priv->psr.lock);
>>  	cancel_work_sync(&dev_priv->psr.work);
>>  }
>> @@ -756,13 +786,11 @@ int intel_psr_wait_for_idle(const struct
>> intel_crtc_state *new_crtc_state)
>>  
>>  static bool __psr_wait_for_idle_locked(struct drm_i915_private
>> *dev_priv)
>>  {
>> -	struct intel_dp *intel_dp;
>>  	i915_reg_t reg;
>>  	u32 mask;
>>  	int err;
>>  
>> -	intel_dp = dev_priv->psr.enabled;
>> -	if (!intel_dp)
>> +	if (!dev_priv->psr.enabled)
>>  		return false;
>>  
>>  	if (dev_priv->psr.psr2_enabled) {
>> @@ -784,6 +812,89 @@ static bool __psr_wait_for_idle_locked(struct
>> drm_i915_private *dev_priv)
>>  	return err == 0 && dev_priv->psr.enabled;
>>  }
>>  
>> +static struct drm_crtc *
>> +find_idle_crtc_for_encoder(struct drm_encoder *encoder,
>> +			   struct drm_modeset_acquire_ctx *ctx)
>> +{
>> +	struct drm_connector_list_iter conn_iter;
>> +	struct drm_device *dev = encoder->dev;
>> +	struct drm_connector *connector;
>> +	struct drm_crtc *crtc;
>> +	bool found = false;
>> +	int ret;
>> +
>> +	drm_connector_list_iter_begin(dev, &conn_iter);
>> +	drm_for_each_connector_iter(connector, &conn_iter)
>> +		if (connector->state->best_encoder == encoder) {
>> +			found = true;
>> +			break;
>> +		}
>> +	drm_connector_list_iter_end(&conn_iter);
>> +
>> +	if (WARN_ON(!found))
>> +		return ERR_PTR(-EINVAL);
>> +
>> +	crtc = connector->state->crtc;
>> +	ret = drm_modeset_lock(&crtc->mutex, ctx);
>> +	if (ret)
>> +		return ERR_PTR(ret);
>> +
>> +	if (connector->state->commit)
>> +		ret = wait_for_completion_interruptible(&connector-
>>> state->commit->hw_done);
>> +	if (!ret && crtc->state->commit)
>> +		ret = wait_for_completion_interruptible(&crtc-
>>> state->commit->hw_done);
>> +	if (ret)
>> +		return ERR_PTR(ret);
>> +
>> +	return crtc;
>> +}
>> +
>> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>> +			       struct drm_modeset_acquire_ctx *ctx,
>> +			       enum i915_psr_debugfs_mode mode)
>> +{
>> +	struct drm_device *dev = &dev_priv->drm;
>> +	struct drm_encoder *encoder;
>> +	struct drm_crtc *crtc;
>> +	int ret;
>> +	bool enable;
>> +
>> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
>> ctx);
>> +	if (ret)
>> +		return ret;
>> +
>> +	enable = psr_global_enabled(mode);
>> +
>> +	mutex_lock(&dev_priv->psr.lock);
>> +
>> +	do {
>> +		if (!dev_priv->psr.dp) {
>> +			dev_priv->psr.debugfs_mode = mode;
>> +			goto end;
>> +		}
>> +		encoder = &dp_to_dig_port(dev_priv->psr.dp)-
>>> base.base;
>> +		mutex_unlock(&dev_priv->psr.lock);
>> +
>> +		crtc = find_idle_crtc_for_encoder(encoder, ctx);
>> +		if (IS_ERR(crtc))
>> +			return PTR_ERR(crtc);
>> +
>> +		mutex_lock(&dev_priv->psr.lock);
>> +	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
> When will this not be true?
nonblocking modeset, for example.
>> +
>> +	if (!enable)
>> +		intel_psr_disable_locked(enc_to_intel_dp(encoder));
>> +
>> +	dev_priv->psr.debugfs_mode = mode;
>> +
>> +	if (enable)
> bspec says PSR enable sequence requires ": The associated transcoder
> and port are running and Aux channel associated with this port has IO
> power enabled" Shouldn't crtc_state->active be checked.
It's implied by having psr.dp != NULL
>> +		intel_psr_enable_locked(dev_priv,
>> to_intel_crtc_state(crtc->state));
>> +
>> +end:
>> +	mutex_unlock(&dev_priv->psr.lock);
>> +	return ret;
>> +}
>> +
>>  static void intel_psr_work(struct work_struct *work)
>>  {
>>  	struct drm_i915_private *dev_priv =
>> @@ -811,7 +922,8 @@ static void intel_psr_work(struct work_struct
>> *work)
>>  	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv-
>>> psr.active)
>>  		goto unlock;
>>  
>> -	intel_psr_activate(dev_priv->psr.enabled);
>> +	intel_psr_activate(dev_priv->psr.dp
>> +);
> Spurious new line.
Indeed!
>>  unlock:
>>  	mutex_unlock(&dev_priv->psr.lock);
>>  }
>> @@ -866,7 +978,7 @@ void intel_psr_invalidate(struct drm_i915_private
>> *dev_priv,
>>  		return;
>>  	}
>>  
>> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
>>> base.base.crtc;
>> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>>  	pipe = to_intel_crtc(crtc)->pipe;
>>  
>>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
>> @@ -909,7 +1021,7 @@ void intel_psr_flush(struct drm_i915_private
>> *dev_priv,
>>  		return;
>>  	}
>>  
>> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
>>> base.base.crtc;
>> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>>  	pipe = to_intel_crtc(crtc)->pipe;
>>  
>>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
>> @@ -971,6 +1083,8 @@ void intel_psr_init(struct drm_i915_private
>> *dev_priv)
>>  		/* For new platforms let's respect VBT back again */
>>  		dev_priv->psr.link_standby = dev_priv-
>>> vbt.psr.full_link;
>>  
>> +	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
>> +
>>  	INIT_WORK(&dev_priv->psr.work, intel_psr_work);
>>  	mutex_init(&dev_priv->psr.lock);
>>  }
>> @@ -991,7 +1105,7 @@ void intel_psr_short_pulse(struct intel_dp
>> *intel_dp)
>>  
>>  	mutex_lock(&psr->lock);
>>  
>> -	if (psr->enabled != intel_dp)
>> +	if (!psr->enabled || psr->dp != intel_dp)
>>  		goto exit;
>>  
>>  	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val)
>> != 1) {


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

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3.
  2018-07-27  8:41               ` Maarten Lankhorst
@ 2018-07-28  5:23                 ` Dhinakaran Pandiyan
  2018-07-30  9:40                   ` Maarten Lankhorst
  2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
  0 siblings, 2 replies; 31+ messages in thread
From: Dhinakaran Pandiyan @ 2018-07-28  5:23 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx; +Cc: Rodrigo Vivi

On Fri, 2018-07-27 at 10:41 +0200, Maarten Lankhorst wrote:
> Op 27-07-18 om 05:27 schreef Dhinakaran Pandiyan:
> > 
> > On Thu, 2018-07-26 at 11:06 +0200, Maarten Lankhorst wrote:
> > > 
> > > Currently tests modify i915.enable_psr and then do a modeset
> > > cycle
> > > to change PSR. We can write a value to i915_edp_psr_status to
> > > force
> > > a certain value without a modeset.
> > > 
> > > To retain compatibility with older userspace, we also still allow
> > > the override through the module parameter, and add some tracking
> > > to check whether a debugfs mode is specified.
> > > 
> > > Changes since v1:
> > > - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
> > > .enabled.
> > > - Fix i915_psr_debugfs_mode to match the writes to debugfs.
> > > - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode,
> > > simplify
> > >   it and move it to intel_psr.c. This keeps all internals in
> > > intel_psr.c
> > > - Perform an interruptible wait for hw completion outside of the
> > > psr
> > >   lock, instead of being forced to trywait and return -EBUSY.
> > > Changes since v2:
> > > - Rebase on top of intel_psr changes.
> > Thanks for resending this, I have some questions to understand the
> > patch better.
> > 
> > > 
> > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.c
> > > om>
> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_debugfs.c |  75 ++++++++++++--
> > >  drivers/gpu/drm/i915/i915_drv.h     |   9 +-
> > >  drivers/gpu/drm/i915/intel_drv.h    |   3 +
> > >  drivers/gpu/drm/i915/intel_psr.c    | 154
> > > ++++++++++++++++++++++++
> > > ----
> > >  4 files changed, 214 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > > b/drivers/gpu/drm/i915/i915_debugfs.c
> > > index 59dc0610ea44..b2904bb2be49 100644
> > > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > > @@ -2689,14 +2689,11 @@ psr_source_status(struct drm_i915_private
> > > *dev_priv, struct seq_file *m)
> > >  
> > >  static int i915_edp_psr_status(struct seq_file *m, void *data)
> > >  {
> > > -	struct drm_i915_private *dev_priv = node_to_i915(m-
> > > > 
> > > > private);
> > > +	struct drm_i915_private *dev_priv = m->private;
> > >  	u32 psrperf = 0;
> > >  	bool enabled = false;
> > >  	bool sink_support;
> > >  
> > > -	if (!HAS_PSR(dev_priv))
> > > -		return -ENODEV;
> > > -
> > >  	sink_support = dev_priv->psr.sink_support;
> > >  	seq_printf(m, "Sink_Support: %s\n",
> > > yesno(sink_support));
> > >  	if (!sink_support)
> > > @@ -2705,7 +2702,7 @@ static int i915_edp_psr_status(struct
> > > seq_file
> > > *m, void *data)
> > >  	intel_runtime_pm_get(dev_priv);
> > >  
> > >  	mutex_lock(&dev_priv->psr.lock);
> > > -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
> > > > 
> > > > psr.enabled));
> > > +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
> > > > 
> > > > psr.enabled));
> > >  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
> > >  		   dev_priv->psr.busy_frontbuffer_bits);
> > >  
> > > @@ -2776,6 +2773,72 @@
> > > DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
> > >  			i915_edp_psr_debug_get,
> > > i915_edp_psr_debug_set,
> > >  			"%llu\n");
> > >  
> > > +static ssize_t i915_edp_psr_write(struct file *file, const char
> > > __user *ubuf,
> > > +				  size_t len, loff_t *offp)
> > > +{
> > > +	struct seq_file *m = file->private_data;
> > > +	struct drm_i915_private *dev_priv = m->private;
> > > +	struct drm_modeset_acquire_ctx ctx;
> > > +	int ret, val;
> > > +
> > > +	if (!dev_priv->psr.sink_support)
> > > +		return -ENODEV;
> > > +
> > > +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
> > > +	if (ret < 0) {
> > > +		bool enable;
> > > +		ret = kstrtobool_from_user(ubuf, len, &enable);
> > > +
> > > +		if (ret < 0)
> > > +			return ret;
> > > +
> > > +		val = enable;
> > > +	}
> > > +
> > > +	if (val != PSR_DEBUGFS_MODE_DEFAULT &&
> > > +	    val != PSR_DEBUGFS_MODE_DISABLED &&
> > > +	    val != PSR_DEBUGFS_MODE_ENABLED)
> > > +		return -EINVAL;
> > > +
> > > +	intel_runtime_pm_get(dev_priv);
> > > +
> > > +	drm_modeset_acquire_init(&ctx,
> > > DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> > > +
> > > +retry:
> > > +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
> > > +	if (ret == -EBUSY) {
> > > +		ret = drm_modeset_backoff(&ctx);
> > > +		if (!ret)
> > > +			goto retry;
> > > +	}
> > > +
> > > +	drm_modeset_drop_locks(&ctx);
> > > +	drm_modeset_acquire_fini(&ctx);
> > Deadlocked here during testing
> > 
> > $ echo 0 >  /sys/kernel/debug/dri/0/i915_edp_psr_status
> > bash: echo: write error: Resource deadlock avoided
> Oops, that check should be: "if (ret == -EDEADLK)"
> 
> That should fix your error. :)
> > 
> > [ 1248.856671] WARNING: CPU: 2 PID: 1788 at
> > drivers/gpu/drm/drm_modeset_lock.c:223
> > drm_modeset_drop_locks+0x56/0x60
> > [drm]
> > [ 1248.856757] Modules linked in: rfcomm cmac bnep arc4 iwlmvm
> > nls_iso8859_1 mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek
> > snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep
> > snd_hda_core iwlwifi snd_pcm snd_seq_midi snd_seq_midi_event
> > snd_rawmidi intel_rapl btusb btrtl snd_seq btbcm
> > x86_pkg_temp_thermal
> > btintel intel_powerclamp bluetooth coretemp crct10dif_pclmul
> > crc32_pclmul snd_timer snd_seq_device ghash_clmulni_intel cfg80211
> > aesni_intel snd aes_x86_64 crypto_simd cryptd soundcore
> > ecdh_generic
> > glue_helper input_leds mei_me mei intel_pch_thermal mac_hid
> > parport_pc
> > ppdev lp parport autofs4 i915 i2c_algo_bit drm_kms_helper
> > syscopyarea
> > sysfillrect sysimgblt fb_sys_fops drm e1000e psmouse ahci libahci
> > video
> > [ 1248.857288] CPU: 2 PID: 1788 Comm: bash Not tainted 4.18.0-
> > rc6drm-
> > tip #138
> > [ 1248.857297] Hardware name: LENOVO 20F6CTO1WW/20F6CTO1WW, BIOS
> > R02ET48W (1.21 ) 06/01/2016
> > [ 1248.857354] RIP: 0010:drm_modeset_drop_locks+0x56/0x60 [drm]
> > [ 1248.857363] Code: 50 08 48 8d b8 50 ff ff ff 48 89 51 08 48 89
> > 0a 48
> > 89 00 48 89 40 08 e8 a8 90 7d c9 48 8b 43 70 49 39 c4 75 d2 5b 41
> > 5c 5d
> > c3 <0f> 0b eb bc 66 0f 1f 44 00 00 0f 1f 44 00 00 48 8b 97 d0 0a 00
> > 00
> > [ 1248.857860] RSP: 0018:ffffa4dd01fabcf8 EFLAGS: 00010286
> > [ 1248.857878] RAX: 00000000ffffffdd RBX: ffffa4dd01fabd28 RCX:
> > 0000000000000000
> > [ 1248.857889] RDX: 0000000000000000 RSI: ffff97bb88476898 RDI:
> > ffffa4dd01fabd28
> > [ 1248.857898] RBP: ffffa4dd01fabd08 R08: 0000000000000000 R09:
> > 0000000000000001
> > [ 1248.857908] R10: 0000000000000001 R11: 0000000000000000 R12:
> > 0000000000000002
> > [ 1248.857918] R13: 00005603cdb60880 R14: 0000000000000002 R15:
> > ffffa4dd01fabee8
> > [ 1248.857930] FS:  00007f83b1dea740(0000)
> > GS:ffff97bb99a00000(0000)
> > knlGS:0000000000000000
> > [ 1248.857940] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [ 1248.857950] CR2: 00005603cdb60880 CR3: 0000000214338003 CR4:
> > 00000000003606e0
> > [ 1248.857959] Call Trace:
> > [ 1248.858094]  i915_edp_psr_write+0xd5/0x180 [i915]
> > [ 1248.858172]  full_proxy_write+0x5f/0x90
> > [ 1248.858207]  __vfs_write+0x3a/0x1a0
> > [ 1248.858227]  ? rcu_read_lock_sched_held+0x79/0x80
> > [ 1248.858243]  ? rcu_sync_lockdep_assert+0x32/0x60
> > [ 1248.858260]  ? __sb_start_write+0x135/0x190
> > [ 1248.858275]  ? vfs_write+0x193/0x1c0
> > [ 1248.858306]  vfs_write+0xc6/0x1c0
> > [ 1248.858335]  ksys_write+0x58/0xc0
> > [ 1248.858370]  __x64_sys_write+0x1a/0x20
> > [ 1248.858387]  do_syscall_64+0x65/0x1b0
> > [ 1248.858409]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
> > [ 1248.858423] RIP: 0033:0x7f83b14f2154
> > [ 1248.858430] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84
> > 00 00
> > 00 00 00 66 90 48 8d 05 b1 07 2e 00 8b 00 85 c0 75 13 b8 01 00 00
> > 00 0f
> > 05 <48> 3d 00 f0 ff ff 77 54 f3 c3 66 90 41 54 55 49 89 d4 53 48 89
> > f5
> > [ 1248.858928] RSP: 002b:00007ffee7320168 EFLAGS: 00000246
> > ORIG_RAX:
> > 0000000000000001
> > [ 1248.858946] RAX: ffffffffffffffda RBX: 0000000000000002 RCX:
> > 00007f83b14f2154
> > [ 1248.858956] RDX: 0000000000000002 RSI: 00005603cdb60880 RDI:
> > 0000000000000001
> > [ 1248.858965] RBP: 00005603cdb60880 R08: 000000000000000a R09:
> > 0000000000000001
> > [ 1248.858975] R10: 000000000000000a R11: 0000000000000246 R12:
> > 00007f83b17ce760
> > [ 1248.858984] R13: 0000000000000002 R14: 00007f83b17ca2a0 R15:
> > 00007f83b17c9760
> > [ 1248.859043] irq event stamp: 59768
> > [ 1248.859058] hardirqs last  enabled at (59767):
> > [<ffffffff89a31dc6>]
> > _raw_spin_unlock_irqrestore+0x36/0x60
> > [ 1248.859072] hardirqs last disabled at (59768):
> > [<ffffffff89c01309>]
> > error_entry+0x89/0x110
> > [ 1248.859087] softirqs last  enabled at (59724):
> > [<ffffffff89e00378>]
> > __do_softirq+0x378/0x4e3
> > [ 1248.859100] softirqs last disabled at (59711):
> > [<ffffffff89098e0d>]
> > irq_exit+0xcd/0xe0
> > [ 1248.859156] WARNING: CPU: 2 PID: 1788 at
> > drivers/gpu/drm/drm_modeset_lock.c:223
> > drm_modeset_drop_locks+0x56/0x60
> > [drm]
> > [ 1248.859166] ---[ end trace b7222f9239d3065b ]--
> And this warning.
> > 
> > 
> > > 
> > > +
> > > +	intel_runtime_pm_put(dev_priv);
> > > +
> > > +	return ret ?: len;
> > > +}
> > > +
> > > +static int i915_edp_psr_open(struct inode *inode, struct file
> > > *file)
> > > +{
> > > +	struct drm_i915_private *dev_priv = inode->i_private;
> > > +
> > > +	if (!HAS_PSR(dev_priv))
> > > +		return -ENODEV;
> > > +
> > > +	return single_open(file, i915_edp_psr_status, dev_priv);
> > What do you think of using "i915_edp_psr_debug" instead?
> All for it.
> > 
> > > 
> > > +}
> > > +
> > > +static const struct file_operations i915_edp_psr_ops = {
> > > +	.owner = THIS_MODULE,
> > > +	.open = i915_edp_psr_open,
> > > +	.read = seq_read,
> > > +	.llseek = seq_lseek,
> > > +	.release = single_release,
> > > +	.write = i915_edp_psr_write
> > > +};
> > > +
> > >  static int i915_energy_uJ(struct seq_file *m, void *data)
> > >  {
> > >  	struct drm_i915_private *dev_priv = node_to_i915(m-
> > > > 
> > > > private);
> > > @@ -4720,7 +4783,6 @@ static const struct drm_info_list
> > > i915_debugfs_list[] = {
> > >  	{"i915_swizzle_info", i915_swizzle_info, 0},
> > >  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
> > >  	{"i915_llc", i915_llc, 0},
> > > -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
> > >  	{"i915_energy_uJ", i915_energy_uJ, 0},
> > >  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
> > >  	{"i915_power_domain_info", i915_power_domain_info, 0},
> > > @@ -4744,6 +4806,7 @@ static const struct i915_debugfs_files {
> > >  	const struct file_operations *fops;
> > >  } i915_debugfs_files[] = {
> > >  	{"i915_wedged", &i915_wedged_fops},
> > > +	{"i915_edp_psr_status", &i915_edp_psr_ops},
> > >  	{"i915_cache_sharing", &i915_cache_sharing_fops},
> > >  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
> > >  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > > b/drivers/gpu/drm/i915/i915_drv.h
> > > index 0f49f9988dfa..d8583770e8a6 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > @@ -612,7 +612,8 @@ struct i915_drrs {
> > >  struct i915_psr {
> > >  	struct mutex lock;
> > >  	bool sink_support;
> > > -	struct intel_dp *enabled;
> > > +	bool enabled;
> > > +	struct intel_dp *dp;
> > Separate patch for this change? How about keeping i915_psr.dp
> > always
> > valid?
> I'm keeping i915_psr.dp only valid when the modeset calls
> intel_psr_enable, until the modeset disable calls intel_psr_disable()
> i915_psr.dp is used to also indicate that we can currently enable
> PSR. .enabled is used to determine it's currently enabled.
> 

Realized .dp might mean something else after I hit send. Thanks for
explaining it.

I think the field warrants renaming, not the least because now
.psr2_enabled means can enable PSR2
.enabled means psr1 or psr2 is currently enabled
.dp means can enable psr1 or psr2

how about having

{
	bool enable_ready;
	bool enable;
	struct intel_dp *dp;
}

Where .dp is just a pointer to intel_dp, no hidden meaning attached.
Given that the code currently supports PSR on only one encoder, we can
assign dp = intel_dp during init. 


> > 
> > > 
> > >  	bool active;
> > >  	struct work_struct work;
> > >  	unsigned busy_frontbuffer_bits;
> > > @@ -625,6 +626,12 @@ struct i915_psr {
> > >  	bool debug;
> > >  	ktime_t last_entry_attempt;
> > >  	ktime_t last_exit;
> > > +
> > > +	enum i915_psr_debugfs_mode {
> > > +		PSR_DEBUGFS_MODE_DEFAULT = -1,
> > > +		PSR_DEBUGFS_MODE_DISABLED,
> > > +		PSR_DEBUGFS_MODE_ENABLED
> > If we add another enum, we can write tests to enable PSR1 on PSR2
> > panels.
> > 		PSR_DEBUGFS_MODE_PSR1
> > 		PSR_DEBUGFS_MODE_PSR2
> Should be easy to add, but annoying to toggle.
> 
> Maybe some followup?
> > 
> > > 
> > > +	} debugfs_mode;
> > >  };
> > >  
> > >  enum intel_pch {
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > b/drivers/gpu/drm/i915/intel_drv.h
> > > index c275f91244a6..751ed257fbba 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -1926,6 +1926,9 @@ void intel_psr_enable(struct intel_dp
> > > *intel_dp,
> > >  		      const struct intel_crtc_state
> > > *crtc_state);
> > >  void intel_psr_disable(struct intel_dp *intel_dp,
> > >  		      const struct intel_crtc_state
> > > *old_crtc_state);
> > > +int intel_psr_set_debugfs_mode(struct drm_i915_private
> > > *dev_priv,
> > > +			       struct drm_modeset_acquire_ctx
> > > *ctx,
> > > +			       enum i915_psr_debugfs_mode mode);
> > >  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
> > >  			  unsigned frontbuffer_bits,
> > >  			  enum fb_op_origin origin);
> > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > b/drivers/gpu/drm/i915/intel_psr.c
> > > index 4bd5768731ee..97424ae769f3 100644
> > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > @@ -56,6 +56,16 @@
> > >  #include "intel_drv.h"
> > >  #include "i915_drv.h"
> > >  
> > > +static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
> > > +{
> > > +	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
> > > +		return i915_modparams.enable_psr;
> > > +	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
> > > +		return false;
> > > +	else
> > > +		return true;
> > > +}
> > > +
> > >  void intel_psr_irq_control(struct drm_i915_private *dev_priv,
> > > bool
> > > debug)
> > >  {
> > >  	u32 debug_mask, mask;
> > > @@ -471,11 +481,6 @@ void intel_psr_compute_config(struct
> > > intel_dp
> > > *intel_dp,
> > >  	if (!CAN_PSR(dev_priv))
> > >  		return;
> > >  
> > > -	if (!i915_modparams.enable_psr) {
> > > -		DRM_DEBUG_KMS("PSR disable by flag\n");
> > > -		return;
> > > -	}
> > > -
> > >  	/*
> > >  	 * HSW spec explicitly says PSR is tied to port A.
> > >  	 * BDW+ platforms with DDI implementation of PSR have
> > > different
> > > @@ -517,7 +522,11 @@ void intel_psr_compute_config(struct
> > > intel_dp
> > > *intel_dp,
> > >  
> > >  	crtc_state->has_psr = true;
> > >  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
> > > crtc_state);
> > > -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ?
> > > "2"
> > > : "");
> > > +
> > > +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> > > +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state-
> > > > 
> > > > has_psr2 ? "2" : "");
> > This gets printed during a modeset that is shutting down the crtc.
> > 
> > > 
> > > +	else
> > > +		DRM_DEBUG_KMS("PSR disable by flag\n");
> > > 
> > >  }
> > So, neither debugfs nor modparam has any effect on crtc_state-
> > >has_psr
> > or crtc_state->has_psr2. Why was this check moved to the end? 
> We calculate crtc_state->has_psr(2) to see if PSR can be enabled
> hardware wise.
> 
> This will make sure that the state is correctly written in
> intel_psr_enable, even if we may not enable PSR by default.
> > 
> > We could also rewrite the debug message to look similar to the
> > other
> > compute_config functions
> The debug message could be removed, or moved to intel_psr_enable.
let's move enable debug messages to psr_enable_locked() and
psr_disable_locked()

> > 
> > > 
> > >  
> > >  static void intel_psr_activate(struct intel_dp *intel_dp)
> > > @@ -589,6 +598,22 @@ static void intel_psr_enable_source(struct
> > > intel_dp *intel_dp,
> > >  	}
> > >  }
> > >  
> > > +static void intel_psr_enable_locked(struct drm_i915_private
> > > *dev_priv,
> > > +				    const struct
> > > intel_crtc_state
> > > *crtc_state)
> > > +{
> > > +	struct intel_dp *intel_dp = dev_priv->psr.dp;
> > > +
> > > +	if (dev_priv->psr.enabled)
> > > +		return;
> > > +
> > This function gets called from intel_psr_set_debugfs_mode() Doesn't
> > this allow debugfs to enable PSR even if mode related checks in
> > psr_compute_config() had failed? For e.g., crtc_state->has_psr was
> > false.
> No, see intel_psr_enable. It only sets up state when crtc_state-
> >has_psr is true. This is also why the check in
> intel_psr_compute_config is moved.
> > 
> > > 
> > > +	intel_psr_setup_vsc(intel_dp, crtc_state);
> > > +	intel_psr_enable_sink(intel_dp);
> > > +	intel_psr_enable_source(intel_dp, crtc_state);
> > > +	dev_priv->psr.enabled = true;
> > > +
> > > +	intel_psr_activate(intel_dp);
> > > +}
> > > +
> > >  /**
> > >   * intel_psr_enable - Enable PSR
> > >   * @intel_dp: Intel DP
> > > @@ -611,7 +636,7 @@ void intel_psr_enable(struct intel_dp
> > > *intel_dp,
> > >  
> > >  	WARN_ON(dev_priv->drrs.dp);
> > >  	mutex_lock(&dev_priv->psr.lock);
> > > -	if (dev_priv->psr.enabled) {
> > > +	if (dev_priv->psr.dp) {
> > Check for dev_priv->psr.enabled instead?
> This is handled in intel_psr_enable_locked().
> 
> intel_psr_enable configures the state, but may not enable PSR right
> away if disabled by modparam or debugfs.
> > 
> > 
> > > 
> > >  		DRM_DEBUG_KMS("PSR already in use\n");
> > >  		goto unlock;
> > >  	}
> > > @@ -619,12 +644,10 @@ void intel_psr_enable(struct intel_dp
> > > *intel_dp,
> > >  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
> > >  	dev_priv->psr.busy_frontbuffer_bits = 0;
> > >  
> > > -	intel_psr_setup_vsc(intel_dp, crtc_state);
> > > -	intel_psr_enable_sink(intel_dp);
> > > -	intel_psr_enable_source(intel_dp, crtc_state);
> > > -	dev_priv->psr.enabled = intel_dp;
> > > +	dev_priv->psr.dp = intel_dp;
> > Now that there is psr.enabled, should we always keep this pointer
> > valid? 
> No.
> > 
> > > 
> > >  
> > > -	intel_psr_activate(intel_dp);
> > > +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
> > Okay, now I see why you have psr_global_enabled() as the last check
> > in
> > psr_compute_config().
> :)
> > 
> > > 
> > > +		intel_psr_enable_locked(dev_priv, crtc_state);
> > >  
> > >  unlock:
> > >  	mutex_unlock(&dev_priv->psr.lock);
> > > @@ -688,7 +711,7 @@ static void intel_psr_disable_locked(struct
> > > intel_dp *intel_dp)
> > >  	/* Disable PSR on Sink */
> > >  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
> > >  
> > > -	dev_priv->psr.enabled = NULL;
> > > +	dev_priv->psr.enabled = false;
> > >  }
> > >  
> > >  /**
> > > @@ -712,7 +735,14 @@ void intel_psr_disable(struct intel_dp
> > > *intel_dp,
> > >  		return;
> > >  
> > >  	mutex_lock(&dev_priv->psr.lock);
> > > +	if (intel_dp != dev_priv->psr.dp) {
> > > +		mutex_unlock(&dev_priv->psr.lock);
> > > +		return;
> > > +	}
> > > +
> > >  	intel_psr_disable_locked(intel_dp);
> > > +
> > > +	dev_priv->psr.dp = NULL;
> > Is there still a need to use this field as flag?
> Yes.
> > 
> > > 
> > >  	mutex_lunlock(&dev_priv->psr.lock);
> > >  	cancel_work_sync(&dev_priv->psr.work);
> > >  }
> > > @@ -756,13 +786,11 @@ int intel_psr_wait_for_idle(const struct
> > > intel_crtc_state *new_crtc_state)
> > >  
> > >  static bool __psr_wait_for_idle_locked(struct drm_i915_private
> > > *dev_priv)
> > >  {
> > > -	struct intel_dp *intel_dp;
> > >  	i915_reg_t reg;
> > >  	u32 mask;
> > >  	int err;
> > >  
> > > -	intel_dp = dev_priv->psr.enabled;
> > > -	if (!intel_dp)
> > > +	if (!dev_priv->psr.enabled)
> > >  		return false;
> > >  
> > >  	if (dev_priv->psr.psr2_enabled) {
> > > @@ -784,6 +812,89 @@ static bool
> > > __psr_wait_for_idle_locked(struct
> > > drm_i915_private *dev_priv)
> > >  	return err == 0 && dev_priv->psr.enabled;
> > >  }
> > >  
> > > +static struct drm_crtc *
> > > +find_idle_crtc_for_encoder(struct drm_encoder *encoder,
> > > +			   struct drm_modeset_acquire_ctx *ctx)
> > > +{
> > > +	struct drm_connector_list_iter conn_iter;
> > > +	struct drm_device *dev = encoder->dev;
> > > +	struct drm_connector *connector;
> > > +	struct drm_crtc *crtc;
> > > +	bool found = false;
> > > +	int ret;
> > > +
> > > +	drm_connector_list_iter_begin(dev, &conn_iter);
> > > +	drm_for_each_connector_iter(connector, &conn_iter)
> > > +		if (connector->state->best_encoder == encoder) {
> > > +			found = true;
> > > +			break;
> > > +		}
> > > +	drm_connector_list_iter_end(&conn_iter);
> > > +
> > > +	if (WARN_ON(!found))
> > > +		return ERR_PTR(-EINVAL);
> > > +
> > > +	crtc = connector->state->crtc;
> > > +	ret = drm_modeset_lock(&crtc->mutex, ctx);
> > > +	if (ret)
> > > +		return ERR_PTR(ret);
> > > +
> > > +	if (connector->state->commit)
> > > +		ret =
> > > wait_for_completion_interruptible(&connector-
> > > > 
> > > > state->commit->hw_done);
> > > +	if (!ret && crtc->state->commit)
> > > +		ret = wait_for_completion_interruptible(&crtc-
> > > > 
> > > > state->commit->hw_done);
> > > +	if (ret)
> > > +		return ERR_PTR(ret);
> > > +
> > > +	return crtc;
> > > +}
> > > +
> > > +int intel_psr_set_debugfs_mode(struct drm_i915_private
> > > *dev_priv,
> > > +			       struct drm_modeset_acquire_ctx
> > > *ctx,
> > > +			       enum i915_psr_debugfs_mode mode)
> > > +{
> > > +	struct drm_device *dev = &dev_priv->drm;
> > > +	struct drm_encoder *encoder;
> > > +	struct drm_crtc *crtc;
> > > +	int ret;
> > > +	bool enable;
> > > +
> > > +	ret = drm_modeset_lock(&dev-
> > > >mode_config.connection_mutex,
> > > ctx);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	enable = psr_global_enabled(mode);
> > > +
> > > +	mutex_lock(&dev_priv->psr.lock);
> > > +
> > > +	do {
> > > +		if (!dev_priv->psr.dp) {
> > > +			dev_priv->psr.debugfs_mode = mode;
> > > +			goto end;
> > > +		}
> > > +		encoder = &dp_to_dig_port(dev_priv->psr.dp)-
> > > > 
> > > > base.base;
> > > +		mutex_unlock(&dev_priv->psr.lock);
> > > +
> > > +		crtc = find_idle_crtc_for_encoder(encoder, ctx);
> > > +		if (IS_ERR(crtc))
> > > +			return PTR_ERR(crtc);
> > > +
> > > +		mutex_lock(&dev_priv->psr.lock);
> > > +	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
> > When will this not be true?
> nonblocking modeset, for example.

With psr.dp = intel_dp statically assigned in psr_init_dpcd(), can we
get rid of this check? And the connector loop in
find_idle_crtc_for_encoder() can just be intel_dp->attached_connector.


> > 
> > > 
> > > +
> > > +	if (!enable)
> > > +		intel_psr_disable_locked(enc_to_intel_dp(encoder
> > > ));
> > > +
> > > +	dev_priv->psr.debugfs_mode = mode;
> > > +
> > > +	if (enable)
> > bspec says PSR enable sequence requires ": The associated
> > transcoder
> > and port are running and Aux channel associated with this port has
> > IO
> > power enabled" Shouldn't crtc_state->active be checked.
> It's implied by having psr.dp != NULL
> > 
> > > 
> > > +		intel_psr_enable_locked(dev_priv,
> > > to_intel_crtc_state(crtc->state));
> > > +
> > > +end:
> > > +	mutex_unlock(&dev_priv->psr.lock);
> > > +	return ret;
> > > +}
> > > +
> > >  static void intel_psr_work(struct work_struct *work)
> > >  {
> > >  	struct drm_i915_private *dev_priv =
> > > @@ -811,7 +922,8 @@ static void intel_psr_work(struct work_struct
> > > *work)
> > >  	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv-
> > > > 
> > > > psr.active)
> > >  		goto unlock;
> > >  
> > > -	intel_psr_activate(dev_priv->psr.enabled);
> > > +	intel_psr_activate(dev_priv->psr.dp
> > > +);
> > Spurious new line.
> Indeed!
> > 
> > > 
> > >  unlock:
> > >  	mutex_unlock(&dev_priv->psr.lock);
> > >  }
> > > @@ -866,7 +978,7 @@ void intel_psr_invalidate(struct
> > > drm_i915_private
> > > *dev_priv,
> > >  		return;
> > >  	}
> > >  
> > > -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> > > > 
> > > > base.base.crtc;
> > > +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
> > >  	pipe = to_intel_crtc(crtc)->pipe;
> > >  
> > >  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> > > @@ -909,7 +1021,7 @@ void intel_psr_flush(struct drm_i915_private
> > > *dev_priv,
> > >  		return;
> > >  	}
> > >  
> > > -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> > > > 
> > > > base.base.crtc;
> > > +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
> > >  	pipe = to_intel_crtc(crtc)->pipe;
> > >  
> > >  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> > > @@ -971,6 +1083,8 @@ void intel_psr_init(struct drm_i915_private
> > > *dev_priv)
> > >  		/* For new platforms let's respect VBT back
> > > again */
> > >  		dev_priv->psr.link_standby = dev_priv-
> > > > 
> > > > vbt.psr.full_link;
> > >  
> > > +	dev_priv->psr.debugfs_mode = PSR_DEBUGFS_MODE_DEFAULT;
> > > +
> > >  	INIT_WORK(&dev_priv->psr.work, intel_psr_work);
> > >  	mutex_init(&dev_priv->psr.lock);
> > >  }
> > > @@ -991,7 +1105,7 @@ void intel_psr_short_pulse(struct intel_dp
> > > *intel_dp)
> > >  
> > >  	mutex_lock(&psr->lock);
> > >  
> > > -	if (psr->enabled != intel_dp)
> > > +	if (!psr->enabled || psr->dp != intel_dp)
> > >  		goto exit;
> > >  
> > >  	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS,
> > > &val)
> > > != 1) {
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3.
  2018-07-28  5:23                 ` Dhinakaran Pandiyan
@ 2018-07-30  9:40                   ` Maarten Lankhorst
  2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
  1 sibling, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-30  9:40 UTC (permalink / raw)
  To: dhinakaran.pandiyan, intel-gfx; +Cc: Rodrigo Vivi

Op 28-07-18 om 07:23 schreef Dhinakaran Pandiyan:
> On Fri, 2018-07-27 at 10:41 +0200, Maarten Lankhorst wrote:
>> Op 27-07-18 om 05:27 schreef Dhinakaran Pandiyan:
>>> On Thu, 2018-07-26 at 11:06 +0200, Maarten Lankhorst wrote:
>>>> Currently tests modify i915.enable_psr and then do a modeset
>>>> cycle
>>>> to change PSR. We can write a value to i915_edp_psr_status to
>>>> force
>>>> a certain value without a modeset.
>>>>
>>>> To retain compatibility with older userspace, we also still allow
>>>> the override through the module parameter, and add some tracking
>>>> to check whether a debugfs mode is specified.
>>>>
>>>> Changes since v1:
>>>> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
>>>> .enabled.
>>>> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
>>>> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode,
>>>> simplify
>>>>   it and move it to intel_psr.c. This keeps all internals in
>>>> intel_psr.c
>>>> - Perform an interruptible wait for hw completion outside of the
>>>> psr
>>>>   lock, instead of being forced to trywait and return -EBUSY.
>>>> Changes since v2:
>>>> - Rebase on top of intel_psr changes.
>>> Thanks for resending this, I have some questions to understand the
>>> patch better.
>>>
>>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.c
>>>> om>
>>>> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
>>>> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>>>> ---
>>>>  drivers/gpu/drm/i915/i915_debugfs.c |  75 ++++++++++++--
>>>>  drivers/gpu/drm/i915/i915_drv.h     |   9 +-
>>>>  drivers/gpu/drm/i915/intel_drv.h    |   3 +
>>>>  drivers/gpu/drm/i915/intel_psr.c    | 154
>>>> ++++++++++++++++++++++++
>>>> ----
>>>>  4 files changed, 214 insertions(+), 27 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>>>> b/drivers/gpu/drm/i915/i915_debugfs.c
>>>> index 59dc0610ea44..b2904bb2be49 100644
>>>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>>>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>>>> @@ -2689,14 +2689,11 @@ psr_source_status(struct drm_i915_private
>>>> *dev_priv, struct seq_file *m)
>>>>  
>>>>  static int i915_edp_psr_status(struct seq_file *m, void *data)
>>>>  {
>>>> -	struct drm_i915_private *dev_priv = node_to_i915(m-
>>>>> private);
>>>> +	struct drm_i915_private *dev_priv = m->private;
>>>>  	u32 psrperf = 0;
>>>>  	bool enabled = false;
>>>>  	bool sink_support;
>>>>  
>>>> -	if (!HAS_PSR(dev_priv))
>>>> -		return -ENODEV;
>>>> -
>>>>  	sink_support = dev_priv->psr.sink_support;
>>>>  	seq_printf(m, "Sink_Support: %s\n",
>>>> yesno(sink_support));
>>>>  	if (!sink_support)
>>>> @@ -2705,7 +2702,7 @@ static int i915_edp_psr_status(struct
>>>> seq_file
>>>> *m, void *data)
>>>>  	intel_runtime_pm_get(dev_priv);
>>>>  
>>>>  	mutex_lock(&dev_priv->psr.lock);
>>>> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
>>>>> psr.enabled));
>>>> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
>>>>> psr.enabled));
>>>>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>>>>  		   dev_priv->psr.busy_frontbuffer_bits);
>>>>  
>>>> @@ -2776,6 +2773,72 @@
>>>> DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
>>>>  			i915_edp_psr_debug_get,
>>>> i915_edp_psr_debug_set,
>>>>  			"%llu\n");
>>>>  
>>>> +static ssize_t i915_edp_psr_write(struct file *file, const char
>>>> __user *ubuf,
>>>> +				  size_t len, loff_t *offp)
>>>> +{
>>>> +	struct seq_file *m = file->private_data;
>>>> +	struct drm_i915_private *dev_priv = m->private;
>>>> +	struct drm_modeset_acquire_ctx ctx;
>>>> +	int ret, val;
>>>> +
>>>> +	if (!dev_priv->psr.sink_support)
>>>> +		return -ENODEV;
>>>> +
>>>> +	ret = kstrtoint_from_user(ubuf, len, 10, &val);
>>>> +	if (ret < 0) {
>>>> +		bool enable;
>>>> +		ret = kstrtobool_from_user(ubuf, len, &enable);
>>>> +
>>>> +		if (ret < 0)
>>>> +			return ret;
>>>> +
>>>> +		val = enable;
>>>> +	}
>>>> +
>>>> +	if (val != PSR_DEBUGFS_MODE_DEFAULT &&
>>>> +	    val != PSR_DEBUGFS_MODE_DISABLED &&
>>>> +	    val != PSR_DEBUGFS_MODE_ENABLED)
>>>> +		return -EINVAL;
>>>> +
>>>> +	intel_runtime_pm_get(dev_priv);
>>>> +
>>>> +	drm_modeset_acquire_init(&ctx,
>>>> DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
>>>> +
>>>> +retry:
>>>> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
>>>> +	if (ret == -EBUSY) {
>>>> +		ret = drm_modeset_backoff(&ctx);
>>>> +		if (!ret)
>>>> +			goto retry;
>>>> +	}
>>>> +
>>>> +	drm_modeset_drop_locks(&ctx);
>>>> +	drm_modeset_acquire_fini(&ctx);
>>> Deadlocked here during testing
>>>
>>> $ echo 0 >  /sys/kernel/debug/dri/0/i915_edp_psr_status
>>> bash: echo: write error: Resource deadlock avoided
>> Oops, that check should be: "if (ret == -EDEADLK)"
>>
>> That should fix your error. :)
>>> [ 1248.856671] WARNING: CPU: 2 PID: 1788 at
>>> drivers/gpu/drm/drm_modeset_lock.c:223
>>> drm_modeset_drop_locks+0x56/0x60
>>> [drm]
>>> [ 1248.856757] Modules linked in: rfcomm cmac bnep arc4 iwlmvm
>>> nls_iso8859_1 mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek
>>> snd_hda_codec_generic snd_hda_intel snd_hda_codec snd_hwdep
>>> snd_hda_core iwlwifi snd_pcm snd_seq_midi snd_seq_midi_event
>>> snd_rawmidi intel_rapl btusb btrtl snd_seq btbcm
>>> x86_pkg_temp_thermal
>>> btintel intel_powerclamp bluetooth coretemp crct10dif_pclmul
>>> crc32_pclmul snd_timer snd_seq_device ghash_clmulni_intel cfg80211
>>> aesni_intel snd aes_x86_64 crypto_simd cryptd soundcore
>>> ecdh_generic
>>> glue_helper input_leds mei_me mei intel_pch_thermal mac_hid
>>> parport_pc
>>> ppdev lp parport autofs4 i915 i2c_algo_bit drm_kms_helper
>>> syscopyarea
>>> sysfillrect sysimgblt fb_sys_fops drm e1000e psmouse ahci libahci
>>> video
>>> [ 1248.857288] CPU: 2 PID: 1788 Comm: bash Not tainted 4.18.0-
>>> rc6drm-
>>> tip #138
>>> [ 1248.857297] Hardware name: LENOVO 20F6CTO1WW/20F6CTO1WW, BIOS
>>> R02ET48W (1.21 ) 06/01/2016
>>> [ 1248.857354] RIP: 0010:drm_modeset_drop_locks+0x56/0x60 [drm]
>>> [ 1248.857363] Code: 50 08 48 8d b8 50 ff ff ff 48 89 51 08 48 89
>>> 0a 48
>>> 89 00 48 89 40 08 e8 a8 90 7d c9 48 8b 43 70 49 39 c4 75 d2 5b 41
>>> 5c 5d
>>> c3 <0f> 0b eb bc 66 0f 1f 44 00 00 0f 1f 44 00 00 48 8b 97 d0 0a 00
>>> 00
>>> [ 1248.857860] RSP: 0018:ffffa4dd01fabcf8 EFLAGS: 00010286
>>> [ 1248.857878] RAX: 00000000ffffffdd RBX: ffffa4dd01fabd28 RCX:
>>> 0000000000000000
>>> [ 1248.857889] RDX: 0000000000000000 RSI: ffff97bb88476898 RDI:
>>> ffffa4dd01fabd28
>>> [ 1248.857898] RBP: ffffa4dd01fabd08 R08: 0000000000000000 R09:
>>> 0000000000000001
>>> [ 1248.857908] R10: 0000000000000001 R11: 0000000000000000 R12:
>>> 0000000000000002
>>> [ 1248.857918] R13: 00005603cdb60880 R14: 0000000000000002 R15:
>>> ffffa4dd01fabee8
>>> [ 1248.857930] FS:  00007f83b1dea740(0000)
>>> GS:ffff97bb99a00000(0000)
>>> knlGS:0000000000000000
>>> [ 1248.857940] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> [ 1248.857950] CR2: 00005603cdb60880 CR3: 0000000214338003 CR4:
>>> 00000000003606e0
>>> [ 1248.857959] Call Trace:
>>> [ 1248.858094]  i915_edp_psr_write+0xd5/0x180 [i915]
>>> [ 1248.858172]  full_proxy_write+0x5f/0x90
>>> [ 1248.858207]  __vfs_write+0x3a/0x1a0
>>> [ 1248.858227]  ? rcu_read_lock_sched_held+0x79/0x80
>>> [ 1248.858243]  ? rcu_sync_lockdep_assert+0x32/0x60
>>> [ 1248.858260]  ? __sb_start_write+0x135/0x190
>>> [ 1248.858275]  ? vfs_write+0x193/0x1c0
>>> [ 1248.858306]  vfs_write+0xc6/0x1c0
>>> [ 1248.858335]  ksys_write+0x58/0xc0
>>> [ 1248.858370]  __x64_sys_write+0x1a/0x20
>>> [ 1248.858387]  do_syscall_64+0x65/0x1b0
>>> [ 1248.858409]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
>>> [ 1248.858423] RIP: 0033:0x7f83b14f2154
>>> [ 1248.858430] Code: 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84
>>> 00 00
>>> 00 00 00 66 90 48 8d 05 b1 07 2e 00 8b 00 85 c0 75 13 b8 01 00 00
>>> 00 0f
>>> 05 <48> 3d 00 f0 ff ff 77 54 f3 c3 66 90 41 54 55 49 89 d4 53 48 89
>>> f5
>>> [ 1248.858928] RSP: 002b:00007ffee7320168 EFLAGS: 00000246
>>> ORIG_RAX:
>>> 0000000000000001
>>> [ 1248.858946] RAX: ffffffffffffffda RBX: 0000000000000002 RCX:
>>> 00007f83b14f2154
>>> [ 1248.858956] RDX: 0000000000000002 RSI: 00005603cdb60880 RDI:
>>> 0000000000000001
>>> [ 1248.858965] RBP: 00005603cdb60880 R08: 000000000000000a R09:
>>> 0000000000000001
>>> [ 1248.858975] R10: 000000000000000a R11: 0000000000000246 R12:
>>> 00007f83b17ce760
>>> [ 1248.858984] R13: 0000000000000002 R14: 00007f83b17ca2a0 R15:
>>> 00007f83b17c9760
>>> [ 1248.859043] irq event stamp: 59768
>>> [ 1248.859058] hardirqs last  enabled at (59767):
>>> [<ffffffff89a31dc6>]
>>> _raw_spin_unlock_irqrestore+0x36/0x60
>>> [ 1248.859072] hardirqs last disabled at (59768):
>>> [<ffffffff89c01309>]
>>> error_entry+0x89/0x110
>>> [ 1248.859087] softirqs last  enabled at (59724):
>>> [<ffffffff89e00378>]
>>> __do_softirq+0x378/0x4e3
>>> [ 1248.859100] softirqs last disabled at (59711):
>>> [<ffffffff89098e0d>]
>>> irq_exit+0xcd/0xe0
>>> [ 1248.859156] WARNING: CPU: 2 PID: 1788 at
>>> drivers/gpu/drm/drm_modeset_lock.c:223
>>> drm_modeset_drop_locks+0x56/0x60
>>> [drm]
>>> [ 1248.859166] ---[ end trace b7222f9239d3065b ]--
>> And this warning.
>>>
>>>> +
>>>> +	intel_runtime_pm_put(dev_priv);
>>>> +
>>>> +	return ret ?: len;
>>>> +}
>>>> +
>>>> +static int i915_edp_psr_open(struct inode *inode, struct file
>>>> *file)
>>>> +{
>>>> +	struct drm_i915_private *dev_priv = inode->i_private;
>>>> +
>>>> +	if (!HAS_PSR(dev_priv))
>>>> +		return -ENODEV;
>>>> +
>>>> +	return single_open(file, i915_edp_psr_status, dev_priv);
>>> What do you think of using "i915_edp_psr_debug" instead?
>> All for it.
>>>> +}
>>>> +
>>>> +static const struct file_operations i915_edp_psr_ops = {
>>>> +	.owner = THIS_MODULE,
>>>> +	.open = i915_edp_psr_open,
>>>> +	.read = seq_read,
>>>> +	.llseek = seq_lseek,
>>>> +	.release = single_release,
>>>> +	.write = i915_edp_psr_write
>>>> +};
>>>> +
>>>>  static int i915_energy_uJ(struct seq_file *m, void *data)
>>>>  {
>>>>  	struct drm_i915_private *dev_priv = node_to_i915(m-
>>>>> private);
>>>> @@ -4720,7 +4783,6 @@ static const struct drm_info_list
>>>> i915_debugfs_list[] = {
>>>>  	{"i915_swizzle_info", i915_swizzle_info, 0},
>>>>  	{"i915_ppgtt_info", i915_ppgtt_info, 0},
>>>>  	{"i915_llc", i915_llc, 0},
>>>> -	{"i915_edp_psr_status", i915_edp_psr_status, 0},
>>>>  	{"i915_energy_uJ", i915_energy_uJ, 0},
>>>>  	{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
>>>>  	{"i915_power_domain_info", i915_power_domain_info, 0},
>>>> @@ -4744,6 +4806,7 @@ static const struct i915_debugfs_files {
>>>>  	const struct file_operations *fops;
>>>>  } i915_debugfs_files[] = {
>>>>  	{"i915_wedged", &i915_wedged_fops},
>>>> +	{"i915_edp_psr_status", &i915_edp_psr_ops},
>>>>  	{"i915_cache_sharing", &i915_cache_sharing_fops},
>>>>  	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
>>>>  	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
>>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h
>>>> b/drivers/gpu/drm/i915/i915_drv.h
>>>> index 0f49f9988dfa..d8583770e8a6 100644
>>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>>> @@ -612,7 +612,8 @@ struct i915_drrs {
>>>>  struct i915_psr {
>>>>  	struct mutex lock;
>>>>  	bool sink_support;
>>>> -	struct intel_dp *enabled;
>>>> +	bool enabled;
>>>> +	struct intel_dp *dp;
>>> Separate patch for this change? How about keeping i915_psr.dp
>>> always
>>> valid?
>> I'm keeping i915_psr.dp only valid when the modeset calls
>> intel_psr_enable, until the modeset disable calls intel_psr_disable()
>> i915_psr.dp is used to also indicate that we can currently enable
>> PSR. .enabled is used to determine it's currently enabled.
>>
> Realized .dp might mean something else after I hit send. Thanks for
> explaining it.
>
> I think the field warrants renaming, not the least because now
> .psr2_enabled means can enable PSR2
> .enabled means psr1 or psr2 is currently enabled
> .dp means can enable psr1 or psr2
>
> how about having
>
> {
> 	bool enable_ready;
> 	bool enable;
> 	struct intel_dp *dp;
> }
>
> Where .dp is just a pointer to intel_dp, no hidden meaning attached.
> Given that the code currently supports PSR on only one encoder, we can
> assign dp = intel_dp during init. 
Yeah would make sense. I think renaming it from enable_ready to prepared would be more clear..
>
>>>>  	bool active;
>>>>  	struct work_struct work;
>>>>  	unsigned busy_frontbuffer_bits;
>>>> @@ -625,6 +626,12 @@ struct i915_psr {
>>>>  	bool debug;
>>>>  	ktime_t last_entry_attempt;
>>>>  	ktime_t last_exit;
>>>> +
>>>> +	enum i915_psr_debugfs_mode {
>>>> +		PSR_DEBUGFS_MODE_DEFAULT = -1,
>>>> +		PSR_DEBUGFS_MODE_DISABLED,
>>>> +		PSR_DEBUGFS_MODE_ENABLED
>>> If we add another enum, we can write tests to enable PSR1 on PSR2
>>> panels.
>>> 		PSR_DEBUGFS_MODE_PSR1
>>> 		PSR_DEBUGFS_MODE_PSR2
>> Should be easy to add, but annoying to toggle.
>>
>> Maybe some followup?
>>>> +	} debugfs_mode;
>>>>  };
>>>>  
>>>>  enum intel_pch {
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>>>> b/drivers/gpu/drm/i915/intel_drv.h
>>>> index c275f91244a6..751ed257fbba 100644
>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>> @@ -1926,6 +1926,9 @@ void intel_psr_enable(struct intel_dp
>>>> *intel_dp,
>>>>  		      const struct intel_crtc_state
>>>> *crtc_state);
>>>>  void intel_psr_disable(struct intel_dp *intel_dp,
>>>>  		      const struct intel_crtc_state
>>>> *old_crtc_state);
>>>> +int intel_psr_set_debugfs_mode(struct drm_i915_private
>>>> *dev_priv,
>>>> +			       struct drm_modeset_acquire_ctx
>>>> *ctx,
>>>> +			       enum i915_psr_debugfs_mode mode);
>>>>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>>>>  			  unsigned frontbuffer_bits,
>>>>  			  enum fb_op_origin origin);
>>>> diff --git a/drivers/gpu/drm/i915/intel_psr.c
>>>> b/drivers/gpu/drm/i915/intel_psr.c
>>>> index 4bd5768731ee..97424ae769f3 100644
>>>> --- a/drivers/gpu/drm/i915/intel_psr.c
>>>> +++ b/drivers/gpu/drm/i915/intel_psr.c
>>>> @@ -56,6 +56,16 @@
>>>>  #include "intel_drv.h"
>>>>  #include "i915_drv.h"
>>>>  
>>>> +static bool psr_global_enabled(enum i915_psr_debugfs_mode mode)
>>>> +{
>>>> +	if (mode == PSR_DEBUGFS_MODE_DEFAULT)
>>>> +		return i915_modparams.enable_psr;
>>>> +	else if (mode == PSR_DEBUGFS_MODE_DISABLED)
>>>> +		return false;
>>>> +	else
>>>> +		return true;
>>>> +}
>>>> +
>>>>  void intel_psr_irq_control(struct drm_i915_private *dev_priv,
>>>> bool
>>>> debug)
>>>>  {
>>>>  	u32 debug_mask, mask;
>>>> @@ -471,11 +481,6 @@ void intel_psr_compute_config(struct
>>>> intel_dp
>>>> *intel_dp,
>>>>  	if (!CAN_PSR(dev_priv))
>>>>  		return;
>>>>  
>>>> -	if (!i915_modparams.enable_psr) {
>>>> -		DRM_DEBUG_KMS("PSR disable by flag\n");
>>>> -		return;
>>>> -	}
>>>> -
>>>>  	/*
>>>>  	 * HSW spec explicitly says PSR is tied to port A.
>>>>  	 * BDW+ platforms with DDI implementation of PSR have
>>>> different
>>>> @@ -517,7 +522,11 @@ void intel_psr_compute_config(struct
>>>> intel_dp
>>>> *intel_dp,
>>>>  
>>>>  	crtc_state->has_psr = true;
>>>>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
>>>> crtc_state);
>>>> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ?
>>>> "2"
>>>> : "");
>>>> +
>>>> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
>>>> +		DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state-
>>>>> has_psr2 ? "2" : "");
>>> This gets printed during a modeset that is shutting down the crtc.
>>>
>>>> +	else
>>>> +		DRM_DEBUG_KMS("PSR disable by flag\n");
>>>>
>>>>  }
>>> So, neither debugfs nor modparam has any effect on crtc_state-
>>>> has_psr
>>> or crtc_state->has_psr2. Why was this check moved to the end? 
>> We calculate crtc_state->has_psr(2) to see if PSR can be enabled
>> hardware wise.
>>
>> This will make sure that the state is correctly written in
>> intel_psr_enable, even if we may not enable PSR by default.
>>> We could also rewrite the debug message to look similar to the
>>> other
>>> compute_config functions
>> The debug message could be removed, or moved to intel_psr_enable.
> let's move enable debug messages to psr_enable_locked() and
> psr_disable_locked()
Yeah.
>>>>  
>>>>  static void intel_psr_activate(struct intel_dp *intel_dp)
>>>> @@ -589,6 +598,22 @@ static void intel_psr_enable_source(struct
>>>> intel_dp *intel_dp,
>>>>  	}
>>>>  }
>>>>  
>>>> +static void intel_psr_enable_locked(struct drm_i915_private
>>>> *dev_priv,
>>>> +				    const struct
>>>> intel_crtc_state
>>>> *crtc_state)
>>>> +{
>>>> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
>>>> +
>>>> +	if (dev_priv->psr.enabled)
>>>> +		return;
>>>> +
>>> This function gets called from intel_psr_set_debugfs_mode() Doesn't
>>> this allow debugfs to enable PSR even if mode related checks in
>>> psr_compute_config() had failed? For e.g., crtc_state->has_psr was
>>> false.
>> No, see intel_psr_enable. It only sets up state when crtc_state-
>>> has_psr is true. This is also why the check in
>> intel_psr_compute_config is moved.
>>>> +	intel_psr_setup_vsc(intel_dp, crtc_state);
>>>> +	intel_psr_enable_sink(intel_dp);
>>>> +	intel_psr_enable_source(intel_dp, crtc_state);
>>>> +	dev_priv->psr.enabled = true;
>>>> +
>>>> +	intel_psr_activate(intel_dp);
>>>> +}
>>>> +
>>>>  /**
>>>>   * intel_psr_enable - Enable PSR
>>>>   * @intel_dp: Intel DP
>>>> @@ -611,7 +636,7 @@ void intel_psr_enable(struct intel_dp
>>>> *intel_dp,
>>>>  
>>>>  	WARN_ON(dev_priv->drrs.dp);
>>>>  	mutex_lock(&dev_priv->psr.lock);
>>>> -	if (dev_priv->psr.enabled) {
>>>> +	if (dev_priv->psr.dp) {
>>> Check for dev_priv->psr.enabled instead?
>> This is handled in intel_psr_enable_locked().
>>
>> intel_psr_enable configures the state, but may not enable PSR right
>> away if disabled by modparam or debugfs.
>>>
>>>>  		DRM_DEBUG_KMS("PSR already in use\n");
>>>>  		goto unlock;
>>>>  	}
>>>> @@ -619,12 +644,10 @@ void intel_psr_enable(struct intel_dp
>>>> *intel_dp,
>>>>  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
>>>>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>>>>  
>>>> -	intel_psr_setup_vsc(intel_dp, crtc_state);
>>>> -	intel_psr_enable_sink(intel_dp);
>>>> -	intel_psr_enable_source(intel_dp, crtc_state);
>>>> -	dev_priv->psr.enabled = intel_dp;
>>>> +	dev_priv->psr.dp = intel_dp;
>>> Now that there is psr.enabled, should we always keep this pointer
>>> valid? 
>> No.
>>>>  
>>>> -	intel_psr_activate(intel_dp);
>>>> +	if (psr_global_enabled(dev_priv->psr.debugfs_mode))
>>> Okay, now I see why you have psr_global_enabled() as the last check
>>> in
>>> psr_compute_config().
>> :)
>>>> +		intel_psr_enable_locked(dev_priv, crtc_state);
>>>>  
>>>>  unlock:
>>>>  	mutex_unlock(&dev_priv->psr.lock);
>>>> @@ -688,7 +711,7 @@ static void intel_psr_disable_locked(struct
>>>> intel_dp *intel_dp)
>>>>  	/* Disable PSR on Sink */
>>>>  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
>>>>  
>>>> -	dev_priv->psr.enabled = NULL;
>>>> +	dev_priv->psr.enabled = false;
>>>>  }
>>>>  
>>>>  /**
>>>> @@ -712,7 +735,14 @@ void intel_psr_disable(struct intel_dp
>>>> *intel_dp,
>>>>  		return;
>>>>  
>>>>  	mutex_lock(&dev_priv->psr.lock);
>>>> +	if (intel_dp != dev_priv->psr.dp) {
>>>> +		mutex_unlock(&dev_priv->psr.lock);
>>>> +		return;
>>>> +	}
>>>> +
>>>>  	intel_psr_disable_locked(intel_dp);
>>>> +
>>>> +	dev_priv->psr.dp = NULL;
>>> Is there still a need to use this field as flag?
>> Yes.
>>>>  	mutex_lunlock(&dev_priv->psr.lock);
>>>>  	cancel_work_sync(&dev_priv->psr.work);
>>>>  }
>>>> @@ -756,13 +786,11 @@ int intel_psr_wait_for_idle(const struct
>>>> intel_crtc_state *new_crtc_state)
>>>>  
>>>>  static bool __psr_wait_for_idle_locked(struct drm_i915_private
>>>> *dev_priv)
>>>>  {
>>>> -	struct intel_dp *intel_dp;
>>>>  	i915_reg_t reg;
>>>>  	u32 mask;
>>>>  	int err;
>>>>  
>>>> -	intel_dp = dev_priv->psr.enabled;
>>>> -	if (!intel_dp)
>>>> +	if (!dev_priv->psr.enabled)
>>>>  		return false;
>>>>  
>>>>  	if (dev_priv->psr.psr2_enabled) {
>>>> @@ -784,6 +812,89 @@ static bool
>>>> __psr_wait_for_idle_locked(struct
>>>> drm_i915_private *dev_priv)
>>>>  	return err == 0 && dev_priv->psr.enabled;
>>>>  }
>>>>  
>>>> +static struct drm_crtc *
>>>> +find_idle_crtc_for_encoder(struct drm_encoder *encoder,
>>>> +			   struct drm_modeset_acquire_ctx *ctx)
>>>> +{
>>>> +	struct drm_connector_list_iter conn_iter;
>>>> +	struct drm_device *dev = encoder->dev;
>>>> +	struct drm_connector *connector;
>>>> +	struct drm_crtc *crtc;
>>>> +	bool found = false;
>>>> +	int ret;
>>>> +
>>>> +	drm_connector_list_iter_begin(dev, &conn_iter);
>>>> +	drm_for_each_connector_iter(connector, &conn_iter)
>>>> +		if (connector->state->best_encoder == encoder) {
>>>> +			found = true;
>>>> +			break;
>>>> +		}
>>>> +	drm_connector_list_iter_end(&conn_iter);
>>>> +
>>>> +	if (WARN_ON(!found))
>>>> +		return ERR_PTR(-EINVAL);
>>>> +
>>>> +	crtc = connector->state->crtc;
>>>> +	ret = drm_modeset_lock(&crtc->mutex, ctx);
>>>> +	if (ret)
>>>> +		return ERR_PTR(ret);
>>>> +
>>>> +	if (connector->state->commit)
>>>> +		ret =
>>>> wait_for_completion_interruptible(&connector-
>>>>> state->commit->hw_done);
>>>> +	if (!ret && crtc->state->commit)
>>>> +		ret = wait_for_completion_interruptible(&crtc-
>>>>> state->commit->hw_done);
>>>> +	if (ret)
>>>> +		return ERR_PTR(ret);
>>>> +
>>>> +	return crtc;
>>>> +}
>>>> +
>>>> +int intel_psr_set_debugfs_mode(struct drm_i915_private
>>>> *dev_priv,
>>>> +			       struct drm_modeset_acquire_ctx
>>>> *ctx,
>>>> +			       enum i915_psr_debugfs_mode mode)
>>>> +{
>>>> +	struct drm_device *dev = &dev_priv->drm;
>>>> +	struct drm_encoder *encoder;
>>>> +	struct drm_crtc *crtc;
>>>> +	int ret;
>>>> +	bool enable;
>>>> +
>>>> +	ret = drm_modeset_lock(&dev-
>>>>> mode_config.connection_mutex,
>>>> ctx);
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	enable = psr_global_enabled(mode);
>>>> +
>>>> +	mutex_lock(&dev_priv->psr.lock);
>>>> +
>>>> +	do {
>>>> +		if (!dev_priv->psr.dp) {
>>>> +			dev_priv->psr.debugfs_mode = mode;
>>>> +			goto end;
>>>> +		}
>>>> +		encoder = &dp_to_dig_port(dev_priv->psr.dp)-
>>>>> base.base;
>>>> +		mutex_unlock(&dev_priv->psr.lock);
>>>> +
>>>> +		crtc = find_idle_crtc_for_encoder(encoder, ctx);
>>>> +		if (IS_ERR(crtc))
>>>> +			return PTR_ERR(crtc);
>>>> +
>>>> +		mutex_lock(&dev_priv->psr.lock);
>>>> +	} while (dev_priv->psr.dp != enc_to_intel_dp(encoder));
>>> When will this not be true?
>> nonblocking modeset, for example.
> With psr.dp = intel_dp statically assigned in psr_init_dpcd(), can we
> get rid of this check? And the connector loop in
> find_idle_crtc_for_encoder() can just be intel_dp->attached_connector.
Should simplify things indeed.

~Maarten

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

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

* [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4.
  2018-07-28  5:23                 ` Dhinakaran Pandiyan
  2018-07-30  9:40                   ` Maarten Lankhorst
@ 2018-07-31 13:35                   ` Maarten Lankhorst
  2018-07-31 13:35                     ` [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode Maarten Lankhorst
                                       ` (2 more replies)
  1 sibling, 3 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-31 13:35 UTC (permalink / raw)
  To: intel-gfx; +Cc: Dhinakaran Pandiyan, Rodrigo Vivi

Currently tests modify i915.enable_psr and then do a modeset cycle
to change PSR. We can write a value to i915_edp_psr_debug to force
a certain PSR mode without a modeset.

To retain compatibility with older userspace, we also still allow
the override through the module parameter, and add some tracking
to check whether a debugfs mode is specified.

Changes since v1:
- Rename dev_priv->psr.enabled to .dp, and .hw_configured to .enabled.
- Fix i915_psr_debugfs_mode to match the writes to debugfs.
- Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
  it and move it to intel_psr.c. This keeps all internals in intel_psr.c
- Perform an interruptible wait for hw completion outside of the psr
  lock, instead of being forced to trywait and return -EBUSY.
Changes since v2:
- Rebase on top of intel_psr changes.
Changes since v3:
- Assign psr.dp during init. (dhnkrn)
- Add prepared bool, which should be used instead of relying on psr.dp. (dhnkrn)
- Fix -EDEADLK handling in debugfs. (dhnkrn)
- Clean up waiting for idle in intel_psr_set_debugfs_mode.
- Print PSR mode when trying to enable PSR. (dhnkrn)
- Move changing psr debug setting to i915_edp_psr_debug_set. (dhnkrn)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  21 ++++-
 drivers/gpu/drm/i915/i915_drv.h     |  12 ++-
 drivers/gpu/drm/i915/i915_irq.c     |   2 +-
 drivers/gpu/drm/i915/intel_drv.h    |   5 +-
 drivers/gpu/drm/i915/intel_psr.c    | 136 +++++++++++++++++++++++-----
 5 files changed, 144 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 59dc0610ea44..a7e927413e8e 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2705,7 +2705,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->psr.lock);
-	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
+	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
 	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
 		   dev_priv->psr.busy_frontbuffer_bits);
 
@@ -2747,14 +2747,29 @@ static int
 i915_edp_psr_debug_set(void *data, u64 val)
 {
 	struct drm_i915_private *dev_priv = data;
+	struct drm_modeset_acquire_ctx ctx;
+	int ret;
 
 	if (!CAN_PSR(dev_priv))
 		return -ENODEV;
 
-	DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val));
+	DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
 
 	intel_runtime_pm_get(dev_priv);
-	intel_psr_irq_control(dev_priv, !!val);
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+retry:
+	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
+	if (ret == -EDEADLK) {
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
 	intel_runtime_pm_put(dev_priv);
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0f49f9988dfa..ef04b6cd7863 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -611,8 +611,17 @@ struct i915_drrs {
 
 struct i915_psr {
 	struct mutex lock;
+
+#define I915_PSR_DEBUG_IRQ	BIT(0)
+#define I915_PSR_DEBUG_MODE_MASK (7 << 1)
+#define I915_PSR_DEBUG_DEFAULT	(0 << 1)
+#define I915_PSR_DEBUG_DISABLE	(1 << 1)
+#define I915_PSR_DEBUG_ENABLE	(2 << 1)
+
+	u32 debug;
 	bool sink_support;
-	struct intel_dp *enabled;
+	bool prepared, enabled;
+	struct intel_dp *dp;
 	bool active;
 	struct work_struct work;
 	unsigned busy_frontbuffer_bits;
@@ -622,7 +631,6 @@ struct i915_psr {
 	bool alpm;
 	bool psr2_enabled;
 	u8 sink_sync_latency;
-	bool debug;
 	ktime_t last_entry_attempt;
 	ktime_t last_exit;
 };
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5dadefca2ad2..defd696e71fc 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -4051,7 +4051,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 
 	if (IS_HASWELL(dev_priv)) {
 		gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR);
-		intel_psr_irq_control(dev_priv, dev_priv->psr.debug);
+		intel_psr_irq_control(dev_priv, dev_priv->psr.debug & I915_PSR_DEBUG_IRQ);
 		display_mask |= DE_EDP_PSR_INT_HSW;
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 99a5f5be5b82..f4cfb7ed2262 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1930,6 +1930,9 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *crtc_state);
 void intel_psr_disable(struct intel_dp *intel_dp,
 		      const struct intel_crtc_state *old_crtc_state);
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       u64 value);
 void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 			  unsigned frontbuffer_bits,
 			  enum fb_op_origin origin);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 4bd5768731ee..7848829094ca 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,18 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+static bool psr_global_enabled(u32 debug)
+{
+	switch (debug & I915_PSR_DEBUG_MODE_MASK) {
+	case I915_PSR_DEBUG_DEFAULT:
+		return i915_modparams.enable_psr;
+	case I915_PSR_DEBUG_DISABLE:
+		return false;
+	default:
+		return true;
+	}
+}
+
 void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug)
 {
 	u32 debug_mask, mask;
@@ -80,7 +92,6 @@ void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug)
 	if (debug)
 		mask |= debug_mask;
 
-	WRITE_ONCE(dev_priv->psr.debug, debug);
 	I915_WRITE(EDP_PSR_IMR, ~mask);
 }
 
@@ -212,6 +223,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 	dev_priv->psr.sink_support = true;
 	dev_priv->psr.sink_sync_latency =
 		intel_dp_get_sink_sync_latency(intel_dp);
+	dev_priv->psr.dp = intel_dp;
 
 	if (INTEL_GEN(dev_priv) >= 9 &&
 	    (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
@@ -471,11 +483,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 	if (!CAN_PSR(dev_priv))
 		return;
 
-	if (!i915_modparams.enable_psr) {
-		DRM_DEBUG_KMS("PSR disable by flag\n");
-		return;
-	}
-
 	/*
 	 * HSW spec explicitly says PSR is tied to port A.
 	 * BDW+ platforms with DDI implementation of PSR have different
@@ -517,7 +524,6 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
 	crtc_state->has_psr = true;
 	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
-	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
 }
 
 static void intel_psr_activate(struct intel_dp *intel_dp)
@@ -589,6 +595,23 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
 	}
 }
 
+static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
+				    const struct intel_crtc_state *crtc_state)
+{
+	struct intel_dp *intel_dp = dev_priv->psr.dp;
+
+	if (dev_priv->psr.enabled)
+		return;
+
+	DRM_DEBUG_KMS("Enabling PSR%s\n", dev_priv->psr.psr2_enabled ? "2" : "1");
+	intel_psr_setup_vsc(intel_dp, crtc_state);
+	intel_psr_enable_sink(intel_dp);
+	intel_psr_enable_source(intel_dp, crtc_state);
+	dev_priv->psr.enabled = true;
+
+	intel_psr_activate(intel_dp);
+}
+
 /**
  * intel_psr_enable - Enable PSR
  * @intel_dp: Intel DP
@@ -611,20 +634,20 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 
 	WARN_ON(dev_priv->drrs.dp);
 	mutex_lock(&dev_priv->psr.lock);
-	if (dev_priv->psr.enabled) {
+	if (dev_priv->psr.prepared) {
 		DRM_DEBUG_KMS("PSR already in use\n");
 		goto unlock;
 	}
 
 	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
 	dev_priv->psr.busy_frontbuffer_bits = 0;
+	dev_priv->psr.prepared = true;
+	dev_priv->psr.dp = intel_dp;
 
-	intel_psr_setup_vsc(intel_dp, crtc_state);
-	intel_psr_enable_sink(intel_dp);
-	intel_psr_enable_source(intel_dp, crtc_state);
-	dev_priv->psr.enabled = intel_dp;
-
-	intel_psr_activate(intel_dp);
+	if (psr_global_enabled(dev_priv->psr.debug))
+		intel_psr_enable_locked(dev_priv, crtc_state);
+	else
+		DRM_DEBUG_KMS("PSR disabled by flag\n");
 
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
@@ -683,12 +706,13 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
 	if (!dev_priv->psr.enabled)
 		return;
 
+	DRM_DEBUG_KMS("Disabling PSR\n");
 	intel_psr_disable_source(intel_dp);
 
 	/* Disable PSR on Sink */
 	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
 
-	dev_priv->psr.enabled = NULL;
+	dev_priv->psr.enabled = false;
 }
 
 /**
@@ -712,7 +736,14 @@ void intel_psr_disable(struct intel_dp *intel_dp,
 		return;
 
 	mutex_lock(&dev_priv->psr.lock);
+	if (intel_dp != dev_priv->psr.dp || !dev_priv->psr.prepared) {
+		mutex_unlock(&dev_priv->psr.lock);
+		return;
+	}
+
 	intel_psr_disable_locked(intel_dp);
+
+	dev_priv->psr.prepared = false;
 	mutex_unlock(&dev_priv->psr.lock);
 	cancel_work_sync(&dev_priv->psr.work);
 }
@@ -724,9 +755,6 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
 	i915_reg_t reg;
 	u32 mask;
 
-	if (!new_crtc_state->has_psr)
-		return 0;
-
 	/*
 	 * The sole user right now is intel_pipe_update_start(),
 	 * which won't race with psr_enable/disable, which is
@@ -737,6 +765,9 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
 	 * not needed and will induce latencies in the atomic
 	 * update path.
 	 */
+	if (!dev_priv->psr.enabled)
+		return 0;
+
 	if (dev_priv->psr.psr2_enabled) {
 		reg = EDP_PSR2_STATUS;
 		mask = EDP_PSR2_STATUS_STATE_MASK;
@@ -756,13 +787,11 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
 
 static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
 {
-	struct intel_dp *intel_dp;
 	i915_reg_t reg;
 	u32 mask;
 	int err;
 
-	intel_dp = dev_priv->psr.enabled;
-	if (!intel_dp)
+	if (!dev_priv->psr.enabled)
 		return false;
 
 	if (dev_priv->psr.psr2_enabled) {
@@ -784,6 +813,62 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
 	return err == 0 && dev_priv->psr.enabled;
 }
 
+int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
+			       struct drm_modeset_acquire_ctx *ctx,
+			       u64 val)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct drm_connector_state *conn_state;
+	struct drm_crtc *crtc;
+	struct intel_dp *dp;
+	int ret;
+	bool enable;
+
+	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK) ||
+	    (val & I915_PSR_DEBUG_MODE_MASK) > I915_PSR_DEBUG_ENABLE) {
+		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
+		return -EINVAL;
+	}
+
+	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+	if (ret)
+		return ret;
+
+	/* dev_priv->psr.dp should be set once and then never touched again. */
+	dp = READ_ONCE(dev_priv->psr.dp);
+	conn_state = dp->attached_connector->base.state;
+	crtc = conn_state->crtc;
+	if (crtc) {
+		ret = drm_modeset_lock(&crtc->mutex, ctx);
+		if (ret)
+			return ret;
+
+		ret = wait_for_completion_interruptible(&crtc->state->commit->hw_done);
+	} else
+		ret = wait_for_completion_interruptible(&conn_state->commit->hw_done);
+
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&dev_priv->psr.lock);
+	if (ret)
+		return ret;
+
+	enable = psr_global_enabled(val);
+
+	if (!enable)
+		intel_psr_disable_locked(dev_priv->psr.dp);
+
+	dev_priv->psr.debug = val;
+	intel_psr_irq_control(dev_priv, dev_priv->psr.debug & I915_PSR_DEBUG_IRQ);
+
+	if (dev_priv->psr.prepared && enable)
+		intel_psr_enable_locked(dev_priv, to_intel_crtc_state(crtc->state));
+
+	mutex_unlock(&dev_priv->psr.lock);
+	return ret;
+}
+
 static void intel_psr_work(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv =
@@ -811,7 +896,8 @@ static void intel_psr_work(struct work_struct *work)
 	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv->psr.active)
 		goto unlock;
 
-	intel_psr_activate(dev_priv->psr.enabled);
+	intel_psr_activate(dev_priv->psr.dp
+);
 unlock:
 	mutex_unlock(&dev_priv->psr.lock);
 }
@@ -866,7 +952,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -909,7 +995,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
 		return;
 	}
 
-	crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
 	pipe = to_intel_crtc(crtc)->pipe;
 
 	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
@@ -991,7 +1077,7 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp)
 
 	mutex_lock(&psr->lock);
 
-	if (psr->enabled != intel_dp)
+	if (!psr->enabled || psr->dp != intel_dp)
 		goto exit;
 
 	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) {
-- 
2.18.0

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

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

* [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode.
  2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
@ 2018-07-31 13:35                     ` Maarten Lankhorst
  2018-08-08  1:35                       ` Dhinakaran Pandiyan
  2018-08-01  9:41                     ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
  2018-08-08  0:07                     ` Dhinakaran Pandiyan
  2 siblings, 1 reply; 31+ messages in thread
From: Maarten Lankhorst @ 2018-07-31 13:35 UTC (permalink / raw)
  To: intel-gfx; +Cc: Dhinakaran Pandiyan

This will make it easier to test PSR1 on PSR2 capable eDP machines.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  2 ++
 drivers/gpu/drm/i915/intel_psr.c | 27 ++++++++++++++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ef04b6cd7863..07783b9e7960 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -617,6 +617,8 @@ struct i915_psr {
 #define I915_PSR_DEBUG_DEFAULT	(0 << 1)
 #define I915_PSR_DEBUG_DISABLE	(1 << 1)
 #define I915_PSR_DEBUG_ENABLE	(2 << 1)
+#define I915_PSR_DEBUG_FORCE_PSR1 (3 << 1)
+#define I915_PSR_DEBUG_FORCE_PSR2 (4 << 1)
 
 	u32 debug;
 	bool sink_support;
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 7848829094ca..4cf4ac7068d0 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -813,19 +813,38 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
 	return err == 0 && dev_priv->psr.enabled;
 }
 
+static bool switching_psr(struct drm_i915_private *dev_priv,
+			  struct intel_crtc_state *crtc_state,
+			  u32 mode)
+{
+	/* Can't switch psr state anyway if PSR2 is not supported. */
+	if (!crtc_state || !crtc_state->has_psr2)
+		return false;
+
+	if (dev_priv->psr.psr2_enabled && mode == I915_PSR_DEBUG_FORCE_PSR1)
+		return true;
+
+	if (!dev_priv->psr.psr2_enabled && mode != I915_PSR_DEBUG_FORCE_PSR1)
+		return true;
+
+	return false;
+}
+
 int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
 			       struct drm_modeset_acquire_ctx *ctx,
 			       u64 val)
 {
 	struct drm_device *dev = &dev_priv->drm;
 	struct drm_connector_state *conn_state;
+	struct intel_crtc_state *crtc_state = NULL;
 	struct drm_crtc *crtc;
 	struct intel_dp *dp;
 	int ret;
 	bool enable;
+	u32 mode = val & I915_PSR_DEBUG_MODE_MASK;
 
 	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK) ||
-	    (val & I915_PSR_DEBUG_MODE_MASK) > I915_PSR_DEBUG_ENABLE) {
+	    mode > I915_PSR_DEBUG_FORCE_PSR2) {
 		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
 		return -EINVAL;
 	}
@@ -843,7 +862,8 @@ int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
 		if (ret)
 			return ret;
 
-		ret = wait_for_completion_interruptible(&crtc->state->commit->hw_done);
+		crtc_state = to_intel_crtc_state(crtc->state);
+		ret = wait_for_completion_interruptible(&crtc_state->base.commit->hw_done);
 	} else
 		ret = wait_for_completion_interruptible(&conn_state->commit->hw_done);
 
@@ -856,10 +876,11 @@ int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
 
 	enable = psr_global_enabled(val);
 
-	if (!enable)
+	if (!enable || switching_psr(dev_priv, crtc_state, mode))
 		intel_psr_disable_locked(dev_priv->psr.dp);
 
 	dev_priv->psr.debug = val;
+	dev_priv->psr.psr2_enabled = mode != I915_PSR_DEBUG_FORCE_PSR1 && crtc_state->has_psr2;
 	intel_psr_irq_control(dev_priv, dev_priv->psr.debug & I915_PSR_DEBUG_IRQ);
 
 	if (dev_priv->psr.prepared && enable)
-- 
2.18.0

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

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

* Re: [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4.
  2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
  2018-07-31 13:35                     ` [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode Maarten Lankhorst
@ 2018-08-01  9:41                     ` Maarten Lankhorst
  2018-08-08  0:07                     ` Dhinakaran Pandiyan
  2 siblings, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-08-01  9:41 UTC (permalink / raw)
  To: intel-gfx; +Cc: Dhinakaran Pandiyan, Rodrigo Vivi

Op 31-07-18 om 15:35 schreef Maarten Lankhorst:
> Currently tests modify i915.enable_psr and then do a modeset cycle
> to change PSR. We can write a value to i915_edp_psr_debug to force
> a certain PSR mode without a modeset.
>
> To retain compatibility with older userspace, we also still allow
> the override through the module parameter, and add some tracking
> to check whether a debugfs mode is specified.
>
> Changes since v1:
> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to .enabled.
> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>   it and move it to intel_psr.c. This keeps all internals in intel_psr.c
> - Perform an interruptible wait for hw completion outside of the psr
>   lock, instead of being forced to trywait and return -EBUSY.
> Changes since v2:
> - Rebase on top of intel_psr changes.
> Changes since v3:
> - Assign psr.dp during init. (dhnkrn)
> - Add prepared bool, which should be used instead of relying on psr.dp. (dhnkrn)
> - Fix -EDEADLK handling in debugfs. (dhnkrn)
> - Clean up waiting for idle in intel_psr_set_debugfs_mode.
> - Print PSR mode when trying to enable PSR. (dhnkrn)
> - Move changing psr debug setting to i915_edp_psr_debug_set. (dhnkrn)
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |  21 ++++-
>  drivers/gpu/drm/i915/i915_drv.h     |  12 ++-
>  drivers/gpu/drm/i915/i915_irq.c     |   2 +-
>  drivers/gpu/drm/i915/intel_drv.h    |   5 +-
>  drivers/gpu/drm/i915/intel_psr.c    | 136 +++++++++++++++++++++++-----
>  5 files changed, 144 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 59dc0610ea44..a7e927413e8e 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2705,7 +2705,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  	intel_runtime_pm_get(dev_priv);
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>  		   dev_priv->psr.busy_frontbuffer_bits);
>  
> @@ -2747,14 +2747,29 @@ static int
>  i915_edp_psr_debug_set(void *data, u64 val)
>  {
>  	struct drm_i915_private *dev_priv = data;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret;
>  
>  	if (!CAN_PSR(dev_priv))
>  		return -ENODEV;
>  
> -	DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val));
> +	DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
>  
>  	intel_runtime_pm_get(dev_priv);
> -	intel_psr_irq_control(dev_priv, !!val);
> +
> +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +retry:
> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
> +	if (ret == -EDEADLK) {
> +		ret = drm_modeset_backoff(&ctx);
> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
>  	intel_runtime_pm_put(dev_priv);
>  
>  	return 0;
^Oops, needs to be changed to return ret;

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

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

* Re: [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4.
  2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
  2018-07-31 13:35                     ` [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode Maarten Lankhorst
  2018-08-01  9:41                     ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
@ 2018-08-08  0:07                     ` Dhinakaran Pandiyan
  2018-08-08  9:00                       ` Maarten Lankhorst
  2 siblings, 1 reply; 31+ messages in thread
From: Dhinakaran Pandiyan @ 2018-08-08  0:07 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx; +Cc: Rodrigo Vivi

On Tue, 2018-07-31 at 15:35 +0200, Maarten Lankhorst wrote:
> Currently tests modify i915.enable_psr and then do a modeset cycle
> to change PSR. We can write a value to i915_edp_psr_debug to force
> a certain PSR mode without a modeset.
> 
> To retain compatibility with older userspace, we also still allow
> the override through the module parameter, and add some tracking
> to check whether a debugfs mode is specified.
> 
> Changes since v1:
> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
> .enabled.
> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>   it and move it to intel_psr.c. This keeps all internals in
> intel_psr.c
> - Perform an interruptible wait for hw completion outside of the psr
>   lock, instead of being forced to trywait and return -EBUSY.
> Changes since v2:
> - Rebase on top of intel_psr changes.
> Changes since v3:
> - Assign psr.dp during init. (dhnkrn)
> - Add prepared bool, which should be used instead of relying on
> psr.dp. (dhnkrn)
> - Fix -EDEADLK handling in debugfs. (dhnkrn)
> - Clean up waiting for idle in intel_psr_set_debugfs_mode.
> - Print PSR mode when trying to enable PSR. (dhnkrn)
> - Move changing psr debug setting to i915_edp_psr_debug_set. (dhnkrn)
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |  21 ++++-
>  drivers/gpu/drm/i915/i915_drv.h     |  12 ++-
>  drivers/gpu/drm/i915/i915_irq.c     |   2 +-
>  drivers/gpu/drm/i915/intel_drv.h    |   5 +-
>  drivers/gpu/drm/i915/intel_psr.c    | 136 +++++++++++++++++++++++---
> --
>  5 files changed, 144 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 59dc0610ea44..a7e927413e8e 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2705,7 +2705,7 @@ static int i915_edp_psr_status(struct seq_file
> *m, void *data)
>  	intel_runtime_pm_get(dev_priv);
>  
>  	mutex_lock(&dev_priv->psr.lock);
> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
> >psr.enabled));
> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
> >psr.enabled));
>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>  		   dev_priv->psr.busy_frontbuffer_bits);
>  
> @@ -2747,14 +2747,29 @@ static int
>  i915_edp_psr_debug_set(void *data, u64 val)
>  {
>  	struct drm_i915_private *dev_priv = data;
> +	struct drm_modeset_acquire_ctx ctx;
> +	int ret;
>  
>  	if (!CAN_PSR(dev_priv))
>  		return -ENODEV;
>  
> -	DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val));
> +	DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
>  
>  	intel_runtime_pm_get(dev_priv);
> -	intel_psr_irq_control(dev_priv, !!val);
> +
> +	drm_modeset_acquire_init(&ctx,
> DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +retry:
> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
> +	if (ret == -EDEADLK) {
> +		ret = drm_modeset_backoff(&ctx);
Is there any reason not backoff where modeset_lock() is called, i.e.,
inside set_debugfs_mode()?

> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_modeset_drop_locks(&ctx);
Same with this?

> +	drm_modeset_acquire_fini(&ctx);
> +
>  	intel_runtime_pm_put(dev_priv);
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h
> index 0f49f9988dfa..ef04b6cd7863 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -611,8 +611,17 @@ struct i915_drrs {
>  
>  struct i915_psr {
>  	struct mutex lock;
> +
> +#define I915_PSR_DEBUG_IRQ	BIT(0)
nit: looks a bit odd to use the BIT macro only for the first bit. Is
this the new guideline for single bit definitions?

> +#define I915_PSR_DEBUG_MODE_MASK (7 << 1)
> +#define I915_PSR_DEBUG_DEFAULT	(0 << 1)
> +#define I915_PSR_DEBUG_DISABLE	(1 << 1)
> +#define I915_PSR_DEBUG_ENABLE	(2 << 1)

Can we also please define the enable/disable bits from 0 and move the
debug one towards MSB? The enable/disable bits will be the most
commonly used ones and it'd be easy to remember if there was no shift?
I'm fine if you don't want to change too.

> +
> +	u32 debug;
>  	bool sink_support;
> -	struct intel_dp *enabled;
> +	bool prepared, enabled;
> +	struct intel_dp *dp;
>  	bool active;
>  	struct work_struct work;
>  	unsigned busy_frontbuffer_bits;
> @@ -622,7 +631,6 @@ struct i915_psr {
>  	bool alpm;
>  	bool psr2_enabled;
>  	u8 sink_sync_latency;
> -	bool debug;
>  	ktime_t last_entry_attempt;
>  	ktime_t last_exit;
>  };
> diff --git a/drivers/gpu/drm/i915/i915_irq.c
> b/drivers/gpu/drm/i915/i915_irq.c
> index 5dadefca2ad2..defd696e71fc 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -4051,7 +4051,7 @@ static int ironlake_irq_postinstall(struct
> drm_device *dev)
>  
>  	if (IS_HASWELL(dev_priv)) {
>  		gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR);
> -		intel_psr_irq_control(dev_priv, dev_priv-
> >psr.debug);
> +		intel_psr_irq_control(dev_priv, dev_priv->psr.debug
> & I915_PSR_DEBUG_IRQ);
>  		display_mask |= DE_EDP_PSR_INT_HSW;
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 99a5f5be5b82..f4cfb7ed2262 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1930,6 +1930,9 @@ void intel_psr_enable(struct intel_dp
> *intel_dp,
>  		      const struct intel_crtc_state *crtc_state);
>  void intel_psr_disable(struct intel_dp *intel_dp,
>  		      const struct intel_crtc_state
> *old_crtc_state);
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       u64 value);
>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  			  unsigned frontbuffer_bits,
>  			  enum fb_op_origin origin);
> diff --git a/drivers/gpu/drm/i915/intel_psr.c
> b/drivers/gpu/drm/i915/intel_psr.c
> index 4bd5768731ee..7848829094ca 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -56,6 +56,18 @@
>  #include "intel_drv.h"
>  #include "i915_drv.h"
>  
> +static bool psr_global_enabled(u32 debug)
> +{
> +	switch (debug & I915_PSR_DEBUG_MODE_MASK) {
> +	case I915_PSR_DEBUG_DEFAULT:
> +		return i915_modparams.enable_psr;
> +	case I915_PSR_DEBUG_DISABLE:
> +		return false;
> +	default:
> +		return true;
> +	}
> +}
> +
>  void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool
> debug)
>  {
>  	u32 debug_mask, mask;
> @@ -80,7 +92,6 @@ void intel_psr_irq_control(struct drm_i915_private
> *dev_priv, bool debug)
>  	if (debug)
>  		mask |= debug_mask;
>  
> -	WRITE_ONCE(dev_priv->psr.debug, debug);
>  	I915_WRITE(EDP_PSR_IMR, ~mask);
>  }
>  
> @@ -212,6 +223,7 @@ void intel_psr_init_dpcd(struct intel_dp
> *intel_dp)
>  	dev_priv->psr.sink_support = true;
>  	dev_priv->psr.sink_sync_latency =
>  		intel_dp_get_sink_sync_latency(intel_dp);
> +	dev_priv->psr.dp = intel_dp;
>  
>  	if (INTEL_GEN(dev_priv) >= 9 &&
>  	    (intel_dp->psr_dpcd[0] ==
> DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
> @@ -471,11 +483,6 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>  	if (!CAN_PSR(dev_priv))
>  		return;
>  
> -	if (!i915_modparams.enable_psr) {
> -		DRM_DEBUG_KMS("PSR disable by flag\n");
> -		return;
> -	}
> -
>  	/*
>  	 * HSW spec explicitly says PSR is tied to port A.
>  	 * BDW+ platforms with DDI implementation of PSR have
> different
> @@ -517,7 +524,6 @@ void intel_psr_compute_config(struct intel_dp
> *intel_dp,
>  
>  	crtc_state->has_psr = true;
>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
> crtc_state);
> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2"
> : "");
>  }
>  
>  static void intel_psr_activate(struct intel_dp *intel_dp)
> @@ -589,6 +595,23 @@ static void intel_psr_enable_source(struct
> intel_dp *intel_dp,
>  	}
>  }
>  
> +static void intel_psr_enable_locked(struct drm_i915_private
> *dev_priv,
> +				    const struct intel_crtc_state
> *crtc_state)
> +{
> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
> +
> +	if (dev_priv->psr.enabled)
> +		return;
> +
> +	DRM_DEBUG_KMS("Enabling PSR%s\n", dev_priv->psr.psr2_enabled 
> ? "2" : "1");
> +	intel_psr_setup_vsc(intel_dp, crtc_state);
> +	intel_psr_enable_sink(intel_dp);
> +	intel_psr_enable_source(intel_dp, crtc_state);
> +	dev_priv->psr.enabled = true;
> +
> +	intel_psr_activate(intel_dp);
> +}
> +
>  /**
>   * intel_psr_enable - Enable PSR
>   * @intel_dp: Intel DP
> @@ -611,20 +634,20 @@ void intel_psr_enable(struct intel_dp
> *intel_dp,
>  
>  	WARN_ON(dev_priv->drrs.dp);
We could add a new line here?

>  	mutex_lock(&dev_priv->psr.lock);
> -	if (dev_priv->psr.enabled) {
> +	if (dev_priv->psr.prepared) {
>  		DRM_DEBUG_KMS("PSR already in use\n");
>  		goto unlock;
>  	}
>  
>  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
>  	dev_priv->psr.busy_frontbuffer_bits = 0;
> +	dev_priv->psr.prepared = true;
> +	dev_priv->psr.dp = intel_dp;
.dp is already set in init_dpcd()

>  
> -	intel_psr_setup_vsc(intel_dp, crtc_state);
> -	intel_psr_enable_sink(intel_dp);
> -	intel_psr_enable_source(intel_dp, crtc_state);
> -	dev_priv->psr.enabled = intel_dp;
> -
> -	intel_psr_activate(intel_dp);
> +	if (psr_global_enabled(dev_priv->psr.debug))
> +		intel_psr_enable_locked(dev_priv, crtc_state);
> +	else
> +		DRM_DEBUG_KMS("PSR disabled by flag\n");
>  
>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
> @@ -683,12 +706,13 @@ static void intel_psr_disable_locked(struct
> intel_dp *intel_dp)
>  	if (!dev_priv->psr.enabled)
>  		return;
>  
> +	DRM_DEBUG_KMS("Disabling PSR\n");
Print PSR1/2 too? Like you've done in the enable counter part.

>  	intel_psr_disable_source(intel_dp);
>  
>  	/* Disable PSR on Sink */
>  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
>  
> -	dev_priv->psr.enabled = NULL;
> +	dev_priv->psr.enabled = false;
>  }
>  
>  /**
> @@ -712,7 +736,14 @@ void intel_psr_disable(struct intel_dp
> *intel_dp,
>  		return;
>  
>  	mutex_lock(&dev_priv->psr.lock);
> +	if (intel_dp != dev_priv->psr.dp || !dev_priv->psr.prepared)
Won't intel_dp == dev_priv->psr.dp if old_crtc_state->has_psr was true?

>  {
> +		mutex_unlock(&dev_priv->psr.lock);
> +		return;
> +	}
> +
>  	intel_psr_disable_locked(intel_dp);
> +
> +	dev_priv->psr.prepared = false;
>  	mutex_unlock(&dev_priv->psr.lock);
>  	cancel_work_sync(&dev_priv->psr.work);
>  }
> @@ -724,9 +755,6 @@ int intel_psr_wait_for_idle(const struct
> intel_crtc_state *new_crtc_state)
>  	i915_reg_t reg;
>  	u32 mask;
>  
> -	if (!new_crtc_state->has_psr)
> -		return 0;
> -
>  	/*
>  	 * The sole user right now is intel_pipe_update_start(),
>  	 * which won't race with psr_enable/disable, which is
> @@ -737,6 +765,9 @@ int intel_psr_wait_for_idle(const struct
> intel_crtc_state *new_crtc_state)
>  	 * not needed and will induce latencies in the atomic
>  	 * update path.
>  	 */
> +	if (!dev_priv->psr.enabled)
> +		return 0;
> +
>  	if (dev_priv->psr.psr2_enabled) {
>  		reg = EDP_PSR2_STATUS;
>  		mask = EDP_PSR2_STATUS_STATE_MASK;
> @@ -756,13 +787,11 @@ int intel_psr_wait_for_idle(const struct
> intel_crtc_state *new_crtc_state)
>  
>  static bool __psr_wait_for_idle_locked(struct drm_i915_private
> *dev_priv)
>  {
> -	struct intel_dp *intel_dp;
>  	i915_reg_t reg;
>  	u32 mask;
>  	int err;
>  
> -	intel_dp = dev_priv->psr.enabled;
> -	if (!intel_dp)
> +	if (!dev_priv->psr.enabled)
>  		return false;
>  
>  	if (dev_priv->psr.psr2_enabled) {
> @@ -784,6 +813,62 @@ static bool __psr_wait_for_idle_locked(struct
> drm_i915_private *dev_priv)
>  	return err == 0 && dev_priv->psr.enabled;
>  }
>  
> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_modeset_acquire_ctx *ctx,
> +			       u64 val)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct drm_connector_state *conn_state;
> +	struct drm_crtc *crtc;
> +	struct intel_dp *dp;
> +	int ret;
> +	bool enable;
> +
> +	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK)
> ||
> +	    (val & I915_PSR_DEBUG_MODE_MASK) >
> I915_PSR_DEBUG_ENABLE) {
> +		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
> +		return -EINVAL;
> +	}
> +
> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
> ctx);
> +	if (ret)
> +		return ret;
> +
> +	/* dev_priv->psr.dp should be set once and then never
> touched again. */
> +	dp = READ_ONCE(dev_priv->psr.dp);
> +	conn_state = dp->attached_connector->base.state;
> +	crtc = conn_state->crtc;
> +	if (crtc) {
> +		ret = drm_modeset_lock(&crtc->mutex, ctx);
> +		if (ret)
> +			return ret;
> +
> +		ret = wait_for_completion_interruptible(&crtc-
> >state->commit->hw_done);
> +	} else
> +		ret = wait_for_completion_interruptible(&conn_state-
> >commit->hw_done);
Shouldn't this wait on connection state be done even if a crtc was
present?

> +
> +	if (ret)
> +		return ret;
> +
> +	ret = mutex_lock_interruptible(&dev_priv->psr.lock);
> +	if (ret)
> +		return ret;
> +
> +	enable = psr_global_enabled(val);
> +
> +	if (!enable)
> +		intel_psr_disable_locked(dev_priv->psr.dp);
> +
> +	dev_priv->psr.debug = val;
> +	intel_psr_irq_control(dev_priv, dev_priv->psr.debug &
> I915_PSR_DEBUG_IRQ);
> +
> +	if (dev_priv->psr.prepared && enable)
> +		intel_psr_enable_locked(dev_priv,
> to_intel_crtc_state(crtc->state));
> +
> +	mutex_unlock(&dev_priv->psr.lock);
> +	return ret;
> +}
> +
>  static void intel_psr_work(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -811,7 +896,8 @@ static void intel_psr_work(struct work_struct
> *work)
>  	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv-
> >psr.active)
>  		goto unlock;
>  
> -	intel_psr_activate(dev_priv->psr.enabled);
> +	intel_psr_activate(dev_priv->psr.dp
> +);
^typo

>  unlock:
>  	mutex_unlock(&dev_priv->psr.lock);
>  }
> @@ -866,7 +952,7 @@ void intel_psr_invalidate(struct drm_i915_private
> *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> >base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -909,7 +995,7 @@ void intel_psr_flush(struct drm_i915_private
> *dev_priv,
>  		return;
>  	}
>  
> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
> >base.base.crtc;
> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>  	pipe = to_intel_crtc(crtc)->pipe;
>  
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> @@ -991,7 +1077,7 @@ void intel_psr_short_pulse(struct intel_dp
> *intel_dp)
>  
>  	mutex_lock(&psr->lock);
>  
> -	if (psr->enabled != intel_dp)
> +	if (!psr->enabled || psr->dp != intel_dp)
>  		goto exit;
>  
>  	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val)
> != 1) {
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode.
  2018-07-31 13:35                     ` [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode Maarten Lankhorst
@ 2018-08-08  1:35                       ` Dhinakaran Pandiyan
  2018-08-08  9:01                         ` Maarten Lankhorst
  0 siblings, 1 reply; 31+ messages in thread
From: Dhinakaran Pandiyan @ 2018-08-08  1:35 UTC (permalink / raw)
  To: Maarten Lankhorst, intel-gfx; +Cc: Rodrigo Vivi

On Tue, 2018-07-31 at 15:35 +0200, Maarten Lankhorst wrote:
> This will make it easier to test PSR1 on PSR2 capable eDP machines.
Thanks for writing this patch, we can make use of this to fix failures
on PSR2 machines in CI.

> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h  |  2 ++
>  drivers/gpu/drm/i915/intel_psr.c | 27 ++++++++++++++++++++++++---
>  2 files changed, 26 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h
> index ef04b6cd7863..07783b9e7960 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -617,6 +617,8 @@ struct i915_psr {
>  #define I915_PSR_DEBUG_DEFAULT	(0 << 1)
>  #define I915_PSR_DEBUG_DISABLE	(1 << 1)
>  #define I915_PSR_DEBUG_ENABLE	(2 << 1)
> +#define I915_PSR_DEBUG_FORCE_PSR1 (3 << 1)
> +#define I915_PSR_DEBUG_FORCE_PSR2 (4 << 1)
>  
>  	u32 debug;
>  	bool sink_support;
> diff --git a/drivers/gpu/drm/i915/intel_psr.c
> b/drivers/gpu/drm/i915/intel_psr.c
> index 7848829094ca..4cf4ac7068d0 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -813,19 +813,38 @@ static bool __psr_wait_for_idle_locked(struct
> drm_i915_private *dev_priv)
>  	return err == 0 && dev_priv->psr.enabled;
>  }
>  
> +static bool switching_psr(struct drm_i915_private *dev_priv,
> +			  struct intel_crtc_state *crtc_state,
> +			  u32 mode)
> +{
> +	/* Can't switch psr state anyway if PSR2 is not supported.
> */
> +	if (!crtc_state || !crtc_state->has_psr2)
> +		return false;
> +
> +	if (dev_priv->psr.psr2_enabled && mode ==
> I915_PSR_DEBUG_FORCE_PSR1)
> +		return true;
> +
> +	if (!dev_priv->psr.psr2_enabled && mode !=
> I915_PSR_DEBUG_FORCE_PSR1)
> +		return true;
> +
> +	return false;
> +}
> +
>  int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>  			       struct drm_modeset_acquire_ctx *ctx,
>  			       u64 val)
>  {
>  	struct drm_device *dev = &dev_priv->drm;
>  	struct drm_connector_state *conn_state;
> +	struct intel_crtc_state *crtc_state = NULL;
>  	struct drm_crtc *crtc;
>  	struct intel_dp *dp;
>  	int ret;
>  	bool enable;
> +	u32 mode = val & I915_PSR_DEBUG_MODE_MASK;
>  
>  	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK)
> ||
> -	    (val & I915_PSR_DEBUG_MODE_MASK) >
> I915_PSR_DEBUG_ENABLE) {
> +	    mode > I915_PSR_DEBUG_FORCE_PSR2) {
>  		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
>  		return -EINVAL;
>  	}
> @@ -843,7 +862,8 @@ int intel_psr_set_debugfs_mode(struct
> drm_i915_private *dev_priv,
>  		if (ret)
>  			return ret;
>  
> -		ret = wait_for_completion_interruptible(&crtc-
> >state->commit->hw_done);
> +		crtc_state = to_intel_crtc_state(crtc->state);
> +		ret = wait_for_completion_interruptible(&crtc_state-
> >base.commit->hw_done);
>  	} else
>  		ret = wait_for_completion_interruptible(&conn_state-
> >commit->hw_done);
>  
> @@ -856,10 +876,11 @@ int intel_psr_set_debugfs_mode(struct
> drm_i915_private *dev_priv,
>  
>  	enable = psr_global_enabled(val);
>  
> -	if (!enable)
> +	if (!enable || switching_psr(dev_priv, crtc_state, mode))
>  		intel_psr_disable_locked(dev_priv->psr.dp);
>  
>  	dev_priv->psr.debug = val;
> +	dev_priv->psr.psr2_enabled = mode !=
> I915_PSR_DEBUG_FORCE_PSR1 && crtc_state->has_psr2;
crtc_state can be NULL.

>  	intel_psr_irq_control(dev_priv, dev_priv->psr.debug &
> I915_PSR_DEBUG_IRQ);
>  
>  	if (dev_priv->psr.prepared && enable)


If a modeset was done after writing I915_PSR_DEBUG_FORCE_PSR1, we'll
still end up enabling PSR2. Check for debug flags in intel_psr_enable()
?

-DK

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

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

* Re: [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4.
  2018-08-08  0:07                     ` Dhinakaran Pandiyan
@ 2018-08-08  9:00                       ` Maarten Lankhorst
  0 siblings, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-08-08  9:00 UTC (permalink / raw)
  To: dhinakaran.pandiyan, intel-gfx; +Cc: Rodrigo Vivi

Op 08-08-18 om 02:07 schreef Dhinakaran Pandiyan:
> On Tue, 2018-07-31 at 15:35 +0200, Maarten Lankhorst wrote:
>> Currently tests modify i915.enable_psr and then do a modeset cycle
>> to change PSR. We can write a value to i915_edp_psr_debug to force
>> a certain PSR mode without a modeset.
>>
>> To retain compatibility with older userspace, we also still allow
>> the override through the module parameter, and add some tracking
>> to check whether a debugfs mode is specified.
>>
>> Changes since v1:
>> - Rename dev_priv->psr.enabled to .dp, and .hw_configured to
>> .enabled.
>> - Fix i915_psr_debugfs_mode to match the writes to debugfs.
>> - Rename __i915_edp_psr_write to intel_psr_set_debugfs_mode, simplify
>>   it and move it to intel_psr.c. This keeps all internals in
>> intel_psr.c
>> - Perform an interruptible wait for hw completion outside of the psr
>>   lock, instead of being forced to trywait and return -EBUSY.
>> Changes since v2:
>> - Rebase on top of intel_psr changes.
>> Changes since v3:
>> - Assign psr.dp during init. (dhnkrn)
>> - Add prepared bool, which should be used instead of relying on
>> psr.dp. (dhnkrn)
>> - Fix -EDEADLK handling in debugfs. (dhnkrn)
>> - Clean up waiting for idle in intel_psr_set_debugfs_mode.
>> - Print PSR mode when trying to enable PSR. (dhnkrn)
>> - Move changing psr debug setting to i915_edp_psr_debug_set. (dhnkrn)
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
>> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c |  21 ++++-
>>  drivers/gpu/drm/i915/i915_drv.h     |  12 ++-
>>  drivers/gpu/drm/i915/i915_irq.c     |   2 +-
>>  drivers/gpu/drm/i915/intel_drv.h    |   5 +-
>>  drivers/gpu/drm/i915/intel_psr.c    | 136 +++++++++++++++++++++++---
>> --
>>  5 files changed, 144 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
>> b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 59dc0610ea44..a7e927413e8e 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -2705,7 +2705,7 @@ static int i915_edp_psr_status(struct seq_file
>> *m, void *data)
>>  	intel_runtime_pm_get(dev_priv);
>>  
>>  	mutex_lock(&dev_priv->psr.lock);
>> -	seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv-
>>> psr.enabled));
>> +	seq_printf(m, "Enabled: %s\n", yesno(dev_priv-
>>> psr.enabled));
>>  	seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
>>  		   dev_priv->psr.busy_frontbuffer_bits);
>>  
>> @@ -2747,14 +2747,29 @@ static int
>>  i915_edp_psr_debug_set(void *data, u64 val)
>>  {
>>  	struct drm_i915_private *dev_priv = data;
>> +	struct drm_modeset_acquire_ctx ctx;
>> +	int ret;
>>  
>>  	if (!CAN_PSR(dev_priv))
>>  		return -ENODEV;
>>  
>> -	DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val));
>> +	DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
>>  
>>  	intel_runtime_pm_get(dev_priv);
>> -	intel_psr_irq_control(dev_priv, !!val);
>> +
>> +	drm_modeset_acquire_init(&ctx,
>> DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
>> +
>> +retry:
>> +	ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
>> +	if (ret == -EDEADLK) {
>> +		ret = drm_modeset_backoff(&ctx);
> Is there any reason not backoff where modeset_lock() is called, i.e.,
> inside set_debugfs_mode()?
Readability, same reason why runtime_pm_put is also kept in i915_edp_psr_debug_set.

The actual debugfs set function shouldn't have to worry about it, same as we do in atomic commits.
>> +		if (!ret)
>> +			goto retry;
>> +	}
>> +
>> +	drm_modeset_drop_locks(&ctx);
> Same with this?
>
>> +	drm_modeset_acquire_fini(&ctx);
>> +
>>  	intel_runtime_pm_put(dev_priv);
>>  
>>  	return 0;
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h
>> b/drivers/gpu/drm/i915/i915_drv.h
>> index 0f49f9988dfa..ef04b6cd7863 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -611,8 +611,17 @@ struct i915_drrs {
>>  
>>  struct i915_psr {
>>  	struct mutex lock;
>> +
>> +#define I915_PSR_DEBUG_IRQ	BIT(0)
> nit: looks a bit odd to use the BIT macro only for the first bit. Is
> this the new guideline for single bit definitions?
I tried to preserve the old behavior, so echo 1 > debug would still enable irq debugging.

I'm all for breaking this if it makes your life easier. :)
>
>> +#define I915_PSR_DEBUG_MODE_MASK (7 << 1)
>> +#define I915_PSR_DEBUG_DEFAULT	(0 << 1)
>> +#define I915_PSR_DEBUG_DISABLE	(1 << 1)
>> +#define I915_PSR_DEBUG_ENABLE	(2 << 1)
> Can we also please define the enable/disable bits from 0 and move the
> debug one towards MSB? The enable/disable bits will be the most
> commonly used ones and it'd be easy to remember if there was no shift?
> I'm fine if you don't want to change too.
Yeah that's fine.
>> +
>> +	u32 debug;
>>  	bool sink_support;
>> -	struct intel_dp *enabled;
>> +	bool prepared, enabled;
>> +	struct intel_dp *dp;
>>  	bool active;
>>  	struct work_struct work;
>>  	unsigned busy_frontbuffer_bits;
>> @@ -622,7 +631,6 @@ struct i915_psr {
>>  	bool alpm;
>>  	bool psr2_enabled;
>>  	u8 sink_sync_latency;
>> -	bool debug;
>>  	ktime_t last_entry_attempt;
>>  	ktime_t last_exit;
>>  };
>> diff --git a/drivers/gpu/drm/i915/i915_irq.c
>> b/drivers/gpu/drm/i915/i915_irq.c
>> index 5dadefca2ad2..defd696e71fc 100644
>> --- a/drivers/gpu/drm/i915/i915_irq.c
>> +++ b/drivers/gpu/drm/i915/i915_irq.c
>> @@ -4051,7 +4051,7 @@ static int ironlake_irq_postinstall(struct
>> drm_device *dev)
>>  
>>  	if (IS_HASWELL(dev_priv)) {
>>  		gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR);
>> -		intel_psr_irq_control(dev_priv, dev_priv-
>>> psr.debug);
>> +		intel_psr_irq_control(dev_priv, dev_priv->psr.debug
>> & I915_PSR_DEBUG_IRQ);
>>  		display_mask |= DE_EDP_PSR_INT_HSW;
>>  	}
>>  
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>> b/drivers/gpu/drm/i915/intel_drv.h
>> index 99a5f5be5b82..f4cfb7ed2262 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1930,6 +1930,9 @@ void intel_psr_enable(struct intel_dp
>> *intel_dp,
>>  		      const struct intel_crtc_state *crtc_state);
>>  void intel_psr_disable(struct intel_dp *intel_dp,
>>  		      const struct intel_crtc_state
>> *old_crtc_state);
>> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>> +			       struct drm_modeset_acquire_ctx *ctx,
>> +			       u64 value);
>>  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>>  			  unsigned frontbuffer_bits,
>>  			  enum fb_op_origin origin);
>> diff --git a/drivers/gpu/drm/i915/intel_psr.c
>> b/drivers/gpu/drm/i915/intel_psr.c
>> index 4bd5768731ee..7848829094ca 100644
>> --- a/drivers/gpu/drm/i915/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/intel_psr.c
>> @@ -56,6 +56,18 @@
>>  #include "intel_drv.h"
>>  #include "i915_drv.h"
>>  
>> +static bool psr_global_enabled(u32 debug)
>> +{
>> +	switch (debug & I915_PSR_DEBUG_MODE_MASK) {
>> +	case I915_PSR_DEBUG_DEFAULT:
>> +		return i915_modparams.enable_psr;
>> +	case I915_PSR_DEBUG_DISABLE:
>> +		return false;
>> +	default:
>> +		return true;
>> +	}
>> +}
>> +
>>  void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool
>> debug)
>>  {
>>  	u32 debug_mask, mask;
>> @@ -80,7 +92,6 @@ void intel_psr_irq_control(struct drm_i915_private
>> *dev_priv, bool debug)
>>  	if (debug)
>>  		mask |= debug_mask;
>>  
>> -	WRITE_ONCE(dev_priv->psr.debug, debug);
>>  	I915_WRITE(EDP_PSR_IMR, ~mask);
>>  }
>>  
>> @@ -212,6 +223,7 @@ void intel_psr_init_dpcd(struct intel_dp
>> *intel_dp)
>>  	dev_priv->psr.sink_support = true;
>>  	dev_priv->psr.sink_sync_latency =
>>  		intel_dp_get_sink_sync_latency(intel_dp);
>> +	dev_priv->psr.dp = intel_dp;
>>  
>>  	if (INTEL_GEN(dev_priv) >= 9 &&
>>  	    (intel_dp->psr_dpcd[0] ==
>> DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
>> @@ -471,11 +483,6 @@ void intel_psr_compute_config(struct intel_dp
>> *intel_dp,
>>  	if (!CAN_PSR(dev_priv))
>>  		return;
>>  
>> -	if (!i915_modparams.enable_psr) {
>> -		DRM_DEBUG_KMS("PSR disable by flag\n");
>> -		return;
>> -	}
>> -
>>  	/*
>>  	 * HSW spec explicitly says PSR is tied to port A.
>>  	 * BDW+ platforms with DDI implementation of PSR have
>> different
>> @@ -517,7 +524,6 @@ void intel_psr_compute_config(struct intel_dp
>> *intel_dp,
>>  
>>  	crtc_state->has_psr = true;
>>  	crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp,
>> crtc_state);
>> -	DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2"
>> : "");
>>  }
>>  
>>  static void intel_psr_activate(struct intel_dp *intel_dp)
>> @@ -589,6 +595,23 @@ static void intel_psr_enable_source(struct
>> intel_dp *intel_dp,
>>  	}
>>  }
>>  
>> +static void intel_psr_enable_locked(struct drm_i915_private
>> *dev_priv,
>> +				    const struct intel_crtc_state
>> *crtc_state)
>> +{
>> +	struct intel_dp *intel_dp = dev_priv->psr.dp;
>> +
>> +	if (dev_priv->psr.enabled)
>> +		return;
>> +
>> +	DRM_DEBUG_KMS("Enabling PSR%s\n", dev_priv->psr.psr2_enabled 
>> ? "2" : "1");
>> +	intel_psr_setup_vsc(intel_dp, crtc_state);
>> +	intel_psr_enable_sink(intel_dp);
>> +	intel_psr_enable_source(intel_dp, crtc_state);
>> +	dev_priv->psr.enabled = true;
>> +
>> +	intel_psr_activate(intel_dp);
>> +}
>> +
>>  /**
>>   * intel_psr_enable - Enable PSR
>>   * @intel_dp: Intel DP
>> @@ -611,20 +634,20 @@ void intel_psr_enable(struct intel_dp
>> *intel_dp,
>>  
>>  	WARN_ON(dev_priv->drrs.dp);
> We could add a new line here?
Indeed, maybe change to if (WARN_ON(intel_dp != dev_priv->drrs.dp)) return; ?
>
>>  	mutex_lock(&dev_priv->psr.lock);
>> -	if (dev_priv->psr.enabled) {
>> +	if (dev_priv->psr.prepared) {
>>  		DRM_DEBUG_KMS("PSR already in use\n");
>>  		goto unlock;
>>  	}
>>  
>>  	dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
>>  	dev_priv->psr.busy_frontbuffer_bits = 0;
>> +	dev_priv->psr.prepared = true;
>> +	dev_priv->psr.dp = intel_dp;
> .dp is already set in init_dpcd()
Paranoia, in case we somehow ended up with 2 eDP's due to a bug. Maybe the change above?

>>  
>> -	intel_psr_setup_vsc(intel_dp, crtc_state);
>> -	intel_psr_enable_sink(intel_dp);
>> -	intel_psr_enable_source(intel_dp, crtc_state);
>> -	dev_priv->psr.enabled = intel_dp;
>> -
>> -	intel_psr_activate(intel_dp);
>> +	if (psr_global_enabled(dev_priv->psr.debug))
>> +		intel_psr_enable_locked(dev_priv, crtc_state);
>> +	else
>> +		DRM_DEBUG_KMS("PSR disabled by flag\n");
>>  
>>  unlock:
>>  	mutex_unlock(&dev_priv->psr.lock);
>> @@ -683,12 +706,13 @@ static void intel_psr_disable_locked(struct
>> intel_dp *intel_dp)
>>  	if (!dev_priv->psr.enabled)
>>  		return;
>>  
>> +	DRM_DEBUG_KMS("Disabling PSR\n");
> Print PSR1/2 too? Like you've done in the enable counter part.
Thought about it, might as well do so.
>
>>  	intel_psr_disable_source(intel_dp);
>>  
>>  	/* Disable PSR on Sink */
>>  	drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
>>  
>> -	dev_priv->psr.enabled = NULL;
>> +	dev_priv->psr.enabled = false;
>>  }
>>  
>>  /**
>> @@ -712,7 +736,14 @@ void intel_psr_disable(struct intel_dp
>> *intel_dp,
>>  		return;
>>  
>>  	mutex_lock(&dev_priv->psr.lock);
>> +	if (intel_dp != dev_priv->psr.dp || !dev_priv->psr.prepared)
> Won't intel_dp == dev_priv->psr.dp if old_crtc_state->has_psr was true?
In case we have 2 eDP's somehow, again.
>
>>  {
>> +		mutex_unlock(&dev_priv->psr.lock);
>> +		return;
>> +	}
>> +
>>  	intel_psr_disable_locked(intel_dp);
>> +
>> +	dev_priv->psr.prepared = false;
>>  	mutex_unlock(&dev_priv->psr.lock);
>>  	cancel_work_sync(&dev_priv->psr.work);
>>  }
>> @@ -724,9 +755,6 @@ int intel_psr_wait_for_idle(const struct
>> intel_crtc_state *new_crtc_state)
>>  	i915_reg_t reg;
>>  	u32 mask;
>>  
>> -	if (!new_crtc_state->has_psr)
>> -		return 0;
>> -
>>  	/*
>>  	 * The sole user right now is intel_pipe_update_start(),
>>  	 * which won't race with psr_enable/disable, which is
>> @@ -737,6 +765,9 @@ int intel_psr_wait_for_idle(const struct
>> intel_crtc_state *new_crtc_state)
>>  	 * not needed and will induce latencies in the atomic
>>  	 * update path.
>>  	 */
>> +	if (!dev_priv->psr.enabled)
>> +		return 0;
>> +
>>  	if (dev_priv->psr.psr2_enabled) {
>>  		reg = EDP_PSR2_STATUS;
>>  		mask = EDP_PSR2_STATUS_STATE_MASK;
>> @@ -756,13 +787,11 @@ int intel_psr_wait_for_idle(const struct
>> intel_crtc_state *new_crtc_state)
>>  
>>  static bool __psr_wait_for_idle_locked(struct drm_i915_private
>> *dev_priv)
>>  {
>> -	struct intel_dp *intel_dp;
>>  	i915_reg_t reg;
>>  	u32 mask;
>>  	int err;
>>  
>> -	intel_dp = dev_priv->psr.enabled;
>> -	if (!intel_dp)
>> +	if (!dev_priv->psr.enabled)
>>  		return false;
>>  
>>  	if (dev_priv->psr.psr2_enabled) {
>> @@ -784,6 +813,62 @@ static bool __psr_wait_for_idle_locked(struct
>> drm_i915_private *dev_priv)
>>  	return err == 0 && dev_priv->psr.enabled;
>>  }
>>  
>> +int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>> +			       struct drm_modeset_acquire_ctx *ctx,
>> +			       u64 val)
>> +{
>> +	struct drm_device *dev = &dev_priv->drm;
>> +	struct drm_connector_state *conn_state;
>> +	struct drm_crtc *crtc;
>> +	struct intel_dp *dp;
>> +	int ret;
>> +	bool enable;
>> +
>> +	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK)
>> ||
>> +	    (val & I915_PSR_DEBUG_MODE_MASK) >
>> I915_PSR_DEBUG_ENABLE) {
>> +		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
>> ctx);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* dev_priv->psr.dp should be set once and then never
>> touched again. */
>> +	dp = READ_ONCE(dev_priv->psr.dp);
>> +	conn_state = dp->attached_connector->base.state;
>> +	crtc = conn_state->crtc;
>> +	if (crtc) {
>> +		ret = drm_modeset_lock(&crtc->mutex, ctx);
>> +		if (ret)
>> +			return ret;
>> +
>> +		ret = wait_for_completion_interruptible(&crtc-
>>> state->commit->hw_done);
>> +	} else
>> +		ret = wait_for_completion_interruptible(&conn_state-
>>> commit->hw_done);
> Shouldn't this wait on connection state be done even if a crtc was
> present?
If the connector is bound to a crtc, then having that idle will mean connector is idle too.

See drm_atomic_helper_setup_commit()

Other way around is not always true.

>> +
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = mutex_lock_interruptible(&dev_priv->psr.lock);
>> +	if (ret)
>> +		return ret;
>> +
>> +	enable = psr_global_enabled(val);
>> +
>> +	if (!enable)
>> +		intel_psr_disable_locked(dev_priv->psr.dp);
>> +
>> +	dev_priv->psr.debug = val;
>> +	intel_psr_irq_control(dev_priv, dev_priv->psr.debug &
>> I915_PSR_DEBUG_IRQ);
>> +
>> +	if (dev_priv->psr.prepared && enable)
>> +		intel_psr_enable_locked(dev_priv,
>> to_intel_crtc_state(crtc->state));
>> +
>> +	mutex_unlock(&dev_priv->psr.lock);
>> +	return ret;
>> +}
>> +
>>  static void intel_psr_work(struct work_struct *work)
>>  {
>>  	struct drm_i915_private *dev_priv =
>> @@ -811,7 +896,8 @@ static void intel_psr_work(struct work_struct
>> *work)
>>  	if (dev_priv->psr.busy_frontbuffer_bits || dev_priv-
>>> psr.active)
>>  		goto unlock;
>>  
>> -	intel_psr_activate(dev_priv->psr.enabled);
>> +	intel_psr_activate(dev_priv->psr.dp
>> +);
> ^typo
Indeed! Will fix.
>>  unlock:
>>  	mutex_unlock(&dev_priv->psr.lock);
>>  }
>> @@ -866,7 +952,7 @@ void intel_psr_invalidate(struct drm_i915_private
>> *dev_priv,
>>  		return;
>>  	}
>>  
>> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
>>> base.base.crtc;
>> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>>  	pipe = to_intel_crtc(crtc)->pipe;
>>  
>>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
>> @@ -909,7 +995,7 @@ void intel_psr_flush(struct drm_i915_private
>> *dev_priv,
>>  		return;
>>  	}
>>  
>> -	crtc = dp_to_dig_port(dev_priv->psr.enabled)-
>>> base.base.crtc;
>> +	crtc = dp_to_dig_port(dev_priv->psr.dp)->base.base.crtc;
>>  	pipe = to_intel_crtc(crtc)->pipe;
>>  
>>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
>> @@ -991,7 +1077,7 @@ void intel_psr_short_pulse(struct intel_dp
>> *intel_dp)
>>  
>>  	mutex_lock(&psr->lock);
>>  
>> -	if (psr->enabled != intel_dp)
>> +	if (!psr->enabled || psr->dp != intel_dp)
>>  		goto exit;
>>  
>>  	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val)
>> != 1) {

Thanks for review, will send a new version today.

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

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

* Re: [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode.
  2018-08-08  1:35                       ` Dhinakaran Pandiyan
@ 2018-08-08  9:01                         ` Maarten Lankhorst
  0 siblings, 0 replies; 31+ messages in thread
From: Maarten Lankhorst @ 2018-08-08  9:01 UTC (permalink / raw)
  To: dhinakaran.pandiyan, intel-gfx; +Cc: Rodrigo Vivi

Op 08-08-18 om 03:35 schreef Dhinakaran Pandiyan:
> On Tue, 2018-07-31 at 15:35 +0200, Maarten Lankhorst wrote:
>> This will make it easier to test PSR1 on PSR2 capable eDP machines.
> Thanks for writing this patch, we can make use of this to fix failures
> on PSR2 machines in CI.
>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_drv.h  |  2 ++
>>  drivers/gpu/drm/i915/intel_psr.c | 27 ++++++++++++++++++++++++---
>>  2 files changed, 26 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h
>> b/drivers/gpu/drm/i915/i915_drv.h
>> index ef04b6cd7863..07783b9e7960 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -617,6 +617,8 @@ struct i915_psr {
>>  #define I915_PSR_DEBUG_DEFAULT	(0 << 1)
>>  #define I915_PSR_DEBUG_DISABLE	(1 << 1)
>>  #define I915_PSR_DEBUG_ENABLE	(2 << 1)
>> +#define I915_PSR_DEBUG_FORCE_PSR1 (3 << 1)
>> +#define I915_PSR_DEBUG_FORCE_PSR2 (4 << 1)
>>  
>>  	u32 debug;
>>  	bool sink_support;
>> diff --git a/drivers/gpu/drm/i915/intel_psr.c
>> b/drivers/gpu/drm/i915/intel_psr.c
>> index 7848829094ca..4cf4ac7068d0 100644
>> --- a/drivers/gpu/drm/i915/intel_psr.c
>> +++ b/drivers/gpu/drm/i915/intel_psr.c
>> @@ -813,19 +813,38 @@ static bool __psr_wait_for_idle_locked(struct
>> drm_i915_private *dev_priv)
>>  	return err == 0 && dev_priv->psr.enabled;
>>  }
>>  
>> +static bool switching_psr(struct drm_i915_private *dev_priv,
>> +			  struct intel_crtc_state *crtc_state,
>> +			  u32 mode)
>> +{
>> +	/* Can't switch psr state anyway if PSR2 is not supported.
>> */
>> +	if (!crtc_state || !crtc_state->has_psr2)
>> +		return false;
>> +
>> +	if (dev_priv->psr.psr2_enabled && mode ==
>> I915_PSR_DEBUG_FORCE_PSR1)
>> +		return true;
>> +
>> +	if (!dev_priv->psr.psr2_enabled && mode !=
>> I915_PSR_DEBUG_FORCE_PSR1)
>> +		return true;
>> +
>> +	return false;
>> +}
>> +
>>  int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
>>  			       struct drm_modeset_acquire_ctx *ctx,
>>  			       u64 val)
>>  {
>>  	struct drm_device *dev = &dev_priv->drm;
>>  	struct drm_connector_state *conn_state;
>> +	struct intel_crtc_state *crtc_state = NULL;
>>  	struct drm_crtc *crtc;
>>  	struct intel_dp *dp;
>>  	int ret;
>>  	bool enable;
>> +	u32 mode = val & I915_PSR_DEBUG_MODE_MASK;
>>  
>>  	if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK)
>> ||
>> -	    (val & I915_PSR_DEBUG_MODE_MASK) >
>> I915_PSR_DEBUG_ENABLE) {
>> +	    mode > I915_PSR_DEBUG_FORCE_PSR2) {
>>  		DRM_DEBUG_KMS("Invalid debug mask %llx\n", val);
>>  		return -EINVAL;
>>  	}
>> @@ -843,7 +862,8 @@ int intel_psr_set_debugfs_mode(struct
>> drm_i915_private *dev_priv,
>>  		if (ret)
>>  			return ret;
>>  
>> -		ret = wait_for_completion_interruptible(&crtc-
>>> state->commit->hw_done);
>> +		crtc_state = to_intel_crtc_state(crtc->state);
>> +		ret = wait_for_completion_interruptible(&crtc_state-
>>> base.commit->hw_done);
>>  	} else
>>  		ret = wait_for_completion_interruptible(&conn_state-
>>> commit->hw_done);
>>  
>> @@ -856,10 +876,11 @@ int intel_psr_set_debugfs_mode(struct
>> drm_i915_private *dev_priv,
>>  
>>  	enable = psr_global_enabled(val);
>>  
>> -	if (!enable)
>> +	if (!enable || switching_psr(dev_priv, crtc_state, mode))
>>  		intel_psr_disable_locked(dev_priv->psr.dp);
>>  
>>  	dev_priv->psr.debug = val;
>> +	dev_priv->psr.psr2_enabled = mode !=
>> I915_PSR_DEBUG_FORCE_PSR1 && crtc_state->has_psr2;
> crtc_state can be NULL.
Right, will fix.
>
>>  	intel_psr_irq_control(dev_priv, dev_priv->psr.debug &
>> I915_PSR_DEBUG_IRQ);
>>  
>>  	if (dev_priv->psr.prepared && enable)
>
> If a modeset was done after writing I915_PSR_DEBUG_FORCE_PSR1, we'll
> still end up enabling PSR2. Check for debug flags in intel_psr_enable()
> ?
Hmm.. good point, will add the same check there.

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

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

end of thread, other threads:[~2018-08-08  9:02 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-14 11:46 [PATCH] drm/i915: Control PSR at runtime through debugfs only Maarten Lankhorst
2018-03-14 12:32 ` ✗ Fi.CI.BAT: failure for " Patchwork
2018-03-14 15:58 ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
2018-03-14 16:07   ` Chris Wilson
2018-03-14 16:11     ` Maarten Lankhorst
2018-03-14 16:27 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
2018-03-14 21:53 ` [PATCH] drm/i915: Control PSR at runtime through debugfs only Rodrigo Vivi
2018-03-15 10:28   ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
2018-03-22  1:45     ` Pandiyan, Dhinakaran
2018-03-22  9:41       ` Maarten Lankhorst
2018-07-26  6:32         ` Dhinakaran Pandiyan
2018-07-26  9:06           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs, v3 Maarten Lankhorst
2018-07-27  3:27             ` Dhinakaran Pandiyan
2018-07-27  8:41               ` Maarten Lankhorst
2018-07-28  5:23                 ` Dhinakaran Pandiyan
2018-07-30  9:40                   ` Maarten Lankhorst
2018-07-31 13:35                   ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
2018-07-31 13:35                     ` [PATCH 2/2] drm/i915/psr: Add debugfs support to force toggling PSR1/2 mode Maarten Lankhorst
2018-08-08  1:35                       ` Dhinakaran Pandiyan
2018-08-08  9:01                         ` Maarten Lankhorst
2018-08-01  9:41                     ` [PATCH 1/2] drm/i915: Allow control of PSR at runtime through debugfs, v4 Maarten Lankhorst
2018-08-08  0:07                     ` Dhinakaran Pandiyan
2018-08-08  9:00                       ` Maarten Lankhorst
2018-07-26 12:54           ` [PATCH] drm/i915: Allow control of PSR at runtime through debugfs Maarten Lankhorst
2018-03-15  0:58 ` ✓ Fi.CI.IGT: success for drm/i915: Control PSR at runtime through debugfs only (rev2) Patchwork
2018-03-15 11:01 ` ✓ Fi.CI.BAT: success for drm/i915: Control PSR at runtime through debugfs only (rev3) Patchwork
2018-03-15 12:17 ` ✓ Fi.CI.IGT: " Patchwork
2018-07-26 10:10 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Control PSR at runtime through debugfs only (rev4) Patchwork
2018-07-26 10:11 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-07-26 10:30 ` ✓ Fi.CI.BAT: success " Patchwork
2018-07-26 11:57 ` ✓ Fi.CI.IGT: " 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.