All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915: Shut down displays gracefully on reboot
@ 2016-08-03 13:36 ville.syrjala
  2016-08-03 13:59 ` ✗ Ro.CI.BAT: failure for " Patchwork
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: ville.syrjala @ 2016-08-03 13:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
reboot the machine. After reboot, the monitor is somehow confused and
refuses to do the payload allocation:
 [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
 [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
and thus we're left with a black screen until the monitor power is
toggled.

It seems that if we shut down things gracefully prior to rebooting, the
monitor doesn't get confused like this. So let's try to shut down all
the displays gracefully on reboot. The downside is that we will
introduce the reboot notifier to all the modesetl locks. So if there's
a locking bug around, we might not be able to reboot the machine
gracefully. sysrq reboot will still work though, as it will not
call the notifiers.

While we do this, we can eliminate the eDP reboot notifier, which is
there to shut down the panel power and make sure the firmware won't
violate the panel power cycle delay post-reboot. Since we're now
shutting eDP down properly, we can mostly just rip out the eDP notifier.
We still need to do the panel power cycle wait though, as that would
normally get postponed until the next modeset. So let's move that part
into intel_panel so that other display types will get the same treatment
as a bonus.

The Dell UP2414Q can often get even more confused, and sometimes what
you have to do is: switch to another input on the monitor, toggle the
monitor power, switch the input back to the original setting. And
sometimes it seems you just have to yank the power cable entirely. I'm
not sure if this reboot notifier might avoid some of these other
failure modes as well, but I'm pretty sure it can't hurt at least.

Cc: Clint Taylor <clinton.a.taylor@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  2 ++
 drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c      | 49 ++----------------------------------
 drivers/gpu/drm/i915/intel_drv.h     |  7 +++---
 drivers/gpu/drm/i915/intel_dsi.c     |  3 ++-
 drivers/gpu/drm/i915/intel_dvo.c     |  2 +-
 drivers/gpu/drm/i915/intel_lvds.c    |  3 ++-
 drivers/gpu/drm/i915/intel_panel.c   | 29 ++++++++++++++++++++-
 8 files changed, 65 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 65ada5d2f88c..f8eb8c7de007 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1727,6 +1727,8 @@ struct intel_wm_config {
 struct drm_i915_private {
 	struct drm_device drm;
 
+	struct notifier_block reboot_notifier;
+
 	struct kmem_cache *objects;
 	struct kmem_cache *vmas;
 	struct kmem_cache *requests;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a8e8cc8dfae9..2192a21aa6c9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -31,6 +31,8 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vgaarb.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
 #include <drm/drm_edid.h>
 #include <drm/drmP.h>
 #include "intel_drv.h"
@@ -15578,6 +15580,23 @@ fail:
 	drm_modeset_acquire_fini(&ctx);
 }
 
+
+static int intel_reboot_notifier(struct notifier_block *nb,
+				 unsigned long code, void *unused)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(nb, typeof(*dev_priv), reboot_notifier);
+
+	if (code != SYS_RESTART)
+		return 0;
+
+	intel_display_suspend(&dev_priv->drm);
+
+	intel_panel_reboot_notifier(dev_priv);
+
+	return 0;
+}
+
 void intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -15706,6 +15725,9 @@ void intel_modeset_init(struct drm_device *dev)
 	 * since the watermark calculation done here will use pstate->fb.
 	 */
 	sanitize_watermarks(dev);
+
+	dev_priv->reboot_notifier.notifier_call = intel_reboot_notifier;
+	register_reboot_notifier(&dev_priv->reboot_notifier);
 }
 
 static void intel_enable_pipe_a(struct drm_device *dev)
@@ -16291,6 +16313,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
+	unregister_reboot_notifier(&dev_priv->reboot_notifier);
+
 	intel_disable_gt_powersave(dev_priv);
 
 	/*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 001f74fc0ce5..d8d13a9e33e5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -28,8 +28,6 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/export.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -631,42 +629,6 @@ _pp_stat_reg(struct intel_dp *intel_dp)
 	return regs.pp_stat;
 }
 
-/* Reboot notifier handler to shutdown panel power to guarantee T12 timing
-   This function only applicable when panel PM state is not to be tracked */
-static int edp_notify_handler(struct notifier_block *this, unsigned long code,
-			      void *unused)
-{
-	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
-						 edp_notifier);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (!is_edp(intel_dp) || code != SYS_RESTART)
-		return 0;
-
-	pps_lock(intel_dp);
-
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-		i915_reg_t pp_ctrl_reg, pp_div_reg;
-		u32 pp_div;
-
-		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
-		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
-		pp_div = I915_READ(pp_div_reg);
-		pp_div &= PP_REFERENCE_DIVIDER_MASK;
-
-		/* 0x1F write to PP_DIV_REG sets max cycle delay */
-		I915_WRITE(pp_div_reg, pp_div | 0x1F);
-		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
-		msleep(intel_dp->panel_power_cycle_delay);
-	}
-
-	pps_unlock(intel_dp);
-
-	return 0;
-}
-
 static bool edp_have_panel_power(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -4562,11 +4524,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 		pps_lock(intel_dp);
 		edp_panel_vdd_off_sync(intel_dp);
 		pps_unlock(intel_dp);
-
-		if (intel_dp->edp_notifier.notifier_call) {
-			unregister_reboot_notifier(&intel_dp->edp_notifier);
-			intel_dp->edp_notifier.notifier_call = NULL;
-		}
 	}
 
 	intel_dp_aux_fini(intel_dp);
@@ -5465,9 +5422,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	mutex_unlock(&dev->mode_config.mutex);
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
-		register_reboot_notifier(&intel_dp->edp_notifier);
-
 		/*
 		 * Figure out the current pipe for the initial backlight setup.
 		 * If the current pipe isn't valid, try the PPS pipe, and if that
@@ -5488,7 +5442,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 			      pipe_name(pipe));
 	}
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode,
+			 intel_dp->panel_power_cycle_delay);
 	intel_connector->panel.backlight.power = intel_edp_backlight_power;
 	intel_panel_setup_backlight(connector, pipe);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 50cdc890d956..92fa66a02ca5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -226,6 +226,7 @@ struct intel_panel {
 	struct drm_display_mode *fixed_mode;
 	struct drm_display_mode *downclock_mode;
 	int fitting_mode;
+	int reboot_power_cycle_delay;
 
 	/* backlight */
 	struct {
@@ -877,8 +878,6 @@ struct intel_dp {
 	unsigned long last_backlight_off;
 	ktime_t panel_power_off_time;
 
-	struct notifier_block edp_notifier;
-
 	/*
 	 * Pipe whose power sequencer is currently locked into
 	 * this port. Only relevant on VLV/CHV.
@@ -1521,8 +1520,10 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
 /* intel_panel.c */
 int intel_panel_init(struct intel_panel *panel,
 		     struct drm_display_mode *fixed_mode,
-		     struct drm_display_mode *downclock_mode);
+		     struct drm_display_mode *downclock_mode,
+		     int reboot_power_cycle_delay);
 void intel_panel_fini(struct intel_panel *panel);
+void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv);
 void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
 			    struct drm_display_mode *adjusted_mode);
 void intel_pch_panel_fitting(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index de8e9fb51595..5b722ec23381 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1596,7 +1596,8 @@ void intel_dsi_init(struct drm_device *dev)
 	connector->display_info.width_mm = fixed_mode->width_mm;
 	connector->display_info.height_mm = fixed_mode->height_mm;
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
+			 intel_dsi->panel_pwr_cycle_delay);
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	intel_dsi_add_properties(intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 47bdf9dad0d3..c2c9c922590c 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -547,7 +547,7 @@ void intel_dvo_init(struct drm_device *dev)
 			 */
 			intel_panel_init(&intel_connector->panel,
 					 intel_dvo_get_current_mode(connector),
-					 NULL);
+					 NULL, 0);
 			intel_dvo->panel_wants_dither = true;
 		}
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 49550470483e..07d7ac2c1520 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -1120,7 +1120,8 @@ void intel_lvds_init(struct drm_device *dev)
 out:
 	mutex_unlock(&dev->mode_config.mutex);
 
-	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+	/* FIXME fill in an accurate power cycle delay */
+	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode, 0);
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 96c65d77e886..fe57a743ad21 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1781,14 +1781,41 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
 	}
 }
 
+/*
+ * Make sure the power cycle delay is respected. The PPS
+ * does supposedly initiate a power cycle on reset, but it
+ * also resets the power cycle delay register value to the
+ * default value, and hence may not wait long enough if the
+ * firmware attempts to power up the panel immediately.
+ * Also eg. DSI doesn't use the PPS.
+ */
+void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = &dev_priv->drm;
+	struct intel_connector *connector;
+	int reboot_power_cycle_delay = 0;
+
+	for_each_intel_connector(dev, connector) {
+		struct intel_panel *panel = &connector->panel;
+
+		reboot_power_cycle_delay = max(reboot_power_cycle_delay,
+					       panel->reboot_power_cycle_delay);
+	}
+
+	if (reboot_power_cycle_delay)
+		msleep(reboot_power_cycle_delay);
+}
+
 int intel_panel_init(struct intel_panel *panel,
 		     struct drm_display_mode *fixed_mode,
-		     struct drm_display_mode *downclock_mode)
+		     struct drm_display_mode *downclock_mode,
+		     int reboot_power_cycle_delay)
 {
 	intel_panel_init_backlight_funcs(panel);
 
 	panel->fixed_mode = fixed_mode;
 	panel->downclock_mode = downclock_mode;
+	panel->reboot_power_cycle_delay = reboot_power_cycle_delay;
 
 	return 0;
 }
-- 
2.7.4

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

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

* ✗ Ro.CI.BAT: failure for drm/i915: Shut down displays gracefully on reboot
  2016-08-03 13:36 [PATCH] drm/i915: Shut down displays gracefully on reboot ville.syrjala
@ 2016-08-03 13:59 ` Patchwork
  2016-08-05 22:45 ` [PATCH] " Clint Taylor
  2016-08-06  8:09 ` Lukas Wunner
  2 siblings, 0 replies; 9+ messages in thread
From: Patchwork @ 2016-08-03 13:59 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Shut down displays gracefully on reboot
URL   : https://patchwork.freedesktop.org/series/10593/
State : failure

== Summary ==

Series 10593v1 drm/i915: Shut down displays gracefully on reboot
http://patchwork.freedesktop.org/api/1.0/series/10593/revisions/1/mbox

Test kms_cursor_legacy:
        Subgroup basic-cursor-vs-flip-varying-size:
                pass       -> FAIL       (ro-ilk1-i5-650)
        Subgroup basic-flip-vs-cursor-legacy:
                fail       -> PASS       (ro-bdw-i7-5600u)
        Subgroup basic-flip-vs-cursor-varying-size:
                fail       -> PASS       (ro-snb-i7-2620M)
                fail       -> PASS       (ro-bdw-i5-5250u)
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-a:
                dmesg-warn -> PASS       (ro-bdw-i7-5557U)

fi-hsw-i7-4770k  total:240  pass:218  dwarn:0   dfail:0   fail:0   skip:22 
fi-kbl-qkkr      total:240  pass:181  dwarn:29  dfail:0   fail:3   skip:27 
fi-skl-i5-6260u  total:240  pass:224  dwarn:0   dfail:0   fail:2   skip:14 
fi-skl-i7-6700k  total:240  pass:208  dwarn:0   dfail:0   fail:4   skip:28 
fi-snb-i7-2600   total:240  pass:198  dwarn:0   dfail:0   fail:0   skip:42 
ro-bdw-i5-5250u  total:240  pass:220  dwarn:4   dfail:0   fail:0   skip:16 
ro-bdw-i7-5557U  total:240  pass:224  dwarn:0   dfail:0   fail:0   skip:16 
ro-bdw-i7-5600u  total:240  pass:207  dwarn:0   dfail:0   fail:1   skip:32 
ro-bsw-n3050     total:240  pass:193  dwarn:0   dfail:0   fail:4   skip:43 
ro-byt-n2820     total:240  pass:197  dwarn:0   dfail:0   fail:3   skip:40 
ro-hsw-i3-4010u  total:240  pass:214  dwarn:0   dfail:0   fail:0   skip:26 
ro-hsw-i7-4770r  total:240  pass:214  dwarn:0   dfail:0   fail:0   skip:26 
ro-ilk-i7-620lm  total:240  pass:173  dwarn:1   dfail:0   fail:1   skip:65 
ro-ilk1-i5-650   total:235  pass:173  dwarn:0   dfail:0   fail:2   skip:60 
ro-ivb2-i7-3770  total:240  pass:209  dwarn:0   dfail:0   fail:0   skip:31 
ro-skl3-i5-6260u total:240  pass:222  dwarn:0   dfail:0   fail:4   skip:14 
ro-snb-i7-2620M  total:240  pass:198  dwarn:0   dfail:0   fail:1   skip:41 
ro-ivb-i7-3770 failed to connect after reboot

Results at /archive/results/CI_IGT_test/RO_Patchwork_1678/

0bee311 drm-intel-nightly: 2016y-08m-03d-13h-02m-57s UTC integration manifest
b221e3a drm/i915: Shut down displays gracefully on reboot

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-03 13:36 [PATCH] drm/i915: Shut down displays gracefully on reboot ville.syrjala
  2016-08-03 13:59 ` ✗ Ro.CI.BAT: failure for " Patchwork
@ 2016-08-05 22:45 ` Clint Taylor
  2016-08-08 12:52   ` Ville Syrjälä
  2016-08-06  8:09 ` Lukas Wunner
  2 siblings, 1 reply; 9+ messages in thread
From: Clint Taylor @ 2016-08-05 22:45 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx; +Cc: Paulo Zanoni

On 08/03/2016 06:36 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> reboot the machine. After reboot, the monitor is somehow confused and
> refuses to do the payload allocation:
>   [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
>   [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> and thus we're left with a black screen until the monitor power is
> toggled.
>
> It seems that if we shut down things gracefully prior to rebooting, the
> monitor doesn't get confused like this. So let's try to shut down all
> the displays gracefully on reboot. The downside is that we will
> introduce the reboot notifier to all the modesetl locks. So if there's
> a locking bug around, we might not be able to reboot the machine
> gracefully. sysrq reboot will still work though, as it will not
> call the notifiers.
>
> While we do this, we can eliminate the eDP reboot notifier, which is
> there to shut down the panel power and make sure the firmware won't
> violate the panel power cycle delay post-reboot. Since we're now
> shutting eDP down properly, we can mostly just rip out the eDP notifier.
> We still need to do the panel power cycle wait though, as that would
> normally get postponed until the next modeset. So let's move that part
> into intel_panel so that other display types will get the same treatment
> as a bonus.
>
> The Dell UP2414Q can often get even more confused, and sometimes what
> you have to do is: switch to another input on the monitor, toggle the
> monitor power, switch the input back to the original setting. And
> sometimes it seems you just have to yank the power cable entirely. I'm
> not sure if this reboot notifier might avoid some of these other
> failure modes as well, but I'm pretty sure it can't hurt at least.
>

While testing this change on SKL if 2 crtc's are enabled resume from 
suspend is 500ms longer than a single crtc resume. Are we calling the 
T12 msleep(500) for non eDP panels?

During testing VDD to the panel, the T12 panel timeout requirement is 
being meet at >500ms during reboot and suspend/resume.

> Cc: Clint Taylor <clinton.a.taylor@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h      |  2 ++
>   drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++
>   drivers/gpu/drm/i915/intel_dp.c      | 49 ++----------------------------------
>   drivers/gpu/drm/i915/intel_drv.h     |  7 +++---
>   drivers/gpu/drm/i915/intel_dsi.c     |  3 ++-
>   drivers/gpu/drm/i915/intel_dvo.c     |  2 +-
>   drivers/gpu/drm/i915/intel_lvds.c    |  3 ++-
>   drivers/gpu/drm/i915/intel_panel.c   | 29 ++++++++++++++++++++-
>   8 files changed, 65 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 65ada5d2f88c..f8eb8c7de007 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1727,6 +1727,8 @@ struct intel_wm_config {
>   struct drm_i915_private {
>   	struct drm_device drm;
>
> +	struct notifier_block reboot_notifier;
> +
>   	struct kmem_cache *objects;
>   	struct kmem_cache *vmas;
>   	struct kmem_cache *requests;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a8e8cc8dfae9..2192a21aa6c9 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -31,6 +31,8 @@
>   #include <linux/kernel.h>
>   #include <linux/slab.h>
>   #include <linux/vgaarb.h>
> +#include <linux/notifier.h>
> +#include <linux/reboot.h>
>   #include <drm/drm_edid.h>
>   #include <drm/drmP.h>
>   #include "intel_drv.h"
> @@ -15578,6 +15580,23 @@ fail:
>   	drm_modeset_acquire_fini(&ctx);
>   }
>
> +
> +static int intel_reboot_notifier(struct notifier_block *nb,
> +				 unsigned long code, void *unused)
> +{
> +	struct drm_i915_private *dev_priv =
> +		container_of(nb, typeof(*dev_priv), reboot_notifier);
> +
> +	if (code != SYS_RESTART)
> +		return 0;
> +
> +	intel_display_suspend(&dev_priv->drm);
> +

Need to check to make sure there is a panel before calling 
intel_panel_reboot_notifier().

> +	intel_panel_reboot_notifier(dev_priv);
> +
> +	return 0;
> +}
> +
>   void intel_modeset_init(struct drm_device *dev)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(dev);
> @@ -15706,6 +15725,9 @@ void intel_modeset_init(struct drm_device *dev)
>   	 * since the watermark calculation done here will use pstate->fb.
>   	 */
>   	sanitize_watermarks(dev);
> +
> +	dev_priv->reboot_notifier.notifier_call = intel_reboot_notifier;
> +	register_reboot_notifier(&dev_priv->reboot_notifier);
>   }
>
>   static void intel_enable_pipe_a(struct drm_device *dev)
> @@ -16291,6 +16313,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(dev);
>
> +	unregister_reboot_notifier(&dev_priv->reboot_notifier);
> +
>   	intel_disable_gt_powersave(dev_priv);
>
>   	/*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 001f74fc0ce5..d8d13a9e33e5 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -28,8 +28,6 @@
>   #include <linux/i2c.h>
>   #include <linux/slab.h>
>   #include <linux/export.h>
> -#include <linux/notifier.h>
> -#include <linux/reboot.h>
>   #include <drm/drmP.h>
>   #include <drm/drm_atomic_helper.h>
>   #include <drm/drm_crtc.h>
> @@ -631,42 +629,6 @@ _pp_stat_reg(struct intel_dp *intel_dp)
>   	return regs.pp_stat;
>   }
>
> -/* Reboot notifier handler to shutdown panel power to guarantee T12 timing
> -   This function only applicable when panel PM state is not to be tracked */
> -static int edp_notify_handler(struct notifier_block *this, unsigned long code,
> -			      void *unused)
> -{
> -	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
> -						 edp_notifier);
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> -		return 0;
> -
> -	pps_lock(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> -		i915_reg_t pp_ctrl_reg, pp_div_reg;
> -		u32 pp_div;
> -
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> -		pp_div = I915_READ(pp_div_reg);
> -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> -
> -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> -		msleep(intel_dp->panel_power_cycle_delay);
> -	}
> -
> -	pps_unlock(intel_dp);
> -
> -	return 0;
> -}
> -
>   static bool edp_have_panel_power(struct intel_dp *intel_dp)
>   {
>   	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -4562,11 +4524,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>   		pps_lock(intel_dp);
>   		edp_panel_vdd_off_sync(intel_dp);
>   		pps_unlock(intel_dp);
> -
> -		if (intel_dp->edp_notifier.notifier_call) {
> -			unregister_reboot_notifier(&intel_dp->edp_notifier);
> -			intel_dp->edp_notifier.notifier_call = NULL;
> -		}
>   	}
>
>   	intel_dp_aux_fini(intel_dp);
> @@ -5465,9 +5422,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>   	mutex_unlock(&dev->mode_config.mutex);
>
>   	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> -		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
> -		register_reboot_notifier(&intel_dp->edp_notifier);
> -
>   		/*
>   		 * Figure out the current pipe for the initial backlight setup.
>   		 * If the current pipe isn't valid, try the PPS pipe, and if that
> @@ -5488,7 +5442,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>   			      pipe_name(pipe));
>   	}
>
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode,
> +			 intel_dp->panel_power_cycle_delay);
>   	intel_connector->panel.backlight.power = intel_edp_backlight_power;
>   	intel_panel_setup_backlight(connector, pipe);
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 50cdc890d956..92fa66a02ca5 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -226,6 +226,7 @@ struct intel_panel {
>   	struct drm_display_mode *fixed_mode;
>   	struct drm_display_mode *downclock_mode;
>   	int fitting_mode;
> +	int reboot_power_cycle_delay;
>
>   	/* backlight */
>   	struct {
> @@ -877,8 +878,6 @@ struct intel_dp {
>   	unsigned long last_backlight_off;
>   	ktime_t panel_power_off_time;
>
> -	struct notifier_block edp_notifier;
> -
>   	/*
>   	 * Pipe whose power sequencer is currently locked into
>   	 * this port. Only relevant on VLV/CHV.
> @@ -1521,8 +1520,10 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
>   /* intel_panel.c */
>   int intel_panel_init(struct intel_panel *panel,
>   		     struct drm_display_mode *fixed_mode,
> -		     struct drm_display_mode *downclock_mode);
> +		     struct drm_display_mode *downclock_mode,
> +		     int reboot_power_cycle_delay);
>   void intel_panel_fini(struct intel_panel *panel);
> +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv);
>   void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
>   			    struct drm_display_mode *adjusted_mode);
>   void intel_pch_panel_fitting(struct intel_crtc *crtc,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> index de8e9fb51595..5b722ec23381 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -1596,7 +1596,8 @@ void intel_dsi_init(struct drm_device *dev)
>   	connector->display_info.width_mm = fixed_mode->width_mm;
>   	connector->display_info.height_mm = fixed_mode->height_mm;
>
> -	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
> +			 intel_dsi->panel_pwr_cycle_delay);
>   	intel_panel_setup_backlight(connector, INVALID_PIPE);
>
>   	intel_dsi_add_properties(intel_connector);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 47bdf9dad0d3..c2c9c922590c 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -547,7 +547,7 @@ void intel_dvo_init(struct drm_device *dev)
>   			 */
>   			intel_panel_init(&intel_connector->panel,
>   					 intel_dvo_get_current_mode(connector),
> -					 NULL);
> +					 NULL, 0);
>   			intel_dvo->panel_wants_dither = true;
>   		}
>
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 49550470483e..07d7ac2c1520 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -1120,7 +1120,8 @@ void intel_lvds_init(struct drm_device *dev)
>   out:
>   	mutex_unlock(&dev->mode_config.mutex);
>
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	/* FIXME fill in an accurate power cycle delay */
> +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode, 0);
>   	intel_panel_setup_backlight(connector, INVALID_PIPE);
>
>   	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 96c65d77e886..fe57a743ad21 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1781,14 +1781,41 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
>   	}
>   }
>
> +/*
> + * Make sure the power cycle delay is respected. The PPS
> + * does supposedly initiate a power cycle on reset, but it
> + * also resets the power cycle delay register value to the
> + * default value, and hence may not wait long enough if the
> + * firmware attempts to power up the panel immediately.
> + * Also eg. DSI doesn't use the PPS.
> + */
> +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct intel_connector *connector;
> +	int reboot_power_cycle_delay = 0;
> +
> +	for_each_intel_connector(dev, connector) {
> +		struct intel_panel *panel = &connector->panel;
> +
> +		reboot_power_cycle_delay = max(reboot_power_cycle_delay,
> +					       panel->reboot_power_cycle_delay);
> +	}
> +
> +	if (reboot_power_cycle_delay)
> +		msleep(reboot_power_cycle_delay);
> +}
> +
>   int intel_panel_init(struct intel_panel *panel,
>   		     struct drm_display_mode *fixed_mode,
> -		     struct drm_display_mode *downclock_mode)
> +		     struct drm_display_mode *downclock_mode,
> +		     int reboot_power_cycle_delay)
>   {
>   	intel_panel_init_backlight_funcs(panel);
>
>   	panel->fixed_mode = fixed_mode;
>   	panel->downclock_mode = downclock_mode;
> +	panel->reboot_power_cycle_delay = reboot_power_cycle_delay;
>
>   	return 0;
>   }
>

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-03 13:36 [PATCH] drm/i915: Shut down displays gracefully on reboot ville.syrjala
  2016-08-03 13:59 ` ✗ Ro.CI.BAT: failure for " Patchwork
  2016-08-05 22:45 ` [PATCH] " Clint Taylor
@ 2016-08-06  8:09 ` Lukas Wunner
  2016-08-06  8:29   ` Chris Wilson
  2 siblings, 1 reply; 9+ messages in thread
From: Lukas Wunner @ 2016-08-06  8:09 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx, Paulo Zanoni

On Wed, Aug 03, 2016 at 04:36:18PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> reboot the machine. After reboot, the monitor is somehow confused and
> refuses to do the payload allocation:
>  [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
>  [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> and thus we're left with a black screen until the monitor power is
> toggled.
> 
> It seems that if we shut down things gracefully prior to rebooting, the
> monitor doesn't get confused like this. So let's try to shut down all
> the displays gracefully on reboot. The downside is that we will
> introduce the reboot notifier to all the modesetl locks. So if there's
> a locking bug around, we might not be able to reboot the machine
> gracefully. sysrq reboot will still work though, as it will not
> call the notifiers.

struct pci_driver has a ->shutdown hook which is currently not defined
in i915_pci_driver. How about using that instead of reboot_notifier
to avoid potential locking issues?

Best regards,

Lukas

> 
> While we do this, we can eliminate the eDP reboot notifier, which is
> there to shut down the panel power and make sure the firmware won't
> violate the panel power cycle delay post-reboot. Since we're now
> shutting eDP down properly, we can mostly just rip out the eDP notifier.
> We still need to do the panel power cycle wait though, as that would
> normally get postponed until the next modeset. So let's move that part
> into intel_panel so that other display types will get the same treatment
> as a bonus.
> 
> The Dell UP2414Q can often get even more confused, and sometimes what
> you have to do is: switch to another input on the monitor, toggle the
> monitor power, switch the input back to the original setting. And
> sometimes it seems you just have to yank the power cable entirely. I'm
> not sure if this reboot notifier might avoid some of these other
> failure modes as well, but I'm pretty sure it can't hurt at least.
> 
> Cc: Clint Taylor <clinton.a.taylor@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  2 ++
>  drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++
>  drivers/gpu/drm/i915/intel_dp.c      | 49 ++----------------------------------
>  drivers/gpu/drm/i915/intel_drv.h     |  7 +++---
>  drivers/gpu/drm/i915/intel_dsi.c     |  3 ++-
>  drivers/gpu/drm/i915/intel_dvo.c     |  2 +-
>  drivers/gpu/drm/i915/intel_lvds.c    |  3 ++-
>  drivers/gpu/drm/i915/intel_panel.c   | 29 ++++++++++++++++++++-
>  8 files changed, 65 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 65ada5d2f88c..f8eb8c7de007 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1727,6 +1727,8 @@ struct intel_wm_config {
>  struct drm_i915_private {
>  	struct drm_device drm;
>  
> +	struct notifier_block reboot_notifier;
> +
>  	struct kmem_cache *objects;
>  	struct kmem_cache *vmas;
>  	struct kmem_cache *requests;
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a8e8cc8dfae9..2192a21aa6c9 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -31,6 +31,8 @@
>  #include <linux/kernel.h>
>  #include <linux/slab.h>
>  #include <linux/vgaarb.h>
> +#include <linux/notifier.h>
> +#include <linux/reboot.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drmP.h>
>  #include "intel_drv.h"
> @@ -15578,6 +15580,23 @@ fail:
>  	drm_modeset_acquire_fini(&ctx);
>  }
>  
> +
> +static int intel_reboot_notifier(struct notifier_block *nb,
> +				 unsigned long code, void *unused)
> +{
> +	struct drm_i915_private *dev_priv =
> +		container_of(nb, typeof(*dev_priv), reboot_notifier);
> +
> +	if (code != SYS_RESTART)
> +		return 0;
> +
> +	intel_display_suspend(&dev_priv->drm);
> +
> +	intel_panel_reboot_notifier(dev_priv);
> +
> +	return 0;
> +}
> +
>  void intel_modeset_init(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> @@ -15706,6 +15725,9 @@ void intel_modeset_init(struct drm_device *dev)
>  	 * since the watermark calculation done here will use pstate->fb.
>  	 */
>  	sanitize_watermarks(dev);
> +
> +	dev_priv->reboot_notifier.notifier_call = intel_reboot_notifier;
> +	register_reboot_notifier(&dev_priv->reboot_notifier);
>  }
>  
>  static void intel_enable_pipe_a(struct drm_device *dev)
> @@ -16291,6 +16313,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  
> +	unregister_reboot_notifier(&dev_priv->reboot_notifier);
> +
>  	intel_disable_gt_powersave(dev_priv);
>  
>  	/*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 001f74fc0ce5..d8d13a9e33e5 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -28,8 +28,6 @@
>  #include <linux/i2c.h>
>  #include <linux/slab.h>
>  #include <linux/export.h>
> -#include <linux/notifier.h>
> -#include <linux/reboot.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
> @@ -631,42 +629,6 @@ _pp_stat_reg(struct intel_dp *intel_dp)
>  	return regs.pp_stat;
>  }
>  
> -/* Reboot notifier handler to shutdown panel power to guarantee T12 timing
> -   This function only applicable when panel PM state is not to be tracked */
> -static int edp_notify_handler(struct notifier_block *this, unsigned long code,
> -			      void *unused)
> -{
> -	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
> -						 edp_notifier);
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dev);
> -
> -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> -		return 0;
> -
> -	pps_lock(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> -		i915_reg_t pp_ctrl_reg, pp_div_reg;
> -		u32 pp_div;
> -
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> -		pp_div = I915_READ(pp_div_reg);
> -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> -
> -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> -		msleep(intel_dp->panel_power_cycle_delay);
> -	}
> -
> -	pps_unlock(intel_dp);
> -
> -	return 0;
> -}
> -
>  static bool edp_have_panel_power(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -4562,11 +4524,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  		pps_lock(intel_dp);
>  		edp_panel_vdd_off_sync(intel_dp);
>  		pps_unlock(intel_dp);
> -
> -		if (intel_dp->edp_notifier.notifier_call) {
> -			unregister_reboot_notifier(&intel_dp->edp_notifier);
> -			intel_dp->edp_notifier.notifier_call = NULL;
> -		}
>  	}
>  
>  	intel_dp_aux_fini(intel_dp);
> @@ -5465,9 +5422,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	mutex_unlock(&dev->mode_config.mutex);
>  
>  	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> -		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
> -		register_reboot_notifier(&intel_dp->edp_notifier);
> -
>  		/*
>  		 * Figure out the current pipe for the initial backlight setup.
>  		 * If the current pipe isn't valid, try the PPS pipe, and if that
> @@ -5488,7 +5442,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  			      pipe_name(pipe));
>  	}
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode,
> +			 intel_dp->panel_power_cycle_delay);
>  	intel_connector->panel.backlight.power = intel_edp_backlight_power;
>  	intel_panel_setup_backlight(connector, pipe);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 50cdc890d956..92fa66a02ca5 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -226,6 +226,7 @@ struct intel_panel {
>  	struct drm_display_mode *fixed_mode;
>  	struct drm_display_mode *downclock_mode;
>  	int fitting_mode;
> +	int reboot_power_cycle_delay;
>  
>  	/* backlight */
>  	struct {
> @@ -877,8 +878,6 @@ struct intel_dp {
>  	unsigned long last_backlight_off;
>  	ktime_t panel_power_off_time;
>  
> -	struct notifier_block edp_notifier;
> -
>  	/*
>  	 * Pipe whose power sequencer is currently locked into
>  	 * this port. Only relevant on VLV/CHV.
> @@ -1521,8 +1520,10 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
>  /* intel_panel.c */
>  int intel_panel_init(struct intel_panel *panel,
>  		     struct drm_display_mode *fixed_mode,
> -		     struct drm_display_mode *downclock_mode);
> +		     struct drm_display_mode *downclock_mode,
> +		     int reboot_power_cycle_delay);
>  void intel_panel_fini(struct intel_panel *panel);
> +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv);
>  void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
>  			    struct drm_display_mode *adjusted_mode);
>  void intel_pch_panel_fitting(struct intel_crtc *crtc,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> index de8e9fb51595..5b722ec23381 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -1596,7 +1596,8 @@ void intel_dsi_init(struct drm_device *dev)
>  	connector->display_info.width_mm = fixed_mode->width_mm;
>  	connector->display_info.height_mm = fixed_mode->height_mm;
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
> +			 intel_dsi->panel_pwr_cycle_delay);
>  	intel_panel_setup_backlight(connector, INVALID_PIPE);
>  
>  	intel_dsi_add_properties(intel_connector);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 47bdf9dad0d3..c2c9c922590c 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -547,7 +547,7 @@ void intel_dvo_init(struct drm_device *dev)
>  			 */
>  			intel_panel_init(&intel_connector->panel,
>  					 intel_dvo_get_current_mode(connector),
> -					 NULL);
> +					 NULL, 0);
>  			intel_dvo->panel_wants_dither = true;
>  		}
>  
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 49550470483e..07d7ac2c1520 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -1120,7 +1120,8 @@ void intel_lvds_init(struct drm_device *dev)
>  out:
>  	mutex_unlock(&dev->mode_config.mutex);
>  
> -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> +	/* FIXME fill in an accurate power cycle delay */
> +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode, 0);
>  	intel_panel_setup_backlight(connector, INVALID_PIPE);
>  
>  	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 96c65d77e886..fe57a743ad21 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1781,14 +1781,41 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
>  	}
>  }
>  
> +/*
> + * Make sure the power cycle delay is respected. The PPS
> + * does supposedly initiate a power cycle on reset, but it
> + * also resets the power cycle delay register value to the
> + * default value, and hence may not wait long enough if the
> + * firmware attempts to power up the panel immediately.
> + * Also eg. DSI doesn't use the PPS.
> + */
> +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = &dev_priv->drm;
> +	struct intel_connector *connector;
> +	int reboot_power_cycle_delay = 0;
> +
> +	for_each_intel_connector(dev, connector) {
> +		struct intel_panel *panel = &connector->panel;
> +
> +		reboot_power_cycle_delay = max(reboot_power_cycle_delay,
> +					       panel->reboot_power_cycle_delay);
> +	}
> +
> +	if (reboot_power_cycle_delay)
> +		msleep(reboot_power_cycle_delay);
> +}
> +
>  int intel_panel_init(struct intel_panel *panel,
>  		     struct drm_display_mode *fixed_mode,
> -		     struct drm_display_mode *downclock_mode)
> +		     struct drm_display_mode *downclock_mode,
> +		     int reboot_power_cycle_delay)
>  {
>  	intel_panel_init_backlight_funcs(panel);
>  
>  	panel->fixed_mode = fixed_mode;
>  	panel->downclock_mode = downclock_mode;
> +	panel->reboot_power_cycle_delay = reboot_power_cycle_delay;
>  
>  	return 0;
>  }
> -- 
> 2.7.4
> 
> _______________________________________________
> 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] 9+ messages in thread

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-06  8:09 ` Lukas Wunner
@ 2016-08-06  8:29   ` Chris Wilson
  2016-08-08 11:47     ` Dave Gordon
  0 siblings, 1 reply; 9+ messages in thread
From: Chris Wilson @ 2016-08-06  8:29 UTC (permalink / raw)
  To: Lukas Wunner; +Cc: intel-gfx, Paulo Zanoni

On Sat, Aug 06, 2016 at 10:09:16AM +0200, Lukas Wunner wrote:
> On Wed, Aug 03, 2016 at 04:36:18PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> > reboot the machine. After reboot, the monitor is somehow confused and
> > refuses to do the payload allocation:
> >  [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
> >  [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> > and thus we're left with a black screen until the monitor power is
> > toggled.
> > 
> > It seems that if we shut down things gracefully prior to rebooting, the
> > monitor doesn't get confused like this. So let's try to shut down all
> > the displays gracefully on reboot. The downside is that we will
> > introduce the reboot notifier to all the modesetl locks. So if there's
> > a locking bug around, we might not be able to reboot the machine
> > gracefully. sysrq reboot will still work though, as it will not
> > call the notifiers.
> 
> struct pci_driver has a ->shutdown hook which is currently not defined
> in i915_pci_driver. How about using that instead of reboot_notifier
> to avoid potential locking issues?

Interestingly that is also called prior to kexec. Doing a
i915_gem_suspend at that point I think would stop some of the GPU faults
we get across kexec.
-Chris

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-06  8:29   ` Chris Wilson
@ 2016-08-08 11:47     ` Dave Gordon
  2016-08-08 12:45       ` Ville Syrjälä
  0 siblings, 1 reply; 9+ messages in thread
From: Dave Gordon @ 2016-08-08 11:47 UTC (permalink / raw)
  To: intel-gfx

On 06/08/16 09:29, Chris Wilson wrote:
> On Sat, Aug 06, 2016 at 10:09:16AM +0200, Lukas Wunner wrote:
>> On Wed, Aug 03, 2016 at 04:36:18PM +0300, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
>>> reboot the machine. After reboot, the monitor is somehow confused and
>>> refuses to do the payload allocation:
>>>  [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
>>>  [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
>>> and thus we're left with a black screen until the monitor power is
>>> toggled.
>>>
>>> It seems that if we shut down things gracefully prior to rebooting, the
>>> monitor doesn't get confused like this. So let's try to shut down all
>>> the displays gracefully on reboot. The downside is that we will
>>> introduce the reboot notifier to all the modesetl locks. So if there's
>>> a locking bug around, we might not be able to reboot the machine
>>> gracefully. sysrq reboot will still work though, as it will not
>>> call the notifiers.
>>
>> struct pci_driver has a ->shutdown hook which is currently not defined
>> in i915_pci_driver. How about using that instead of reboot_notifier
>> to avoid potential locking issues?
>
> Interestingly that is also called prior to kexec. Doing a
> i915_gem_suspend at that point I think would stop some of the GPU faults
> we get across kexec.
> -Chris

Agreed; we've had issues with things such as the GuC being left running 
across kexec, which causes firmware load to fail cos it's write-once!
Doing a clean suspend before kexec would certainly help here.

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-08 11:47     ` Dave Gordon
@ 2016-08-08 12:45       ` Ville Syrjälä
  0 siblings, 0 replies; 9+ messages in thread
From: Ville Syrjälä @ 2016-08-08 12:45 UTC (permalink / raw)
  To: Dave Gordon; +Cc: intel-gfx

On Mon, Aug 08, 2016 at 12:47:09PM +0100, Dave Gordon wrote:
> On 06/08/16 09:29, Chris Wilson wrote:
> > On Sat, Aug 06, 2016 at 10:09:16AM +0200, Lukas Wunner wrote:
> >> On Wed, Aug 03, 2016 at 04:36:18PM +0300, ville.syrjala@linux.intel.com wrote:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> >>> reboot the machine. After reboot, the monitor is somehow confused and
> >>> refuses to do the payload allocation:
> >>>  [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
> >>>  [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> >>> and thus we're left with a black screen until the monitor power is
> >>> toggled.
> >>>
> >>> It seems that if we shut down things gracefully prior to rebooting, the
> >>> monitor doesn't get confused like this. So let's try to shut down all
> >>> the displays gracefully on reboot. The downside is that we will
> >>> introduce the reboot notifier to all the modesetl locks. So if there's
> >>> a locking bug around, we might not be able to reboot the machine
> >>> gracefully. sysrq reboot will still work though, as it will not
> >>> call the notifiers.
> >>
> >> struct pci_driver has a ->shutdown hook which is currently not defined
> >> in i915_pci_driver. How about using that instead of reboot_notifier
> >> to avoid potential locking issues?
> >
> > Interestingly that is also called prior to kexec. Doing a
> > i915_gem_suspend at that point I think would stop some of the GPU faults
> > we get across kexec.
> > -Chris
> 
> Agreed; we've had issues with things such as the GuC being left running 
> across kexec, which causes firmware load to fail cos it's write-once!
> Doing a clean suspend before kexec would certainly help here.

I also realized that even my display suspend is somewhat insufficient
as I didn't consider hpds, ->detect() etc. potentially turning on vdd
again. I thought I might have to start reworking the hpd disable to not
depend on intel_runtime_pm_disable_interrupts(), but if we're going to
want a full blown suspend anyway I might not bother.

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-05 22:45 ` [PATCH] " Clint Taylor
@ 2016-08-08 12:52   ` Ville Syrjälä
  2016-08-08 13:13     ` David Weinehall
  0 siblings, 1 reply; 9+ messages in thread
From: Ville Syrjälä @ 2016-08-08 12:52 UTC (permalink / raw)
  To: Clint Taylor; +Cc: intel-gfx, Paulo Zanoni

On Fri, Aug 05, 2016 at 03:45:19PM -0700, Clint Taylor wrote:
> On 08/03/2016 06:36 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> > reboot the machine. After reboot, the monitor is somehow confused and
> > refuses to do the payload allocation:
> >   [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
> >   [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> > and thus we're left with a black screen until the monitor power is
> > toggled.
> >
> > It seems that if we shut down things gracefully prior to rebooting, the
> > monitor doesn't get confused like this. So let's try to shut down all
> > the displays gracefully on reboot. The downside is that we will
> > introduce the reboot notifier to all the modesetl locks. So if there's
> > a locking bug around, we might not be able to reboot the machine
> > gracefully. sysrq reboot will still work though, as it will not
> > call the notifiers.
> >
> > While we do this, we can eliminate the eDP reboot notifier, which is
> > there to shut down the panel power and make sure the firmware won't
> > violate the panel power cycle delay post-reboot. Since we're now
> > shutting eDP down properly, we can mostly just rip out the eDP notifier.
> > We still need to do the panel power cycle wait though, as that would
> > normally get postponed until the next modeset. So let's move that part
> > into intel_panel so that other display types will get the same treatment
> > as a bonus.
> >
> > The Dell UP2414Q can often get even more confused, and sometimes what
> > you have to do is: switch to another input on the monitor, toggle the
> > monitor power, switch the input back to the original setting. And
> > sometimes it seems you just have to yank the power cable entirely. I'm
> > not sure if this reboot notifier might avoid some of these other
> > failure modes as well, but I'm pretty sure it can't hurt at least.
> >
> 
> While testing this change on SKL if 2 crtc's are enabled resume from 
> suspend is 500ms longer than a single crtc resume. Are we calling the 
> T12 msleep(500) for non eDP panels?

Seems unlikely, unless we misdetect DP as eDP. 500ms sure sounds a lot
for non-eDP though.

> 
> During testing VDD to the panel, the T12 panel timeout requirement is 
> being meet at >500ms during reboot and suspend/resume.
> 
> > Cc: Clint Taylor <clinton.a.taylor@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_drv.h      |  2 ++
> >   drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++++++
> >   drivers/gpu/drm/i915/intel_dp.c      | 49 ++----------------------------------
> >   drivers/gpu/drm/i915/intel_drv.h     |  7 +++---
> >   drivers/gpu/drm/i915/intel_dsi.c     |  3 ++-
> >   drivers/gpu/drm/i915/intel_dvo.c     |  2 +-
> >   drivers/gpu/drm/i915/intel_lvds.c    |  3 ++-
> >   drivers/gpu/drm/i915/intel_panel.c   | 29 ++++++++++++++++++++-
> >   8 files changed, 65 insertions(+), 54 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 65ada5d2f88c..f8eb8c7de007 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1727,6 +1727,8 @@ struct intel_wm_config {
> >   struct drm_i915_private {
> >   	struct drm_device drm;
> >
> > +	struct notifier_block reboot_notifier;
> > +
> >   	struct kmem_cache *objects;
> >   	struct kmem_cache *vmas;
> >   	struct kmem_cache *requests;
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index a8e8cc8dfae9..2192a21aa6c9 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -31,6 +31,8 @@
> >   #include <linux/kernel.h>
> >   #include <linux/slab.h>
> >   #include <linux/vgaarb.h>
> > +#include <linux/notifier.h>
> > +#include <linux/reboot.h>
> >   #include <drm/drm_edid.h>
> >   #include <drm/drmP.h>
> >   #include "intel_drv.h"
> > @@ -15578,6 +15580,23 @@ fail:
> >   	drm_modeset_acquire_fini(&ctx);
> >   }
> >
> > +
> > +static int intel_reboot_notifier(struct notifier_block *nb,
> > +				 unsigned long code, void *unused)
> > +{
> > +	struct drm_i915_private *dev_priv =
> > +		container_of(nb, typeof(*dev_priv), reboot_notifier);
> > +
> > +	if (code != SYS_RESTART)
> > +		return 0;
> > +
> > +	intel_display_suspend(&dev_priv->drm);
> > +
> 
> Need to check to make sure there is a panel before calling 
> intel_panel_reboot_notifier().
> 
> > +	intel_panel_reboot_notifier(dev_priv);
> > +
> > +	return 0;
> > +}
> > +
> >   void intel_modeset_init(struct drm_device *dev)
> >   {
> >   	struct drm_i915_private *dev_priv = to_i915(dev);
> > @@ -15706,6 +15725,9 @@ void intel_modeset_init(struct drm_device *dev)
> >   	 * since the watermark calculation done here will use pstate->fb.
> >   	 */
> >   	sanitize_watermarks(dev);
> > +
> > +	dev_priv->reboot_notifier.notifier_call = intel_reboot_notifier;
> > +	register_reboot_notifier(&dev_priv->reboot_notifier);
> >   }
> >
> >   static void intel_enable_pipe_a(struct drm_device *dev)
> > @@ -16291,6 +16313,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
> >   {
> >   	struct drm_i915_private *dev_priv = to_i915(dev);
> >
> > +	unregister_reboot_notifier(&dev_priv->reboot_notifier);
> > +
> >   	intel_disable_gt_powersave(dev_priv);
> >
> >   	/*
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 001f74fc0ce5..d8d13a9e33e5 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -28,8 +28,6 @@
> >   #include <linux/i2c.h>
> >   #include <linux/slab.h>
> >   #include <linux/export.h>
> > -#include <linux/notifier.h>
> > -#include <linux/reboot.h>
> >   #include <drm/drmP.h>
> >   #include <drm/drm_atomic_helper.h>
> >   #include <drm/drm_crtc.h>
> > @@ -631,42 +629,6 @@ _pp_stat_reg(struct intel_dp *intel_dp)
> >   	return regs.pp_stat;
> >   }
> >
> > -/* Reboot notifier handler to shutdown panel power to guarantee T12 timing
> > -   This function only applicable when panel PM state is not to be tracked */
> > -static int edp_notify_handler(struct notifier_block *this, unsigned long code,
> > -			      void *unused)
> > -{
> > -	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
> > -						 edp_notifier);
> > -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > -	struct drm_i915_private *dev_priv = to_i915(dev);
> > -
> > -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> > -		return 0;
> > -
> > -	pps_lock(intel_dp);
> > -
> > -	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> > -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> > -		i915_reg_t pp_ctrl_reg, pp_div_reg;
> > -		u32 pp_div;
> > -
> > -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> > -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> > -		pp_div = I915_READ(pp_div_reg);
> > -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> > -
> > -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> > -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> > -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> > -		msleep(intel_dp->panel_power_cycle_delay);
> > -	}
> > -
> > -	pps_unlock(intel_dp);
> > -
> > -	return 0;
> > -}
> > -
> >   static bool edp_have_panel_power(struct intel_dp *intel_dp)
> >   {
> >   	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> > @@ -4562,11 +4524,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
> >   		pps_lock(intel_dp);
> >   		edp_panel_vdd_off_sync(intel_dp);
> >   		pps_unlock(intel_dp);
> > -
> > -		if (intel_dp->edp_notifier.notifier_call) {
> > -			unregister_reboot_notifier(&intel_dp->edp_notifier);
> > -			intel_dp->edp_notifier.notifier_call = NULL;
> > -		}
> >   	}
> >
> >   	intel_dp_aux_fini(intel_dp);
> > @@ -5465,9 +5422,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >   	mutex_unlock(&dev->mode_config.mutex);
> >
> >   	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> > -		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
> > -		register_reboot_notifier(&intel_dp->edp_notifier);
> > -
> >   		/*
> >   		 * Figure out the current pipe for the initial backlight setup.
> >   		 * If the current pipe isn't valid, try the PPS pipe, and if that
> > @@ -5488,7 +5442,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >   			      pipe_name(pipe));
> >   	}
> >
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode,
> > +			 intel_dp->panel_power_cycle_delay);
> >   	intel_connector->panel.backlight.power = intel_edp_backlight_power;
> >   	intel_panel_setup_backlight(connector, pipe);
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 50cdc890d956..92fa66a02ca5 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -226,6 +226,7 @@ struct intel_panel {
> >   	struct drm_display_mode *fixed_mode;
> >   	struct drm_display_mode *downclock_mode;
> >   	int fitting_mode;
> > +	int reboot_power_cycle_delay;
> >
> >   	/* backlight */
> >   	struct {
> > @@ -877,8 +878,6 @@ struct intel_dp {
> >   	unsigned long last_backlight_off;
> >   	ktime_t panel_power_off_time;
> >
> > -	struct notifier_block edp_notifier;
> > -
> >   	/*
> >   	 * Pipe whose power sequencer is currently locked into
> >   	 * this port. Only relevant on VLV/CHV.
> > @@ -1521,8 +1520,10 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
> >   /* intel_panel.c */
> >   int intel_panel_init(struct intel_panel *panel,
> >   		     struct drm_display_mode *fixed_mode,
> > -		     struct drm_display_mode *downclock_mode);
> > +		     struct drm_display_mode *downclock_mode,
> > +		     int reboot_power_cycle_delay);
> >   void intel_panel_fini(struct intel_panel *panel);
> > +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv);
> >   void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
> >   			    struct drm_display_mode *adjusted_mode);
> >   void intel_pch_panel_fitting(struct intel_crtc *crtc,
> > diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> > index de8e9fb51595..5b722ec23381 100644
> > --- a/drivers/gpu/drm/i915/intel_dsi.c
> > +++ b/drivers/gpu/drm/i915/intel_dsi.c
> > @@ -1596,7 +1596,8 @@ void intel_dsi_init(struct drm_device *dev)
> >   	connector->display_info.width_mm = fixed_mode->width_mm;
> >   	connector->display_info.height_mm = fixed_mode->height_mm;
> >
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
> > +			 intel_dsi->panel_pwr_cycle_delay);
> >   	intel_panel_setup_backlight(connector, INVALID_PIPE);
> >
> >   	intel_dsi_add_properties(intel_connector);
> > diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> > index 47bdf9dad0d3..c2c9c922590c 100644
> > --- a/drivers/gpu/drm/i915/intel_dvo.c
> > +++ b/drivers/gpu/drm/i915/intel_dvo.c
> > @@ -547,7 +547,7 @@ void intel_dvo_init(struct drm_device *dev)
> >   			 */
> >   			intel_panel_init(&intel_connector->panel,
> >   					 intel_dvo_get_current_mode(connector),
> > -					 NULL);
> > +					 NULL, 0);
> >   			intel_dvo->panel_wants_dither = true;
> >   		}
> >
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index 49550470483e..07d7ac2c1520 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -1120,7 +1120,8 @@ void intel_lvds_init(struct drm_device *dev)
> >   out:
> >   	mutex_unlock(&dev->mode_config.mutex);
> >
> > -	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> > +	/* FIXME fill in an accurate power cycle delay */
> > +	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode, 0);
> >   	intel_panel_setup_backlight(connector, INVALID_PIPE);
> >
> >   	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > index 96c65d77e886..fe57a743ad21 100644
> > --- a/drivers/gpu/drm/i915/intel_panel.c
> > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > @@ -1781,14 +1781,41 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
> >   	}
> >   }
> >
> > +/*
> > + * Make sure the power cycle delay is respected. The PPS
> > + * does supposedly initiate a power cycle on reset, but it
> > + * also resets the power cycle delay register value to the
> > + * default value, and hence may not wait long enough if the
> > + * firmware attempts to power up the panel immediately.
> > + * Also eg. DSI doesn't use the PPS.
> > + */
> > +void intel_panel_reboot_notifier(struct drm_i915_private *dev_priv)
> > +{
> > +	struct drm_device *dev = &dev_priv->drm;
> > +	struct intel_connector *connector;
> > +	int reboot_power_cycle_delay = 0;
> > +
> > +	for_each_intel_connector(dev, connector) {
> > +		struct intel_panel *panel = &connector->panel;
> > +
> > +		reboot_power_cycle_delay = max(reboot_power_cycle_delay,
> > +					       panel->reboot_power_cycle_delay);
> > +	}
> > +
> > +	if (reboot_power_cycle_delay)
> > +		msleep(reboot_power_cycle_delay);
> > +}
> > +
> >   int intel_panel_init(struct intel_panel *panel,
> >   		     struct drm_display_mode *fixed_mode,
> > -		     struct drm_display_mode *downclock_mode)
> > +		     struct drm_display_mode *downclock_mode,
> > +		     int reboot_power_cycle_delay)
> >   {
> >   	intel_panel_init_backlight_funcs(panel);
> >
> >   	panel->fixed_mode = fixed_mode;
> >   	panel->downclock_mode = downclock_mode;
> > +	panel->reboot_power_cycle_delay = reboot_power_cycle_delay;
> >
> >   	return 0;
> >   }
> >

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

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

* Re: [PATCH] drm/i915: Shut down displays gracefully on reboot
  2016-08-08 12:52   ` Ville Syrjälä
@ 2016-08-08 13:13     ` David Weinehall
  0 siblings, 0 replies; 9+ messages in thread
From: David Weinehall @ 2016-08-08 13:13 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Paulo Zanoni

On Mon, Aug 08, 2016 at 03:52:41PM +0300, Ville Syrjälä wrote:
> On Fri, Aug 05, 2016 at 03:45:19PM -0700, Clint Taylor wrote:
> > On 08/03/2016 06:36 AM, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > Dell UP2414Q doesn't like it when we're driving it in MST mode, and then
> > > reboot the machine. After reboot, the monitor is somehow confused and
> > > refuses to do the payload allocation:
> > >   [drm:drm_dp_mst_allocate_vcpi] initing vcpi for 282 8
> > >   [drm:drm_dp_dpcd_write_payload] status not set after read payload table status 0
> > > and thus we're left with a black screen until the monitor power is
> > > toggled.
> > >
> > > It seems that if we shut down things gracefully prior to rebooting, the
> > > monitor doesn't get confused like this. So let's try to shut down all
> > > the displays gracefully on reboot. The downside is that we will
> > > introduce the reboot notifier to all the modesetl locks. So if there's
> > > a locking bug around, we might not be able to reboot the machine
> > > gracefully. sysrq reboot will still work though, as it will not
> > > call the notifiers.
> > >
> > > While we do this, we can eliminate the eDP reboot notifier, which is
> > > there to shut down the panel power and make sure the firmware won't
> > > violate the panel power cycle delay post-reboot. Since we're now
> > > shutting eDP down properly, we can mostly just rip out the eDP notifier.
> > > We still need to do the panel power cycle wait though, as that would
> > > normally get postponed until the next modeset. So let's move that part
> > > into intel_panel so that other display types will get the same treatment
> > > as a bonus.
> > >
> > > The Dell UP2414Q can often get even more confused, and sometimes what
> > > you have to do is: switch to another input on the monitor, toggle the
> > > monitor power, switch the input back to the original setting. And
> > > sometimes it seems you just have to yank the power cable entirely. I'm
> > > not sure if this reboot notifier might avoid some of these other
> > > failure modes as well, but I'm pretty sure it can't hurt at least.
> > >
> > 
> > While testing this change on SKL if 2 crtc's are enabled resume from 
> > suspend is 500ms longer than a single crtc resume. Are we calling the 
> > T12 msleep(500) for non eDP panels?
> 
> Seems unlikely, unless we misdetect DP as eDP. 500ms sure sounds a lot
> for non-eDP though.

You can try this patch to get easy access to the timings to see if
they seem reasonable:


commit 7e88e096931065efebd43d844fe3bf106932a9fa
Author: David Weinehall <david.weinehall@linux.intel.com>
Date:   Thu Jul 21 13:36:49 2016 +0300

    drm/i915/debugfs: Add panel delays for eDP
    
    The eDP backlight and panel enable/disable delays are quite
    useful to know when measuring time consumed by suspend/resume,
    and while the information are printed to the kernel log as debug
    messages, having this information in debugfs makes things easier.
    
    Signed-off-by: David Weinehall <david.weinehall@linux.intel.com>

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e726b02bdb5a..282d6716d012 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -5544,6 +5544,40 @@ static const struct file_operations i915_dpcd_fops = {
 	.release = single_release,
 };
 
+static int i915_panel_show(struct seq_file *m, void *data)
+{
+	struct drm_connector *connector = m->private;
+	struct intel_dp *intel_dp =
+		enc_to_intel_dp(&intel_attached_encoder(connector)->base);
+
+	if (connector->status != connector_status_connected)
+		return -ENODEV;
+
+	seq_printf(m, "Panel power up delay: %d\n",
+		   intel_dp->panel_power_up_delay);
+	seq_printf(m, "Panel power down delay: %d\n",
+		   intel_dp->panel_power_down_delay);
+	seq_printf(m, "Backlight on delay: %d\n",
+		   intel_dp->backlight_on_delay);
+	seq_printf(m, "Backlight off delay: %d\n",
+		   intel_dp->backlight_off_delay);
+
+	return 0;
+}
+
+static int i915_panel_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, i915_panel_show, inode->i_private);
+}
+
+static const struct file_operations i915_panel_fops = {
+	.owner = THIS_MODULE,
+	.open = i915_panel_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 /**
  * i915_debugfs_connector_add - add i915 specific connector debugfs files
  * @connector: pointer to a registered drm_connector
@@ -5563,8 +5597,12 @@ int i915_debugfs_connector_add(struct drm_connector *connector)
 
 	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
 	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-		debugfs_create_file("i915_dpcd", S_IRUGO, root, connector,
-				    &i915_dpcd_fops);
+		debugfs_create_file("i915_dpcd", S_IRUGO, root,
+				    connector, &i915_dpcd_fops);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		debugfs_create_file("i915_panel_timings", S_IRUGO, root,
+				    connector, &i915_panel_fops);
 
 	return 0;
 }
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-03 13:36 [PATCH] drm/i915: Shut down displays gracefully on reboot ville.syrjala
2016-08-03 13:59 ` ✗ Ro.CI.BAT: failure for " Patchwork
2016-08-05 22:45 ` [PATCH] " Clint Taylor
2016-08-08 12:52   ` Ville Syrjälä
2016-08-08 13:13     ` David Weinehall
2016-08-06  8:09 ` Lukas Wunner
2016-08-06  8:29   ` Chris Wilson
2016-08-08 11:47     ` Dave Gordon
2016-08-08 12:45       ` Ville Syrjälä

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