All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/25] vlv: add support for RPM
@ 2014-04-14 17:24 Imre Deak
  2014-04-14 17:24 ` [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros Imre Deak
                   ` (26 more replies)
  0 siblings, 27 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

For a description of this patchset see the previous cover letter [1].

Tested on HSW (non-ULT), VLV with igt/kms_flip and pm_pc8.

v2:
- addressed comments about getting the proper runtime PM references in
  debugfs (Daniel, Paulo, Ville)
- disable RPM if RC6 is disabled for all platforms, not just VLV
  (Daniel)
- refactored the runtime PM callbacks pulling platform independent
  teardown/re-init code to the generic runtime suspend/resume callbacks
  (Daniel)
- fixed a couple of issues I bumped into while checking the RC6/RPS
  and the GPU reset error capturing path

[1]
http://lists.freedesktop.org/archives/intel-gfx/2014-April/043208.html

Imre Deak (25):
  drm/i915: vlv: clean up GTLC wake control/status register macros
  drm/i915: vlv: clear master interrupt flag when disabling interrupts
  drm/i915: vlv: add RC6 residency counters
  drm/i915: fix the RC6 status debug print
  drm/i915: remove the i915_dpio debugfs entry
  drm/i915: get a runtime PM ref for debugfs entries where needed
  drm/i915: move getting struct_mutex lower in the callstack during GPU
    reset
  drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  drm/i915: get a runtime PM ref for the deferred GPU reset work
  drm/i915: gen2: move error capture of IER to its correct place
  drm/i915: add missing error capturing of the PIPESTAT reg
  drm/i915: vlv: check port power domain instead of only D0 for eDP VDD
    on
  drm/i915: fix unbalanced GT powersave enable / disable calls
  drm/i915: sanitize enable_rc6 option
  drm/i915: disable runtime PM if RC6 is disabled
  drm/i915: make runtime PM interrupt enable/disable platform
    independent
  drm/i915: factor out gen6_update_ring_freq
  drm/i915: make runtime PM swizzling/ring_freq init platform
    independent
  drm/i915: reinit GT power save during resume
  drm/i915: vlv: setup RPS min/max frequencies once during init time
  drm/i915: vlv: factor out vlv_force_gfx_clock
  drm/i915: vlv: increase timeout when forcing on the GFX clock
  drm/i915: add various missing GTI/Gunit register definitions
  drm/i915: propagate the error code from runtime PM callbacks
  drm/i915: vlv: add runtime PM support

 drivers/gpu/drm/i915/i915_debugfs.c   |  63 ++---
 drivers/gpu/drm/i915/i915_dma.c       |   8 +-
 drivers/gpu/drm/i915/i915_drv.c       | 452 +++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h       |  64 ++++-
 drivers/gpu/drm/i915/i915_gem.c       |   5 +-
 drivers/gpu/drm/i915/i915_gpu_error.c |  11 +-
 drivers/gpu/drm/i915/i915_irq.c       |  23 +-
 drivers/gpu/drm/i915/i915_reg.h       |  56 ++++-
 drivers/gpu/drm/i915/i915_sysfs.c     |   4 +
 drivers/gpu/drm/i915/intel_display.c  |   9 +-
 drivers/gpu/drm/i915/intel_dp.c       |   6 +-
 drivers/gpu/drm/i915/intel_drv.h      |   2 +
 drivers/gpu/drm/i915/intel_pm.c       | 185 ++++++++++----
 13 files changed, 737 insertions(+), 151 deletions(-)

-- 
1.8.4

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

* [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-24 21:04   ` Rodrigo Vivi
  2014-04-14 17:24 ` [PATCH v2 02/25] drm/i915: vlv: clear master interrupt flag when disabling interrupts Imre Deak
                   ` (25 subsequent siblings)
  26 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

These will be needed by the upcoming VLV RPM helpers.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c |  5 +++--
 drivers/gpu/drm/i915/i915_reg.h | 10 ++++++++--
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 8f5ffab..af8493a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4459,8 +4459,9 @@ int i915_gem_init(struct drm_device *dev)
 
 	if (IS_VALLEYVIEW(dev)) {
 		/* VLVA0 (potential hack), BIOS isn't actually waking us */
-		I915_WRITE(VLV_GTLC_WAKE_CTRL, 1);
-		if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) & 1) == 1, 10))
+		I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
+		if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
+			      VLV_GTLC_ALLOWWAKEACK), 10))
 			DRM_DEBUG_DRIVER("allow wake ack timed out\n");
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8f84555..ee768f0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4996,9 +4996,15 @@ enum punit_power_well {
 #define  FORCEWAKE_ACK_HSW			0x130044
 #define  FORCEWAKE_ACK				0x130090
 #define  VLV_GTLC_WAKE_CTRL			0x130090
+#define   VLV_GTLC_RENDER_CTX_EXISTS		(1 << 25)
+#define   VLV_GTLC_MEDIA_CTX_EXISTS		(1 << 24)
+#define   VLV_GTLC_ALLOWWAKEREQ			(1 << 0)
+
 #define  VLV_GTLC_PW_STATUS			0x130094
-#define VLV_GTLC_PW_RENDER_STATUS_MASK		0x80
-#define VLV_GTLC_PW_MEDIA_STATUS_MASK		0x20
+#define   VLV_GTLC_ALLOWWAKEACK			(1 << 0)
+#define   VLV_GTLC_ALLOWWAKEERR			(1 << 1)
+#define   VLV_GTLC_PW_MEDIA_STATUS_MASK		(1 << 5)
+#define   VLV_GTLC_PW_RENDER_STATUS_MASK	(1 << 7)
 #define  FORCEWAKE_MT				0xa188 /* multi-threaded */
 #define   FORCEWAKE_KERNEL			0x1
 #define   FORCEWAKE_USER			0x2
-- 
1.8.4

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

* [PATCH v2 02/25] drm/i915: vlv: clear master interrupt flag when disabling interrupts
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
  2014-04-14 17:24 ` [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 03/25] drm/i915: vlv: add RC6 residency counters Imre Deak
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Not clearing this flag causes spurious interrupts at least in D3 state,
so before enabling RPM we need to fix this. We were already setting this
flag when enabling interrupts, only clearing it was missing.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7a4d3ae..a651d0d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3305,6 +3305,8 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
 	if (!dev_priv)
 		return;
 
+	I915_WRITE(VLV_MASTER_IER, 0);
+
 	intel_hpd_irq_uninstall(dev_priv);
 
 	for_each_pipe(pipe)
-- 
1.8.4

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

* [PATCH v2 03/25] drm/i915: vlv: add RC6 residency counters
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
  2014-04-14 17:24 ` [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros Imre Deak
  2014-04-14 17:24 ` [PATCH v2 02/25] drm/i915: vlv: clear master interrupt flag when disabling interrupts Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 04/25] drm/i915: fix the RC6 status debug print Imre Deak
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 5 +++++
 drivers/gpu/drm/i915/i915_reg.h     | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 1e83ae4..02f1b39 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1261,6 +1261,11 @@ static int vlv_drpc_info(struct seq_file *m)
 			(I915_READ(VLV_GTLC_PW_STATUS) &
 				VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
 
+	seq_printf(m, "Render RC6 residency since boot: %u\n",
+		   I915_READ(VLV_GT_RENDER_RC6));
+	seq_printf(m, "Media RC6 residency since boot: %u\n",
+		   I915_READ(VLV_GT_MEDIA_RC6));
+
 	spin_lock_irq(&dev_priv->uncore.lock);
 	fw_rendercount = dev_priv->uncore.fw_rendercount;
 	fw_mediacount = dev_priv->uncore.fw_mediacount;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ee768f0..f183746 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5136,6 +5136,9 @@ enum punit_power_well {
 #define   VLV_MEDIA_RC6_COUNT_EN		(1<<1)
 #define   VLV_RENDER_RC6_COUNT_EN		(1<<0)
 #define GEN6_GT_GFX_RC6				0x138108
+#define VLV_GT_RENDER_RC6			0x138108
+#define VLV_GT_MEDIA_RC6			0x13810C
+
 #define GEN6_GT_GFX_RC6p			0x13810C
 #define GEN6_GT_GFX_RC6pp			0x138110
 
-- 
1.8.4

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

* [PATCH v2 04/25] drm/i915: fix the RC6 status debug print
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (2 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 03/25] drm/i915: vlv: add RC6 residency counters Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 05/25] drm/i915: remove the i915_dpio debugfs entry Imre Deak
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

The parsing was incorrect for ILK and VLV.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 75c1c76..4ebb93c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3250,6 +3250,12 @@ static void valleyview_disable_rps(struct drm_device *dev)
 
 static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 {
+	if (IS_VALLEYVIEW(dev)) {
+		if (mode & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1)))
+			mode = GEN6_RC_CTL_RC6_ENABLE;
+		else
+			mode = 0;
+	}
 	DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
 		 (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
 		 (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
@@ -3876,7 +3882,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 	I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN);
 	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
 
-	intel_print_rc6_info(dev, INTEL_RC6_ENABLE);
+	intel_print_rc6_info(dev, GEN6_RC_CTL_RC6_ENABLE);
 }
 
 static unsigned long intel_pxfreq(u32 vidfreq)
-- 
1.8.4

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

* [PATCH v2 05/25] drm/i915: remove the i915_dpio debugfs entry
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (3 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 04/25] drm/i915: fix the RC6 status debug print Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 06/25] drm/i915: get a runtime PM ref for debugfs entries where needed Imre Deak
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

There are igt tools that can read/write the DPIO registers, so having a
debugfs entry for only some of those registers is somewhat arbitrary /
redundant. Remove it.

v2:
- instead of fixing the entry by taking a power domain reference around
  the register accesses, remove the entry (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 48 -------------------------------------
 1 file changed, 48 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 02f1b39..4c785a2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1903,53 +1903,6 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 	return 0;
 }
 
-static int i915_dpio_info(struct seq_file *m, void *data)
-{
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
-
-
-	if (!IS_VALLEYVIEW(dev)) {
-		seq_puts(m, "unsupported\n");
-		return 0;
-	}
-
-	ret = mutex_lock_interruptible(&dev_priv->dpio_lock);
-	if (ret)
-		return ret;
-
-	seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
-
-	seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0)));
-	seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1)));
-
-	seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0)));
-	seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1)));
-
-	seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0)));
-	seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1)));
-
-	seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0)));
-	seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1)));
-
-	seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
-		   vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0));
-
-	mutex_unlock(&dev_priv->dpio_lock);
-
-	return 0;
-}
-
 static int i915_llc(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -3808,7 +3761,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
-	{"i915_dpio", i915_dpio_info, 0},
 	{"i915_llc", i915_llc, 0},
 	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
-- 
1.8.4

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

* [PATCH v2 06/25] drm/i915: get a runtime PM ref for debugfs entries where needed
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (4 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 05/25] drm/i915: remove the i915_dpio debugfs entry Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 07/25] drm/i915: move getting struct_mutex lower in the callstack during GPU reset Imre Deak
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

These debugfs entries access registers that need the D0 power state so
get an RPM ref for them.

v2:
- for all these entries we only need D0 state, so get only an RPM ref,
  not a power domain ref (Daniel, Paulo)
- the dpio entry is not an issue any more as it got removed (Ville)
- restore commit message from v1 (Paulo)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 10 ++++++++++
 drivers/gpu/drm/i915/i915_sysfs.c   |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 4c785a2..cad175c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1239,9 +1239,13 @@ static int vlv_drpc_info(struct seq_file *m)
 	u32 rpmodectl1, rcctl1;
 	unsigned fw_rendercount = 0, fw_mediacount = 0;
 
+	intel_runtime_pm_get(dev_priv);
+
 	rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
 	rcctl1 = I915_READ(GEN6_RC_CONTROL);
 
+	intel_runtime_pm_put(dev_priv);
+
 	seq_printf(m, "Video Turbo Mode: %s\n",
 		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
 	seq_printf(m, "Turbo enabled: %s\n",
@@ -3257,9 +3261,15 @@ static int
 i915_wedged_set(void *data, u64 val)
 {
 	struct drm_device *dev = data;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	intel_runtime_pm_get(dev_priv);
 
 	i915_handle_error(dev, val,
 			  "Manually setting wedged to %llu", val);
+
+	intel_runtime_pm_put(dev_priv);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 9c57029..3620997 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -263,6 +263,8 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
+	intel_runtime_pm_get(dev_priv);
+
 	mutex_lock(&dev_priv->rps.hw_lock);
 	if (IS_VALLEYVIEW(dev_priv->dev)) {
 		u32 freq;
@@ -273,6 +275,8 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	intel_runtime_pm_put(dev_priv);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
-- 
1.8.4

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

* [PATCH v2 07/25] drm/i915: move getting struct_mutex lower in the callstack during GPU reset
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (5 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 06/25] drm/i915: get a runtime PM ref for debugfs entries where needed Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling Imre Deak
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Getting struct_mutex around the whole intel_enable_gt_powersave()
function is not necessary, since it's only needed for the ILK path
therein.

This will make intel_enable_gt_powersave() useable on the RPM resume
path for >=GEN6 (added in an upcoming patch to reset the RPS state
during RPM resume), where we can't (and need not) get this mutex.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 5 +----
 drivers/gpu/drm/i915/intel_pm.c | 2 ++
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 5d8250f..a821608 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -753,11 +753,8 @@ int i915_reset(struct drm_device *dev)
 		 * reset and the re-install of drm irq. Skip for ironlake per
 		 * previous concerns that it doesn't respond well to some forms
 		 * of re-init after reset. */
-		if (INTEL_INFO(dev)->gen > 5) {
-			mutex_lock(&dev->struct_mutex);
+		if (INTEL_INFO(dev)->gen > 5)
 			intel_enable_gt_powersave(dev);
-			mutex_unlock(&dev->struct_mutex);
-		}
 
 		intel_hpd_init(dev);
 	} else {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 4ebb93c..e5b9f08 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4556,9 +4556,11 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (IS_IRONLAKE_M(dev)) {
+		mutex_lock(&dev->struct_mutex);
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
+		mutex_unlock(&dev->struct_mutex);
 	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		/*
 		 * PCU communication is slow and this doesn't need to be
-- 
1.8.4

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

* [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (6 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 07/25] drm/i915: move getting struct_mutex lower in the callstack during GPU reset Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-25  7:59   ` Daniel Vetter
  2014-04-25  8:01   ` Daniel Vetter
  2014-04-14 17:24 ` [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
                   ` (18 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

At least on VLV but probably on other platforms too we depend on RC6
being enabled for RPM, so disable RPM until the delayed RC6 enabling
completes.

v2:
- explain the reason for the _noresume version of RPM get (Daniel)
- use the simpler 'if (schedule_work()) rpm_get();' instead of
  'if (!cancel_work_sync()) rpm_get(); schedule_work();'

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c  |  5 ++++-
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_pm.c  | 34 ++++++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a821608..a20d2d1 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -754,7 +754,7 @@ int i915_reset(struct drm_device *dev)
 		 * previous concerns that it doesn't respond well to some forms
 		 * of re-init after reset. */
 		if (INTEL_INFO(dev)->gen > 5)
-			intel_enable_gt_powersave(dev);
+			intel_reset_gt_powersave(dev);
 
 		intel_hpd_init(dev);
 	} else {
@@ -923,6 +923,9 @@ static int intel_runtime_suspend(struct device *device)
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
+		return -ENODEV;
+
 	WARN_ON(!HAS_RUNTIME_PM(dev));
 	assert_force_wake_inactive(dev_priv);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c551472..618d05a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -924,6 +924,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
 void intel_cleanup_gt_powersave(struct drm_device *dev);
 void intel_enable_gt_powersave(struct drm_device *dev);
 void intel_disable_gt_powersave(struct drm_device *dev);
+void intel_reset_gt_powersave(struct drm_device *dev);
 void ironlake_teardown_rc6(struct drm_device *dev);
 void gen6_update_ring_freq(struct drm_device *dev);
 void gen6_rps_idle(struct drm_i915_private *dev_priv);
@@ -931,6 +932,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
 void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e5b9f08..0e8b263 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4549,6 +4549,8 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 	}
 	dev_priv->rps.enabled = true;
 	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 void intel_enable_gt_powersave(struct drm_device *dev)
@@ -4566,12 +4568,28 @@ void intel_enable_gt_powersave(struct drm_device *dev)
 		 * PCU communication is slow and this doesn't need to be
 		 * done at any specific time, so do this out of our fast path
 		 * to make resume and init faster.
+		 *
+		 * We depend on the HW RC6 power context save/restore
+		 * mechanism when entering D3 through runtime PM suspend. So
+		 * disable RPM until RPS/RC6 is properly setup. We can only
+		 * get here via the driver load/system resume/runtime resume
+		 * paths, so the _noresume version is enough (and in case of
+		 * runtime resume it's necessary).
 		 */
-		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
-				      round_jiffies_up_relative(HZ));
+		if (schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
+					   round_jiffies_up_relative(HZ)))
+			intel_runtime_pm_get_noresume(dev_priv);
 	}
 }
 
+void intel_reset_gt_powersave(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->rps.enabled = false;
+	intel_enable_gt_powersave(dev);
+}
+
 static void ibx_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6025,6 +6043,18 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
 	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
 }
 
+void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
+	pm_runtime_get_noresume(device);
+}
+
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
-- 
1.8.4

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

* [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (7 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 12:11   ` Ville Syrjälä
  2014-04-18 12:47   ` [PATCH v3] " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place Imre Deak
                   ` (17 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Atm we can end up in the GPU reset deferred work in D3 state if the last
runtime PM reference is dropped between detecting a hang/scheduling the
work and executing the work. At least one such case I could trigger is
the simulated reset via the i915_wedged debugfs entry. Fix this by
disabling RPM before scheduling the work until the end of the work.

v2:
- Instead of getting/putting the RPM reference in the reset work itself,
  get it already before scheduling the work. By this we also prevent
  going to D3 before the work gets to run, in addition to making sure
  that we run the work itself in D0. (Ville, Daniel)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
 drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 0b38f88..6398280 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
 
 	/* Free error state after interrupts are fully disabled. */
 	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
-	cancel_work_sync(&dev_priv->gpu_error.work);
+	if (!cancel_work_sync(&dev_priv->gpu_error.work))
+		/*
+		 * The following won't make any difference in the PM state,
+		 * since RPM is disabled already, but do it still for
+		 * consistency.
+		 */
+		intel_runtime_pm_put(dev_priv);
 	i915_destroy_error_state(dev);
 
 	if (dev->pdev->msi_enabled)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a651d0d..5e079d8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
 		 */
 		i915_error_wake_up(dev_priv, true);
 	}
+
+	/* Drop the ref we took when scheduling this work. */
+	intel_runtime_pm_put(dev_priv);
 }
 
 static void i915_report_and_clear_eir(struct drm_device *dev)
@@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
 	 * state of outstanding pagelips). Hence it must not be run on our own
 	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
 	 * code will deadlock.
+	 *
+	 * It's guaranteed that here we are in D0 state, since we can only get
+	 * here via one of the following paths:
+	 * - From an IRQ handler's error detection. -> The driver must make
+	 *   sure that IRQs are unmasked only while holding an RPM ref.
+	 * - From hang-check due to a blocked request. -> The request holds an
+	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
+	 *   won't be called until the request is finished.
+	 * - From hang-check due to a flip hang. -> We have an RPM ref because
+	 *   of the active modeset.
+	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
+	 *   RPM ref.
+	 * Take here an atomic RPM ref still to make sure that we don't
+	 * re-enter D3 until the error work gets to run and completes the
+	 * reset.
 	 */
-	schedule_work(&dev_priv->gpu_error.work);
+	if (schedule_work(&dev_priv->gpu_error.work))
+		intel_runtime_pm_get_noresume(dev_priv);
 }
 
 static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
-- 
1.8.4

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

* [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (8 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 12:22   ` Ville Syrjälä
  2014-04-14 17:24 ` [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg Imre Deak
                   ` (16 subsequent siblings)
  26 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

While checking the error capture path I noticed that this register is
read twice for GEN2, so fix this and also move the read where it's done
for other platforms.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 4865ade..ba79b59 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1053,9 +1053,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 		error->gfx_mode = I915_READ(GFX_MODE);
 	}
 
-	if (IS_GEN2(dev))
-		error->ier = I915_READ16(IER);
-
 	/* 2: Registers which belong to multiple generations */
 	if (INTEL_INFO(dev)->gen >= 7)
 		error->forcewake = I915_READ(FORCEWAKE_MT);
@@ -1079,7 +1076,10 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 	if (HAS_PCH_SPLIT(dev))
 		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
 	else {
-		error->ier = I915_READ(IER);
+		if (IS_GEN2(dev))
+			error->ier = I915_READ16(IER);
+		else
+			error->ier = I915_READ(IER);
 		for_each_pipe(pipe)
 			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 	}
-- 
1.8.4

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

* [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (9 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 12:17   ` Ville Syrjälä
  2014-04-18 12:55   ` [PATCH v3 " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 12/25] drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on Imre Deak
                   ` (15 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

While checking the error capture path I noticed that we lacked the
power domain-on check for PIPESTAT so fix this by moving that to where
the rest of pipe registers are captured.

The move also revealed that we actually don't include this register in
the error report, so fix that too.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h       | 1 -
 drivers/gpu/drm/i915/i915_gpu_error.c | 3 ---
 drivers/gpu/drm/i915/intel_display.c  | 3 +++
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d6acb4..5254f4b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -325,7 +325,6 @@ struct drm_i915_error_state {
 	u32 gab_ctl;
 	u32 gfx_mode;
 	u32 extra_instdone[I915_NUM_INSTDONE_REG];
-	u32 pipestat[I915_MAX_PIPES];
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index ba79b59..7b5cc08 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1028,7 +1028,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 				   struct drm_i915_error_state *error)
 {
 	struct drm_device *dev = dev_priv->dev;
-	int pipe;
 
 	/* General organization
 	 * 1. Registers specific to a single generation
@@ -1080,8 +1079,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 			error->ier = I915_READ16(IER);
 		else
 			error->ier = I915_READ(IER);
-		for_each_pipe(pipe)
-			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 	}
 
 	/* 4: Everything else */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1390ab5..4d8d875 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11925,6 +11925,7 @@ struct intel_display_error_state {
 	struct intel_pipe_error_state {
 		bool power_domain_on;
 		u32 source;
+		u32 stat;
 	} pipe[I915_MAX_PIPES];
 
 	struct intel_plane_error_state {
@@ -12006,6 +12007,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 		}
 
 		error->pipe[i].source = I915_READ(PIPESRC(i));
+		error->pipe[i].stat = I915_READ(PIPESTAT(i));
 	}
 
 	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
@@ -12056,6 +12058,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 		err_printf(m, "  Power: %s\n",
 			   error->pipe[i].power_domain_on ? "on" : "off");
 		err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
+		err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
 
 		err_printf(m, "Plane [%d]:\n", i);
 		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
-- 
1.8.4

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

* [PATCH v2 12/25] drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (10 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 13/25] drm/i915: fix unbalanced GT powersave enable / disable calls Imre Deak
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Some platforms need additional power domains to be on in addition to the
device D0 state to access the panel registers.

Suggested by Daniel.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76987
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b50b170..d283ce2 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -313,8 +313,12 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	enum intel_display_power_domain power_domain;
 
-	return !dev_priv->pm.suspended &&
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	return intel_display_power_enabled(dev_priv, power_domain) &&
 	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
 }
 
-- 
1.8.4

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

* [PATCH v2 13/25] drm/i915: fix unbalanced GT powersave enable / disable calls
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (11 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 12/25] drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option Imre Deak
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Atm, we call intel_gt_powersave_enable() for GEN6 and GEN7 but disable
it for everything starting from GEN6. This is a problem in case of BDW.
Since I don't have a BDW to test if RC6 works properly, just keep it
disabled for now and fix only the disable function.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0e8b263..a56f6b1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4516,7 +4516,7 @@ void intel_disable_gt_powersave(struct drm_device *dev)
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
-	} else if (INTEL_INFO(dev)->gen >= 6) {
+	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
 		cancel_work_sync(&dev_priv->rps.work);
 		mutex_lock(&dev_priv->rps.hw_lock);
-- 
1.8.4

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

* [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (12 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 13/25] drm/i915: fix unbalanced GT powersave enable / disable calls Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 12:28   ` Ville Syrjälä
  2014-04-18 13:01   ` [PATCH v3 " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 15/25] drm/i915: disable runtime PM if RC6 is disabled Imre Deak
                   ` (12 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Atm, an invalid enable_rc6 module option will be silently ignored, so
emit an info message about it. Doing an early sanitization we can also
reuse intel_enable_rc6() in a follow-up patch to see if RC6 is actually
enabled. Currently the caller would have to filter a non-zero return
value based on the platform we are running on. For example on VLV with
i915.enable_rc6 set to 2, RC6 won't be enabled but atm
intel_enable_rc6() would still return 2 in this case.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a56f6b1..89fe0a7 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3262,15 +3262,29 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
-int intel_enable_rc6(const struct drm_device *dev)
+static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
 {
 	/* No RC6 before Ironlake */
 	if (INTEL_INFO(dev)->gen < 5)
 		return 0;
 
 	/* Respect the kernel parameter if it is set */
-	if (i915.enable_rc6 >= 0)
-		return i915.enable_rc6;
+	if (enable_rc6 >= 0) {
+		int mask = 0;
+
+		if (IS_BROADWELL(dev) || IS_HASWELL(dev) ||
+		    IS_VALLEYVIEW(dev) || IS_IRONLAKE_M(dev))
+			mask = INTEL_RC6_ENABLE;
+		else if (INTEL_INFO(dev)->gen >= 6)
+			mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
+			       INTEL_RC6pp_ENABLE;
+
+		if ((enable_rc6 & mask) != enable_rc6)
+			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
+				 enable_rc6, enable_rc6 & mask, mask);
+
+		return enable_rc6 & mask;
+	}
 
 	/* Disable RC6 on Ironlake */
 	if (INTEL_INFO(dev)->gen == 5)
@@ -3282,6 +3296,11 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return INTEL_RC6_ENABLE;
 }
 
+int intel_enable_rc6(const struct drm_device *dev)
+{
+	return i915.enable_rc6;
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4496,6 +4515,8 @@ static void intel_init_emon(struct drm_device *dev)
 
 void intel_init_gt_powersave(struct drm_device *dev)
 {
+	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
+
 	if (IS_VALLEYVIEW(dev))
 		valleyview_setup_pctx(dev);
 }
-- 
1.8.4

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

* [PATCH v2 15/25] drm/i915: disable runtime PM if RC6 is disabled
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (13 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 16/25] drm/i915: make runtime PM interrupt enable/disable platform independent Imre Deak
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

On VLV we depend on RC6 to save the GT render and media HW context
before going to the D3 state via RPM, so as a preparation for the
VLV RPM support (added in an upcoming patch) disable RPM if RC6 is
disabled.

There is probably a similar dependency on other platforms too, so for
safety require RC6 for those too. For these platforms (SNB, HSW, BDW)
this is then a possible fix.

v2:
- require RC6 for all RPM platforms, not just for VLV (Paulo, Daniel)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c |  2 +-
 drivers/gpu/drm/i915/intel_pm.c | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a20d2d1..43980c9 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -923,7 +923,7 @@ static int intel_runtime_suspend(struct device *device)
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
+	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
 		return -ENODEV;
 
 	WARN_ON(!HAS_RUNTIME_PM(dev));
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 89fe0a7..3068f51 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6098,6 +6098,15 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
 
 	pm_runtime_set_active(device);
 
+	/*
+	 * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
+	 * requirement.
+	 */
+	if (!intel_enable_rc6(dev)) {
+		DRM_INFO("RC6 disabled, disabling runtime PM support\n");
+		return;
+	}
+
 	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
 	pm_runtime_mark_last_busy(device);
 	pm_runtime_use_autosuspend(device);
@@ -6113,6 +6122,9 @@ void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
 	if (!HAS_RUNTIME_PM(dev))
 		return;
 
+	if (!intel_enable_rc6(dev))
+		return;
+
 	/* Make sure we're not suspended first. */
 	pm_runtime_get_sync(device);
 	pm_runtime_disable(device);
-- 
1.8.4

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

* [PATCH v2 16/25] drm/i915: make runtime PM interrupt enable/disable platform independent
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (14 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 15/25] drm/i915: disable runtime PM if RC6 is disabled Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq Imre Deak
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

We need to disable the interrupts for all platforms, so make the helpers
for this platform independent and call them from them platform
independent runtime suspend/resume callbacks.

On HSW/BDW this will move interrupt disabling/re-enabling at the
beginning/end of runtime suspend/resume respectively, but I don't see
any reason why this would cause a problem there. In any case this seems
to be the correct thing to do even on those platforms.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      | 14 +++++---------
 drivers/gpu/drm/i915/intel_display.c |  2 --
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 43980c9..f3f9a33 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -888,13 +888,6 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
-static void snb_runtime_suspend(struct drm_i915_private *dev_priv)
-{
-	struct drm_device *dev = dev_priv->dev;
-
-	intel_runtime_pm_disable_interrupts(dev);
-}
-
 static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
 {
 	hsw_enable_pc8(dev_priv);
@@ -904,7 +897,6 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 
-	intel_runtime_pm_restore_interrupts(dev);
 	intel_init_pch_refclk(dev);
 	i915_gem_init_swizzling(dev);
 	mutex_lock(&dev_priv->rps.hw_lock);
@@ -931,8 +923,10 @@ static int intel_runtime_suspend(struct device *device)
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
+	intel_runtime_pm_disable_interrupts(dev);
+
 	if (IS_GEN6(dev))
-		snb_runtime_suspend(dev_priv);
+		;
 	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hsw_runtime_suspend(dev_priv);
 	else
@@ -976,6 +970,8 @@ static int intel_runtime_resume(struct device *device)
 	else
 		WARN_ON(1);
 
+	intel_runtime_pm_restore_interrupts(dev);
+
 	DRM_DEBUG_KMS("Device resumed\n");
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4d8d875..bda79ec 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7067,7 +7067,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 	}
 
 	lpt_disable_clkout_dp(dev);
-	intel_runtime_pm_disable_interrupts(dev);
 	hsw_disable_lcpll(dev_priv, true, true);
 }
 
@@ -7079,7 +7078,6 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Disabling package C8+\n");
 
 	hsw_restore_lcpll(dev_priv);
-	intel_runtime_pm_restore_interrupts(dev);
 	lpt_init_pch_refclk(dev);
 
 	if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
-- 
1.8.4

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

* [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (15 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 16/25] drm/i915: make runtime PM interrupt enable/disable platform independent Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 17:31   ` Ville Syrjälä
  2014-04-18 13:16   ` [PATCH v3 " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 18/25] drm/i915: make runtime PM swizzling/ring_freq init platform independent Imre Deak
                   ` (9 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

This is needed by the next patch moving the call out from platform
specific RPM callbacks to platform independent code.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      |  2 --
 drivers/gpu/drm/i915/intel_display.c |  2 --
 drivers/gpu/drm/i915/intel_pm.c      | 18 +++++++++++++++---
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f3f9a33..afc31e3 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -899,9 +899,7 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
 
 	intel_init_pch_refclk(dev);
 	i915_gem_init_swizzling(dev);
-	mutex_lock(&dev_priv->rps.hw_lock);
 	gen6_update_ring_freq(dev);
-	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
 static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bda79ec..596ae69 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7088,9 +7088,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 
 	intel_prepare_ddi(dev);
 	i915_gem_init_swizzling(dev);
-	mutex_lock(&dev_priv->rps.hw_lock);
 	gen6_update_ring_freq(dev);
-	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
 static void snb_modeset_global_resources(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3068f51..f88d64d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3522,7 +3522,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
-void gen6_update_ring_freq(struct drm_device *dev)
+static void __gen6_update_ring_freq(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int min_freq = 15;
@@ -3592,6 +3592,18 @@ void gen6_update_ring_freq(struct drm_device *dev)
 	}
 }
 
+void gen6_update_ring_freq(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!(INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)))
+		return;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	__gen6_update_ring_freq(dev);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
 int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
 {
 	u32 val, rp0;
@@ -4563,10 +4575,10 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
-		gen6_update_ring_freq(dev);
+		__gen6_update_ring_freq(dev);
 	} else {
 		gen6_enable_rps(dev);
-		gen6_update_ring_freq(dev);
+		__gen6_update_ring_freq(dev);
 	}
 	dev_priv->rps.enabled = true;
 	mutex_unlock(&dev_priv->rps.hw_lock);
-- 
1.8.4

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

* [PATCH v2 18/25] drm/i915: make runtime PM swizzling/ring_freq init platform independent
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (16 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 19/25] drm/i915: reinit GT power save during resume Imre Deak
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

We need to re-init sizzling on all platforms so move it to the
platform independent runtime resume callback. The ring frequency reinit
is also needed everywhere except on VLV, but gen6_update_ring_freq()
will be a noop on VLV, so we can move this function too to platform
independent code.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      | 5 +++--
 drivers/gpu/drm/i915/intel_display.c | 2 --
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index afc31e3..b87109c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -898,8 +898,6 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 
 	intel_init_pch_refclk(dev);
-	i915_gem_init_swizzling(dev);
-	gen6_update_ring_freq(dev);
 }
 
 static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
@@ -968,6 +966,9 @@ static int intel_runtime_resume(struct device *device)
 	else
 		WARN_ON(1);
 
+	i915_gem_init_swizzling(dev);
+	gen6_update_ring_freq(dev);
+
 	intel_runtime_pm_restore_interrupts(dev);
 
 	DRM_DEBUG_KMS("Device resumed\n");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 596ae69..3e7ad14 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7087,8 +7087,6 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 	}
 
 	intel_prepare_ddi(dev);
-	i915_gem_init_swizzling(dev);
-	gen6_update_ring_freq(dev);
 }
 
 static void snb_modeset_global_resources(struct drm_device *dev)
-- 
1.8.4

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

* [PATCH v2 19/25] drm/i915: reinit GT power save during resume
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (17 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 18/25] drm/i915: make runtime PM swizzling/ring_freq init platform independent Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 17:46   ` Ville Syrjälä
  2014-04-22 17:21   ` [PATCH v3 " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 20/25] drm/i915: vlv: setup RPS min/max frequencies once during init time Imre Deak
                   ` (7 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b87109c..1f88917 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -920,6 +920,7 @@ static int intel_runtime_suspend(struct device *device)
 	DRM_DEBUG_KMS("Suspending device\n");
 
 	intel_runtime_pm_disable_interrupts(dev);
+	cancel_work_sync(&dev_priv->rps.work);
 
 	if (IS_GEN6(dev))
 		;
@@ -968,6 +969,7 @@ static int intel_runtime_resume(struct device *device)
 
 	i915_gem_init_swizzling(dev);
 	gen6_update_ring_freq(dev);
+	intel_reset_gt_powersave(dev);
 
 	intel_runtime_pm_restore_interrupts(dev);
 
-- 
1.8.4

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

* [PATCH v2 20/25] drm/i915: vlv: setup RPS min/max frequencies once during init time
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (18 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 19/25] drm/i915: reinit GT power save during resume Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-14 17:24 ` [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock Imre Deak
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

When enabling runtime PM on VLV, GT power save enabling becomes relatively
frequent, so optimize it a bit.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 66 +++++++++++++++++++++++++----------------
 1 file changed, 41 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f88d64d..bc38213 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3698,6 +3698,45 @@ static void valleyview_cleanup_pctx(struct drm_device *dev)
 	dev_priv->vlv_pctx = NULL;
 }
 
+static void valleyview_init_gt_powersave(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	valleyview_setup_pctx(dev);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+
+	dev_priv->rps.max_freq = valleyview_rps_max_freq(dev_priv);
+	dev_priv->rps.rp0_freq = dev_priv->rps.max_freq;
+	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq),
+			 dev_priv->rps.max_freq);
+
+	dev_priv->rps.efficient_freq = valleyview_rps_rpe_freq(dev_priv);
+	DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+			 dev_priv->rps.efficient_freq);
+
+	dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv);
+	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
+			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
+			 dev_priv->rps.min_freq);
+
+	/* Preserve min/max settings in case of re-init */
+	if (dev_priv->rps.max_freq_softlimit == 0)
+		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
+
+	if (dev_priv->rps.min_freq_softlimit == 0)
+		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
+
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
+static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
+{
+	valleyview_cleanup_pctx(dev);
+}
+
 static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3764,29 +3803,6 @@ static void valleyview_enable_rps(struct drm_device *dev)
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
 			 dev_priv->rps.cur_freq);
 
-	dev_priv->rps.max_freq = valleyview_rps_max_freq(dev_priv);
-	dev_priv->rps.rp0_freq  = dev_priv->rps.max_freq;
-	DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq),
-			 dev_priv->rps.max_freq);
-
-	dev_priv->rps.efficient_freq = valleyview_rps_rpe_freq(dev_priv);
-	DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
-			 dev_priv->rps.efficient_freq);
-
-	dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv);
-	DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-			 vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
-			 dev_priv->rps.min_freq);
-
-	/* Preserve min/max settings in case of re-init */
-	if (dev_priv->rps.max_freq_softlimit == 0)
-		dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
-
-	if (dev_priv->rps.min_freq_softlimit == 0)
-		dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
-
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
 			 vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
 			 dev_priv->rps.efficient_freq);
@@ -4530,13 +4546,13 @@ void intel_init_gt_powersave(struct drm_device *dev)
 	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
 
 	if (IS_VALLEYVIEW(dev))
-		valleyview_setup_pctx(dev);
+		valleyview_init_gt_powersave(dev);
 }
 
 void intel_cleanup_gt_powersave(struct drm_device *dev)
 {
 	if (IS_VALLEYVIEW(dev))
-		valleyview_cleanup_pctx(dev);
+		valleyview_cleanup_gt_powersave(dev);
 }
 
 void intel_disable_gt_powersave(struct drm_device *dev)
-- 
1.8.4

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

* [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (19 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 20/25] drm/i915: vlv: setup RPS min/max frequencies once during init time Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 17:49   ` Ville Syrjälä
  2014-04-18 13:35   ` [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off Imre Deak
  2014-04-14 17:24 ` [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock Imre Deak
                   ` (5 subsequent siblings)
  26 siblings, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

This will be needed by the VLV runtime PM helpers too, so factor it out.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 37 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  1 +
 drivers/gpu/drm/i915/intel_pm.c | 16 ++--------------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 1f88917..0609f77 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -905,6 +905,43 @@ static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
 	hsw_disable_pc8(dev_priv);
 }
 
+int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
+{
+	u32 val;
+	int err;
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
+
+#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
+	/* Wait for a previous force on/off to settle */
+	if (force_on) {
+		err = wait_for(!COND, 5);
+		if (err) {
+			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
+				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
+			return err;
+		}
+	}
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
+	if (force_on)
+		val |= VLV_GFX_CLK_FORCE_ON_BIT;
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
+
+	if (!force_on)
+		return 0;
+
+	err = wait_for(COND, 5);
+	if (err)
+		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
+			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
+
+	return err;
+#undef COND
+}
+
 static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5254f4b..3cac434 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1968,6 +1968,7 @@ extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
+int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 
 extern void intel_console_resume(struct work_struct *work);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index bc38213..5a61075 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3129,16 +3129,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	/* Mask turbo interrupt so that they will not come in between */
 	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 
-	/* Bring up the Gfx clock */
-	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
-				VLV_GFX_CLK_FORCE_ON_BIT);
-
-	if (wait_for(((VLV_GFX_CLK_STATUS_BIT &
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 5)) {
-			DRM_ERROR("GFX_CLK_ON request timed out\n");
-		return;
-	}
+	vlv_force_gfx_clock(dev_priv, true);
 
 	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
 
@@ -3149,10 +3140,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 				& GENFREQSTATUS) == 0, 5))
 		DRM_ERROR("timed out waiting for Punit\n");
 
-	/* Release the Gfx clock */
-	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
-				~VLV_GFX_CLK_FORCE_ON_BIT);
+	vlv_force_gfx_clock(dev_priv, false);
 
 	I915_WRITE(GEN6_PMINTRMSK,
 		   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
-- 
1.8.4

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

* [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (20 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-25 14:04   ` Daniel Vetter
  2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
                   ` (4 subsequent siblings)
  26 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

I've seen latencies up to 15msec, so increase the timeout to 20msec.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 0609f77..845e1e1 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -916,7 +916,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
 	/* Wait for a previous force on/off to settle */
 	if (force_on) {
-		err = wait_for(!COND, 5);
+		err = wait_for(!COND, 20);
 		if (err) {
 			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
 				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
@@ -933,7 +933,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 	if (!force_on)
 		return 0;
 
-	err = wait_for(COND, 5);
+	err = wait_for(COND, 20);
 	if (err)
 		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
 			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
-- 
1.8.4

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

* [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (21 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-24 21:17   ` Rodrigo Vivi
                     ` (2 more replies)
  2014-04-14 17:24 ` [PATCH v2 24/25] drm/i915: propagate the error code from runtime PM callbacks Imre Deak
                   ` (3 subsequent siblings)
  26 siblings, 3 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Needed by the VLV S0ix context save/restore helpers.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 43 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f183746..cba0afd 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -92,6 +92,9 @@
 #define   GEN6_MBC_SNPCR_LOW	(2<<21)
 #define   GEN6_MBC_SNPCR_MIN	(3<<21) /* only 1/16th of the cache is shared */
 
+#define GEN7_G3DCTL		0x9024
+#define GEN7_GSCKGCTL		0x9028
+
 #define GEN6_MBCTL		0x0907c
 #define   GEN6_MBCTL_ENABLE_BOOT_FETCH	(1 << 4)
 #define   GEN6_MBCTL_CTX_FETCH_NEEDED	(1 << 3)
@@ -785,9 +788,20 @@ enum punit_power_well {
 #define RING_MAX_IDLE(base)	((base)+0x54)
 #define RING_HWS_PGA(base)	((base)+0x80)
 #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
-#define ARB_MODE		0x04030
+
+#define GEN7_WR_WATERMARK	0x4028
+#define GEN7_GFX_PRIO_CTRL	0x402C
+#define ARB_MODE		0x4030
 #define   ARB_MODE_SWIZZLE_SNB	(1<<4)
 #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
+#define GEN7_GFX_PEND_TLB0	0x4034
+#define GEN7_GFX_PEND_TLB1	0x4038
+/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
+#define GEN7_LRA_LIMITS_BASE	0x403C
+#define GEN7_LRA_LIMITS_REG_NUM	13
+#define GEN7_MEDIA_MAX_REQ_COUNT	0x4070
+#define GEN7_GFX_MAX_REQ_COUNT		0x4074
+
 #define GAMTARBMODE		0x04a08
 #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
 #define   ARB_MODE_SWIZZLE_BDW	(1<<1)
@@ -822,6 +836,9 @@ enum punit_power_well {
 #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
 #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
 #define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
+
+#define GEN7_TLB_RD_ADDR	0x4700
+
 #if 0
 #define PRB0_TAIL	0x02030
 #define PRB0_HEAD	0x02034
@@ -948,6 +965,8 @@ enum punit_power_well {
 
 #define VLV_DISPLAY_BASE 0x180000
 
+#define VLV_GU_CTL0	(VLV_DISPLAY_BASE + 0x2030)
+#define VLV_GU_CTL1	(VLV_DISPLAY_BASE + 0x2034)
 #define SCPD0		0x0209c /* 915+ only */
 #define IER		0x020a0
 #define IIR		0x020a4
@@ -955,6 +974,7 @@ enum punit_power_well {
 #define ISR		0x020ac
 #define VLV_GUNIT_CLOCK_GATE	(VLV_DISPLAY_BASE + 0x2060)
 #define   GCFG_DIS		(1<<8)
+#define VLV_GUNIT_CLOCK_GATE2	(VLV_DISPLAY_BASE + 0x2064)
 #define VLV_IIR_RW	(VLV_DISPLAY_BASE + 0x2084)
 #define VLV_IER		(VLV_DISPLAY_BASE + 0x20a0)
 #define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
@@ -4988,6 +5008,8 @@ enum punit_power_well {
 
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
 
+#define  VLV_PMWGICZ				0x1300a4
+
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_VLV				0x1300b0
 #define  FORCEWAKE_ACK_VLV			0x1300b4
@@ -5011,6 +5033,7 @@ enum punit_power_well {
 #define  FORCEWAKE_MT_ACK			0x130040
 #define  ECOBUS					0xa180
 #define    FORCEWAKE_MT_ENABLE			(1<<5)
+#define  VLV_SPAREG2H				0xA194
 
 #define  GTFIFODBG				0x120000
 #define    GT_FIFO_SBDROPERR			(1<<6)
@@ -5040,12 +5063,24 @@ enum punit_power_well {
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
 # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
 
+#define GEN7_UCGCTL3				0x9408
+
 #define GEN7_UCGCTL4				0x940c
 #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)
 
+#define GEN7_RCGCTL1				0x9410
+#define GEN7_RCGCTL2				0x9414
+#define GEN7_RSTCTL				0x9420
+
 #define GEN8_UCGCTL6				0x9430
 #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE	(1<<14)
 
+#define GEN7_GFXPAUSE				0xA000
+#define GEN7_RPDEUHWTC				0xA080
+#define GEN7_RPDEUC				0xA084
+
+#define VLV_PWRDWNUPCTL				0xA294
+
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
@@ -5098,6 +5133,7 @@ enum punit_power_well {
 #define GEN6_RP_UP_EI				0xA068
 #define GEN6_RP_DOWN_EI				0xA06C
 #define GEN6_RP_IDLE_HYSTERSIS			0xA070
+#define GEN7_RPDEUCSW				0xA088
 #define GEN6_RC_STATE				0xA094
 #define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
 #define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
@@ -5105,9 +5141,11 @@ enum punit_power_well {
 #define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
 #define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
 #define GEN6_RC_SLEEP				0xA0B0
+#define VLV_RCUBMABDTMR				0xA0B0
 #define GEN6_RC1e_THRESHOLD			0xA0B4
 #define GEN6_RC6_THRESHOLD			0xA0B8
 #define GEN6_RC6p_THRESHOLD			0xA0BC
+#define VLV_RCEDATA				0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
 
@@ -5126,6 +5164,9 @@ enum punit_power_well {
 						 GEN6_PM_RP_DOWN_THRESHOLD | \
 						 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define GEN7_GT_SCRATCH_BASE			0x4F100
+#define GEN7_GT_SCRATCH_REG_NUM			8
+
 #define VLV_GTLC_SURVIVABILITY_REG              0x130098
 #define VLV_GFX_CLK_STATUS_BIT			(1<<3)
 #define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
-- 
1.8.4

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

* [PATCH v2 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (22 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-15 13:39   ` [PATCH v3 " Imre Deak
  2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
                   ` (2 subsequent siblings)
  26 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Atm, none of the RPM callbacks can fail, but the next patch adding
RPM support for VLV changes this, so prepare for it.

In case one of these callbacks return error RPM will get permanently
disabled until the error is explicitly cleared. In the future we could
add support for re-enabling it, for example after resetting the HW, but
for now - hopefully - we can live with the simpler solution.

v2:
- propagate the error from the resume callbacks too (Paulo)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 845e1e1..08e210c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
-static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
+static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
 {
 	hsw_enable_pc8(dev_priv);
+
+	return 0;
 }
 
-static void snb_runtime_resume(struct drm_i915_private *dev_priv)
+static int snb_runtime_resume(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 
 	intel_init_pch_refclk(dev);
+
+	return 0;
 }
 
-static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
+static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
 {
 	hsw_disable_pc8(dev_priv);
+
+	return 0;
 }
 
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
@@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
 		return -ENODEV;
@@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
 	intel_runtime_pm_disable_interrupts(dev);
 	cancel_work_sync(&dev_priv->rps.work);
 
-	if (IS_GEN6(dev))
-		;
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_runtime_suspend(dev_priv);
-	else
+	if (IS_GEN6(dev)) {
+		ret = 0;
+	} if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		ret = hsw_runtime_suspend(dev_priv);
+	} else {
+		ret = -ENODEV;
 		WARN_ON(1);
+	}
+
+	if (ret) {
+		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
+		intel_runtime_pm_restore_interrupts(dev);
+
+		return ret;
+	}
 
 	i915_gem_release_all_mmaps(dev_priv);
 
@@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	WARN_ON(!HAS_RUNTIME_PM(dev));
 
@@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
 	intel_opregion_notify_adapter(dev, PCI_D0);
 	dev_priv->pm.suspended = false;
 
-	if (IS_GEN6(dev))
-		snb_runtime_resume(dev_priv);
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_runtime_resume(dev_priv);
-	else
+	if (IS_GEN6(dev)) {
+		ret = snb_runtime_resume(dev_priv);
+	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		ret = hsw_runtime_resume(dev_priv);
+	} else {
 		WARN_ON(1);
+		ret = -ENODEV;
+	}
 
+	/*
+	 * No point of rolling back things in case of an error, as the best
+	 * we can do is to hope that things will still work (and disable RPM).
+	 */
 	i915_gem_init_swizzling(dev);
 	gen6_update_ring_freq(dev);
 	intel_reset_gt_powersave(dev);
 
 	intel_runtime_pm_restore_interrupts(dev);
 
-	DRM_DEBUG_KMS("Device resumed\n");
-	return 0;
+	if (ret)
+		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
+	else
+		DRM_DEBUG_KMS("Device resumed\n");
+
+	return ret;
 }
 
 static const struct dev_pm_ops i915_pm_ops = {
-- 
1.8.4

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

* [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (23 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 24/25] drm/i915: propagate the error code from runtime PM callbacks Imre Deak
@ 2014-04-14 17:24 ` Imre Deak
  2014-04-16 12:39   ` Ville Syrjälä
                     ` (2 more replies)
  2014-04-14 17:41 ` [PATCH v2 26/25] drm/i915: vlv: enable runtime PM Imre Deak
  2014-04-17 11:00 ` [PATCH v2 00/25] vlv: add support for RPM Ville Syrjälä
  26 siblings, 3 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:24 UTC (permalink / raw)
  To: intel-gfx

Add runtime PM support for VLV, but leave it disabled. The next patch
enables it.

The suspend/resume sequence used is based on [1] and [2]. In practice we
depend on the GT RC6 mechanism to save the HW context depending on the
render and media power wells. By the time we run the runtime suspend
callback the display side is also off and the HW context for that is
managed by the display power domain framework.

Besides the above there are Gunit registers that depend on a system-wide
power well. This power well goes off once the device enters any of the
S0i[R123] states. To handle this scenario, save/restore these Gunit
registers. Note that this is not the complete register set dictated by
[2], to remove some overhead, registers that are known not to be used are
ignored. Also some registers are fully setup by initialization functions
called during resume, these are not saved either. The list of registers
can be further reduced, see the TODO note in the code.

[1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
[2] VLV2_S0IXRegs

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
 2 files changed, 389 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 08e210c..bc206dd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
+/*
+ * Save all Gunit registers that may be lost after a D3 and a subsequent
+ * S0i[R123] transition. The list of registers needing a save/restore is
+ * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
+ * registers in the following way:
+ * - Driver: saved/restored by the driver
+ * - Punit : saved/restored by the Punit firmware
+ * - No, w/o marking: no need to save/restore, since the register is R/O or
+ *                    used internally by the HW in a way that doesn't depend
+ *                    keeping the content across a suspend/resume.
+ * - Debug : used for debugging
+ *
+ * We save/restore all registers marked with 'Driver', with the following
+ * exceptions:
+ * - Registers out of use, including also registers marked with 'Debug'.
+ *   These have no effect on the driver's operation, so we don't save/restore
+ *   them to reduce the overhead.
+ * - Registers that are fully setup by an initialization function called from
+ *   the resume path. For example many clock gating and RPS/RC6 registers.
+ * - Registers that provide the right functionality with their reset defaults.
+ *
+ * TODO: Except for registers that based on the above 3 criteria can be safely
+ * ignored, we save/restore all others, practically treating the HW context as
+ * a black-box for the driver. Further investigation is needed to reduce the
+ * saved/restored registers even further, by following the same 3 criteria.
+ */
+static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
+	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
+	s->arb_mode		= I915_READ(ARB_MODE);
+	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
+	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
+
+	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+
+	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
+	s->ecochk		= I915_READ(GAM_ECOCHK);
+	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
+	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
+
+	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	s->g3dctl		= I915_READ(GEN7_G3DCTL);
+	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
+	s->mbctl		= I915_READ(GEN6_MBCTL);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
+	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
+	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
+	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
+	s->rstctl		= I915_READ(GEN7_RSTCTL);
+	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
+	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
+	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
+	s->ecobus		= I915_READ(ECOBUS);
+	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
+	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
+	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
+	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
+	s->rcedata		= I915_READ(VLV_RCEDATA);
+	s->spare2gh		= I915_READ(VLV_SPAREG2H);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	s->gt_imr		= I915_READ(GTIMR);
+	s->gt_ier		= I915_READ(GTIER);
+	s->pm_imr		= I915_READ(GEN6_PMIIR);
+	s->pm_ier		= I915_READ(GEN6_PMIER);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	s->tilectl		= I915_READ(TILECTL);
+	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
+	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
+	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
+	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
+	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
+
+	/*
+	 * Not saving any of:
+	 * DFT,		0x9800-0x9EC0
+	 * SARB,	0xB000-0xB1FC
+	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
+	 * PCI CFG
+	 */
+}
+
+static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	u32 val;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
+	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
+	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
+	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
+	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
+
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
+
+	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
+	I915_WRITE(GAM_ECOCHK,		s->ecochk);
+	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
+	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
+
+	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
+	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
+	I915_WRITE(GEN6_MBCTL,		s->mbctl);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
+	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
+	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
+	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
+	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
+	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
+	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
+	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
+	I915_WRITE(ECOBUS,		s->ecobus);
+	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
+	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
+	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
+	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
+	I915_WRITE(VLV_RCEDATA,		s->rcedata);
+	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	I915_WRITE(GTIMR,		s->gt_imr);
+	I915_WRITE(GTIER,		s->gt_ier);
+	I915_WRITE(GEN6_PMIIR,		s->pm_imr);
+	I915_WRITE(GEN6_PMIER,		s->pm_ier);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	I915_WRITE(TILECTL,			s->tilectl);
+	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
+	/*
+	 * Preserve the GT allow wake and GFX force clock bit, they are not
+	 * be restored, as they are used to control the s0ix suspend/resume
+	 * sequence by the caller.
+	 */
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= VLV_GTLC_ALLOWWAKEREQ;
+	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	val &= VLV_GFX_CLK_FORCE_ON_BIT;
+	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
+
+	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
+	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
+}
+
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 {
 	u32 val;
@@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 #undef COND
 }
 
+static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
+{
+	u32 val;
+	int err = 0;
+
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= ~VLV_GTLC_ALLOWWAKEREQ;
+	if (allow)
+		val |= VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+	POSTING_READ(VLV_GTLC_WAKE_CTRL);
+
+#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
+	      allow)
+	err = wait_for(COND, 1);
+	if (err)
+		DRM_ERROR("timeout disabling GT waking\n");
+	return err;
+#undef COND
+}
+
+static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
+				 bool wait_for_on)
+{
+	u32 mask;
+	u32 val;
+	int err;
+
+	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
+	val = wait_for_on ? mask : 0;
+#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
+	if (COND)
+		return 0;
+
+	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
+			wait_for_on ? "on" : "off",
+			I915_READ(VLV_GTLC_PW_STATUS));
+
+	/*
+	 * RC6 transitioning can be delayed up to 2 msec (see
+	 * valleyview_enable_rps), use 3 msec for safety.
+	 */
+	err = wait_for(COND, 3);
+	if (err)
+		DRM_ERROR("timeout waiting for GT wells to go %s\n",
+			  wait_for_on ? "on" : "off");
+
+	return err;
+#undef COND
+}
+
+static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
+{
+	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
+		return;
+
+	DRM_ERROR("GT register access while GT waking disabled\n");
+	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
+}
+
+static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	u32 mask;
+	int err;
+
+	/*
+	 * Bspec defines the following GT well on flags as debug only, so
+	 * don't treat them as hard failures.
+	 */
+	(void)vlv_wait_for_gt_wells(dev_priv, false);
+
+	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
+	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
+
+	vlv_check_no_gt_access(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, true);
+	if (err)
+		goto err1;
+
+	err = vlv_allow_gt_wake(dev_priv, false);
+	if (err)
+		goto err2;
+	vlv_save_gunit_s0ix_state(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (err)
+		goto err2;
+
+	return 0;
+
+err2:
+	/* For safety always re-enable waking and disable gfx clock forcing */
+	vlv_allow_gt_wake(dev_priv, true);
+err1:
+	vlv_force_gfx_clock(dev_priv, false);
+
+	return err;
+}
+
+static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int err;
+	int ret;
+
+	/*
+	 * If any of the steps fail just try to continue, that's the best we
+	 * can do at this point. Return the first error code (which will also
+	 * leave RPM permanently disabled).
+	 */
+	ret = vlv_force_gfx_clock(dev_priv, true);
+
+	vlv_restore_gunit_s0ix_state(dev_priv);
+
+	err = vlv_allow_gt_wake(dev_priv, true);
+	if (!ret)
+		ret = err;
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (!ret)
+		ret = err;
+
+	vlv_check_no_gt_access(dev_priv);
+
+	intel_init_clock_gating(dev);
+	i915_gem_restore_fences(dev);
+
+	return ret;
+}
+
 static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -970,6 +1293,8 @@ static int intel_runtime_suspend(struct device *device)
 		ret = 0;
 	} if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_suspend(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_suspend(dev_priv);
 	} else {
 		ret = -ENODEV;
 		WARN_ON(1);
@@ -1018,6 +1343,8 @@ static int intel_runtime_resume(struct device *device)
 		ret = snb_runtime_resume(dev_priv);
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_resume(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_resume(dev_priv);
 	} else {
 		WARN_ON(1);
 		ret = -ENODEV;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3cac434..77cb7fc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
 	u32 savePCH_PORT_HOTPLUG;
 };
 
+struct vlv_s0ix_state {
+	/* GAM */
+	u32 wr_watermark;
+	u32 gfx_prio_ctrl;
+	u32 arb_mode;
+	u32 gfx_pend_tlb0;
+	u32 gfx_pend_tlb1;
+	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
+	u32 media_max_req_count;
+	u32 gfx_max_req_count;
+	u32 render_hwsp;
+	u32 ecochk;
+	u32 bsd_hwsp;
+	u32 blt_hwsp;
+	u32 tlb_rd_addr;
+
+	/* MBC */
+	u32 g3dctl;
+	u32 gsckgctl;
+	u32 mbctl;
+
+	/* GCP */
+	u32 ucgctl1;
+	u32 ucgctl3;
+	u32 rcgctl1;
+	u32 rcgctl2;
+	u32 rstctl;
+	u32 misccpctl;
+
+	/* GPM */
+	u32 gfxpause;
+	u32 rpdeuhwtc;
+	u32 rpdeuc;
+	u32 ecobus;
+	u32 pwrdwnupctl;
+	u32 rp_down_timeout;
+	u32 rp_deucsw;
+	u32 rcubmabdtmr;
+	u32 rcedata;
+	u32 spare2gh;
+
+	/* Display 1 CZ domain */
+	u32 gt_imr;
+	u32 gt_ier;
+	u32 pm_imr;
+	u32 pm_ier;
+	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
+
+	/* GT SA CZ domain */
+	u32 tilectl;
+	u32 gt_fifoctl;
+	u32 gtlc_wake_ctrl;
+	u32 gtlc_survive;
+	u32 pmwgicz;
+
+	/* Display 2 CZ domain */
+	u32 gu_ctl0;
+	u32 gu_ctl1;
+	u32 clock_gate_dis2;
+};
+
 struct intel_gen6_power_mgmt {
 	/* work and pm_iir are protected by dev_priv->irq_lock */
 	struct work_struct work;
@@ -1447,6 +1508,7 @@ struct drm_i915_private {
 
 	u32 suspend_count;
 	struct i915_suspend_saved_registers regfile;
+	struct vlv_s0ix_state vlv_s0ix_state;
 
 	struct {
 		/*
-- 
1.8.4

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

* [PATCH v2 26/25] drm/i915: vlv: enable runtime PM
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (24 preceding siblings ...)
  2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
@ 2014-04-14 17:41 ` Imre Deak
  2014-05-06 19:39   ` Daniel Vetter
  2014-04-17 11:00 ` [PATCH v2 00/25] vlv: add support for RPM Ville Syrjälä
  26 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-14 17:41 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

[ I managed to leave out this last one, so sending it now on top of the
  rest. ]

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 77cb7fc..3a98119 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1944,7 +1944,7 @@ struct drm_i915_cmd_table {
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
-				 IS_BROADWELL(dev))
+				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
-- 
1.8.4

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

* [PATCH v3 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-04-14 17:24 ` [PATCH v2 24/25] drm/i915: propagate the error code from runtime PM callbacks Imre Deak
@ 2014-04-15 13:39   ` Imre Deak
  2014-04-30 18:05     ` Ville Syrjälä
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-15 13:39 UTC (permalink / raw)
  To: intel-gfx

Atm, none of the RPM callbacks can fail, but the next patch adding
RPM support for VLV changes this, so prepare for it.

In case one of these callbacks return error RPM will get permanently
disabled until the error is explicitly cleared. In the future we could
add support for re-enabling it, for example after resetting the HW, but
for now - hopefully - we can live with the simpler solution.

v2:
- propagate the error from the resume callbacks too (Paulo)
v3:
- fix rebase fail typo around IS_GEN6() check in intel_runtime_suspend()

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 845e1e1..aeb7dec 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
-static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
+static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
 {
 	hsw_enable_pc8(dev_priv);
+
+	return 0;
 }
 
-static void snb_runtime_resume(struct drm_i915_private *dev_priv)
+static int snb_runtime_resume(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 
 	intel_init_pch_refclk(dev);
+
+	return 0;
 }
 
-static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
+static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
 {
 	hsw_disable_pc8(dev_priv);
+
+	return 0;
 }
 
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
@@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
 		return -ENODEV;
@@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
 	intel_runtime_pm_disable_interrupts(dev);
 	cancel_work_sync(&dev_priv->rps.work);
 
-	if (IS_GEN6(dev))
-		;
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_runtime_suspend(dev_priv);
-	else
+	if (IS_GEN6(dev)) {
+		ret = 0;
+	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		ret = hsw_runtime_suspend(dev_priv);
+	} else {
+		ret = -ENODEV;
 		WARN_ON(1);
+	}
+
+	if (ret) {
+		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
+		intel_runtime_pm_restore_interrupts(dev);
+
+		return ret;
+	}
 
 	i915_gem_release_all_mmaps(dev_priv);
 
@@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	WARN_ON(!HAS_RUNTIME_PM(dev));
 
@@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
 	intel_opregion_notify_adapter(dev, PCI_D0);
 	dev_priv->pm.suspended = false;
 
-	if (IS_GEN6(dev))
-		snb_runtime_resume(dev_priv);
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_runtime_resume(dev_priv);
-	else
+	if (IS_GEN6(dev)) {
+		ret = snb_runtime_resume(dev_priv);
+	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		ret = hsw_runtime_resume(dev_priv);
+	} else {
 		WARN_ON(1);
+		ret = -ENODEV;
+	}
 
+	/*
+	 * No point of rolling back things in case of an error, as the best
+	 * we can do is to hope that things will still work (and disable RPM).
+	 */
 	i915_gem_init_swizzling(dev);
 	gen6_update_ring_freq(dev);
 	intel_reset_gt_powersave(dev);
 
 	intel_runtime_pm_restore_interrupts(dev);
 
-	DRM_DEBUG_KMS("Device resumed\n");
-	return 0;
+	if (ret)
+		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
+	else
+		DRM_DEBUG_KMS("Device resumed\n");
+
+	return ret;
 }
 
 static const struct dev_pm_ops i915_pm_ops = {
-- 
1.8.4

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

* Re: [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-14 17:24 ` [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
@ 2014-04-16 12:11   ` Ville Syrjälä
  2014-04-18 12:47   ` [PATCH v3] " Imre Deak
  1 sibling, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 12:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:30PM +0300, Imre Deak wrote:
> Atm we can end up in the GPU reset deferred work in D3 state if the last
> runtime PM reference is dropped between detecting a hang/scheduling the
> work and executing the work. At least one such case I could trigger is
> the simulated reset via the i915_wedged debugfs entry. Fix this by
> disabling RPM before scheduling the work until the end of the work.
> 
> v2:
> - Instead of getting/putting the RPM reference in the reset work itself,
>   get it already before scheduling the work. By this we also prevent
>   going to D3 before the work gets to run, in addition to making sure
>   that we run the work itself in D0. (Ville, Daniel)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
>  drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 0b38f88..6398280 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
>  
>  	/* Free error state after interrupts are fully disabled. */
>  	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> -	cancel_work_sync(&dev_priv->gpu_error.work);
> +	if (!cancel_work_sync(&dev_priv->gpu_error.work))

'!' shouldn't be there

> +		/*
> +		 * The following won't make any difference in the PM state,
> +		 * since RPM is disabled already, but do it still for
> +		 * consistency.
> +		 */
> +		intel_runtime_pm_put(dev_priv);
>  	i915_destroy_error_state(dev);
>  
>  	if (dev->pdev->msi_enabled)
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a651d0d..5e079d8 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
>  		 */
>  		i915_error_wake_up(dev_priv, true);
>  	}
> +
> +	/* Drop the ref we took when scheduling this work. */
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  static void i915_report_and_clear_eir(struct drm_device *dev)
> @@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
>  	 * state of outstanding pagelips). Hence it must not be run on our own
>  	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
>  	 * code will deadlock.
> +	 *
> +	 * It's guaranteed that here we are in D0 state, since we can only get
> +	 * here via one of the following paths:
> +	 * - From an IRQ handler's error detection. -> The driver must make
> +	 *   sure that IRQs are unmasked only while holding an RPM ref.
> +	 * - From hang-check due to a blocked request. -> The request holds an
> +	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
> +	 *   won't be called until the request is finished.
> +	 * - From hang-check due to a flip hang. -> We have an RPM ref because
> +	 *   of the active modeset.
> +	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
> +	 *   RPM ref.
> +	 * Take here an atomic RPM ref still to make sure that we don't
> +	 * re-enter D3 until the error work gets to run and completes the
> +	 * reset.
>  	 */
> -	schedule_work(&dev_priv->gpu_error.work);
> +	if (schedule_work(&dev_priv->gpu_error.work))
> +		intel_runtime_pm_get_noresume(dev_priv);
>  }
>  
>  static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg
  2014-04-14 17:24 ` [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg Imre Deak
@ 2014-04-16 12:17   ` Ville Syrjälä
  2014-04-18 11:44     ` Imre Deak
  2014-04-18 12:55   ` [PATCH v3 " Imre Deak
  1 sibling, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 12:17 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:32PM +0300, Imre Deak wrote:
> While checking the error capture path I noticed that we lacked the
> power domain-on check for PIPESTAT so fix this by moving that to where
> the rest of pipe registers are captured.
> 
> The move also revealed that we actually don't include this register in
> the error report, so fix that too.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h       | 1 -
>  drivers/gpu/drm/i915/i915_gpu_error.c | 3 ---
>  drivers/gpu/drm/i915/intel_display.c  | 3 +++
>  3 files changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7d6acb4..5254f4b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -325,7 +325,6 @@ struct drm_i915_error_state {
>  	u32 gab_ctl;
>  	u32 gfx_mode;
>  	u32 extra_instdone[I915_NUM_INSTDONE_REG];
> -	u32 pipestat[I915_MAX_PIPES];
>  	u64 fence[I915_MAX_NUM_FENCES];
>  	struct intel_overlay_error_state *overlay;
>  	struct intel_display_error_state *display;
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index ba79b59..7b5cc08 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -1028,7 +1028,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  				   struct drm_i915_error_state *error)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> -	int pipe;
>  
>  	/* General organization
>  	 * 1. Registers specific to a single generation
> @@ -1080,8 +1079,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  			error->ier = I915_READ16(IER);
>  		else
>  			error->ier = I915_READ(IER);
> -		for_each_pipe(pipe)
> -			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
>  	}
>  
>  	/* 4: Everything else */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 1390ab5..4d8d875 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11925,6 +11925,7 @@ struct intel_display_error_state {
>  	struct intel_pipe_error_state {
>  		bool power_domain_on;
>  		u32 source;
> +		u32 stat;
>  	} pipe[I915_MAX_PIPES];
>  
>  	struct intel_plane_error_state {
> @@ -12006,6 +12007,7 @@ intel_display_capture_error_state(struct drm_device *dev)
>  		}
>  
>  		error->pipe[i].source = I915_READ(PIPESRC(i));
> +		error->pipe[i].stat = I915_READ(PIPESTAT(i));

This needs a !HAS_PCH_SPLIT check

>  	}
>  
>  	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
> @@ -12056,6 +12058,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
>  		err_printf(m, "  Power: %s\n",
>  			   error->pipe[i].power_domain_on ? "on" : "off");
>  		err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
> +		err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
>  
>  		err_printf(m, "Plane [%d]:\n", i);
>  		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place
  2014-04-14 17:24 ` [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place Imre Deak
@ 2014-04-16 12:22   ` Ville Syrjälä
  2014-04-16 12:57     ` Imre Deak
  0 siblings, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 12:22 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:31PM +0300, Imre Deak wrote:
> While checking the error capture path I noticed that this register is
> read twice for GEN2, so fix this and also move the read where it's done
> for other platforms.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index 4865ade..ba79b59 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -1053,9 +1053,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  		error->gfx_mode = I915_READ(GFX_MODE);
>  	}
>  
> -	if (IS_GEN2(dev))
> -		error->ier = I915_READ16(IER);
> -
>  	/* 2: Registers which belong to multiple generations */
>  	if (INTEL_INFO(dev)->gen >= 7)
>  		error->forcewake = I915_READ(FORCEWAKE_MT);
> @@ -1079,7 +1076,10 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  	if (HAS_PCH_SPLIT(dev))
>  		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
>  	else {
> -		error->ier = I915_READ(IER);
> +		if (IS_GEN2(dev))
> +			error->ier = I915_READ16(IER);
> +		else
> +			error->ier = I915_READ(IER);
>  		for_each_pipe(pipe)
>  			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
>  	}

The IER handling seems fairly bogus all around. On VLV and PCH platforms
we smash both the display and GT IER into the same u32. So probably no
one can make any sense of the result.

Also I don't know why we try to dump only these two interrupt registers
but not the others.

So seems like there's more work that needs to be done here.

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

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option
  2014-04-14 17:24 ` [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option Imre Deak
@ 2014-04-16 12:28   ` Ville Syrjälä
  2014-04-16 12:37     ` Imre Deak
  2014-04-18 13:01   ` [PATCH v3 " Imre Deak
  1 sibling, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 12:28 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:35PM +0300, Imre Deak wrote:
> Atm, an invalid enable_rc6 module option will be silently ignored, so
> emit an info message about it. Doing an early sanitization we can also
> reuse intel_enable_rc6() in a follow-up patch to see if RC6 is actually
> enabled. Currently the caller would have to filter a non-zero return
> value based on the platform we are running on. For example on VLV with
> i915.enable_rc6 set to 2, RC6 won't be enabled but atm
> intel_enable_rc6() would still return 2 in this case.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 27 ++++++++++++++++++++++++---
>  1 file changed, 24 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index a56f6b1..89fe0a7 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3262,15 +3262,29 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
>  		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
>  }
>  
> -int intel_enable_rc6(const struct drm_device *dev)
> +static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
>  {
>  	/* No RC6 before Ironlake */
>  	if (INTEL_INFO(dev)->gen < 5)
>  		return 0;
>  
>  	/* Respect the kernel parameter if it is set */
> -	if (i915.enable_rc6 >= 0)
> -		return i915.enable_rc6;
> +	if (enable_rc6 >= 0) {
> +		int mask = 0;
> +
> +		if (IS_BROADWELL(dev) || IS_HASWELL(dev) ||
> +		    IS_VALLEYVIEW(dev) || IS_IRONLAKE_M(dev))
> +			mask = INTEL_RC6_ENABLE;
> +		else if (INTEL_INFO(dev)->gen >= 6)
> +			mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
> +			       INTEL_RC6pp_ENABLE;

You forgot ILK. 

Also this would seem simpler:

if (SNB|IVB)
 mask = rc6 | rc6p | rc6pp;
else
 mask = rc6;

> +
> +		if ((enable_rc6 & mask) != enable_rc6)
> +			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
> +				 enable_rc6, enable_rc6 & mask, mask);
> +
> +		return enable_rc6 & mask;
> +	}
>  
>  	/* Disable RC6 on Ironlake */
>  	if (INTEL_INFO(dev)->gen == 5)
> @@ -3282,6 +3296,11 @@ int intel_enable_rc6(const struct drm_device *dev)
>  	return INTEL_RC6_ENABLE;
>  }
>  
> +int intel_enable_rc6(const struct drm_device *dev)
> +{
> +	return i915.enable_rc6;
> +}
> +
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -4496,6 +4515,8 @@ static void intel_init_emon(struct drm_device *dev)
>  
>  void intel_init_gt_powersave(struct drm_device *dev)
>  {
> +	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
> +
>  	if (IS_VALLEYVIEW(dev))
>  		valleyview_setup_pctx(dev);
>  }
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option
  2014-04-16 12:28   ` Ville Syrjälä
@ 2014-04-16 12:37     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-16 12:37 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 3415 bytes --]

On Wed, 2014-04-16 at 15:28 +0300, Ville Syrjälä wrote:
> On Mon, Apr 14, 2014 at 08:24:35PM +0300, Imre Deak wrote:
> > Atm, an invalid enable_rc6 module option will be silently ignored, so
> > emit an info message about it. Doing an early sanitization we can also
> > reuse intel_enable_rc6() in a follow-up patch to see if RC6 is actually
> > enabled. Currently the caller would have to filter a non-zero return
> > value based on the platform we are running on. For example on VLV with
> > i915.enable_rc6 set to 2, RC6 won't be enabled but atm
> > intel_enable_rc6() would still return 2 in this case.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 27 ++++++++++++++++++++++++---
> >  1 file changed, 24 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index a56f6b1..89fe0a7 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3262,15 +3262,29 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
> >  		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
> >  }
> >  
> > -int intel_enable_rc6(const struct drm_device *dev)
> > +static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
> >  {
> >  	/* No RC6 before Ironlake */
> >  	if (INTEL_INFO(dev)->gen < 5)
> >  		return 0;
> >  
> >  	/* Respect the kernel parameter if it is set */
> > -	if (i915.enable_rc6 >= 0)
> > -		return i915.enable_rc6;
> > +	if (enable_rc6 >= 0) {
> > +		int mask = 0;
> > +
> > +		if (IS_BROADWELL(dev) || IS_HASWELL(dev) ||
> > +		    IS_VALLEYVIEW(dev) || IS_IRONLAKE_M(dev))
> > +			mask = INTEL_RC6_ENABLE;
> > +		else if (INTEL_INFO(dev)->gen >= 6)
> > +			mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
> > +			       INTEL_RC6pp_ENABLE;
> 
> You forgot ILK. 

For desktop ILK intel_enable_gt_powersave() will keep RC6 disabled, so
the above is correct based on that.

> Also this would seem simpler:
> 
> if (SNB|IVB)
>  mask = rc6 | rc6p | rc6pp;
> else
>  mask = rc6;

Ok, can rewrite it with the above exception for desktop ILK.

--Imre

> 
> > +
> > +		if ((enable_rc6 & mask) != enable_rc6)
> > +			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
> > +				 enable_rc6, enable_rc6 & mask, mask);
> > +
> > +		return enable_rc6 & mask;
> > +	}
> >  
> >  	/* Disable RC6 on Ironlake */
> >  	if (INTEL_INFO(dev)->gen == 5)
> > @@ -3282,6 +3296,11 @@ int intel_enable_rc6(const struct drm_device *dev)
> >  	return INTEL_RC6_ENABLE;
> >  }
> >  
> > +int intel_enable_rc6(const struct drm_device *dev)
> > +{
> > +	return i915.enable_rc6;
> > +}
> > +
> >  static void gen6_enable_rps_interrupts(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -4496,6 +4515,8 @@ static void intel_init_emon(struct drm_device *dev)
> >  
> >  void intel_init_gt_powersave(struct drm_device *dev)
> >  {
> > +	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
> > +
> >  	if (IS_VALLEYVIEW(dev))
> >  		valleyview_setup_pctx(dev);
> >  }
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
  2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
@ 2014-04-16 12:39   ` Ville Syrjälä
  2014-04-16 14:53   ` Daniel Vetter
  2014-04-22 17:28   ` [PATCH v3 " Imre Deak
  2 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 12:39 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
> Add runtime PM support for VLV, but leave it disabled. The next patch
> enables it.
> 
> The suspend/resume sequence used is based on [1] and [2]. In practice we
> depend on the GT RC6 mechanism to save the HW context depending on the
> render and media power wells. By the time we run the runtime suspend
> callback the display side is also off and the HW context for that is
> managed by the display power domain framework.
> 
> Besides the above there are Gunit registers that depend on a system-wide
> power well. This power well goes off once the device enters any of the
> S0i[R123] states. To handle this scenario, save/restore these Gunit
> registers. Note that this is not the complete register set dictated by
> [2], to remove some overhead, registers that are known not to be used are
> ignored. Also some registers are fully setup by initialization functions
> called during resume, these are not saved either. The list of registers
> can be further reduced, see the TODO note in the code.
> 
> [1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
> [2] VLV2_S0IXRegs
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
>  2 files changed, 389 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 08e210c..bc206dd 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +/*
> + * Save all Gunit registers that may be lost after a D3 and a subsequent
> + * S0i[R123] transition. The list of registers needing a save/restore is
> + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
> + * registers in the following way:
> + * - Driver: saved/restored by the driver
> + * - Punit : saved/restored by the Punit firmware
> + * - No, w/o marking: no need to save/restore, since the register is R/O or
> + *                    used internally by the HW in a way that doesn't depend
> + *                    keeping the content across a suspend/resume.
> + * - Debug : used for debugging
> + *
> + * We save/restore all registers marked with 'Driver', with the following
> + * exceptions:
> + * - Registers out of use, including also registers marked with 'Debug'.
> + *   These have no effect on the driver's operation, so we don't save/restore
> + *   them to reduce the overhead.
> + * - Registers that are fully setup by an initialization function called from
> + *   the resume path. For example many clock gating and RPS/RC6 registers.
> + * - Registers that provide the right functionality with their reset defaults.
> + *
> + * TODO: Except for registers that based on the above 3 criteria can be safely
> + * ignored, we save/restore all others, practically treating the HW context as
> + * a black-box for the driver. Further investigation is needed to reduce the
> + * saved/restored registers even further, by following the same 3 criteria.
> + */
> +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
> +	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
> +	s->arb_mode		= I915_READ(ARB_MODE);
> +	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
> +	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
> +
> +	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +
> +	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
> +	s->ecochk		= I915_READ(GAM_ECOCHK);
> +	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
> +	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
> +
> +	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	s->g3dctl		= I915_READ(GEN7_G3DCTL);
> +	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
> +	s->mbctl		= I915_READ(GEN6_MBCTL);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
> +	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
> +	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
> +	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
> +	s->rstctl		= I915_READ(GEN7_RSTCTL);
> +	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
> +	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
> +	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
> +	s->ecobus		= I915_READ(ECOBUS);
> +	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
> +	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
> +	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
> +	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
> +	s->rcedata		= I915_READ(VLV_RCEDATA);
> +	s->spare2gh		= I915_READ(VLV_SPAREG2H);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	s->gt_imr		= I915_READ(GTIMR);
> +	s->gt_ier		= I915_READ(GTIER);
> +	s->pm_imr		= I915_READ(GEN6_PMIIR);
                                                    ^
M

> +	s->pm_ier		= I915_READ(GEN6_PMIER);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	s->tilectl		= I915_READ(TILECTL);
> +	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
> +	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
> +	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
> +	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
> +	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
> +
> +	/*
> +	 * Not saving any of:
> +	 * DFT,		0x9800-0x9EC0
> +	 * SARB,	0xB000-0xB1FC
> +	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
> +	 * PCI CFG
> +	 */
> +}
> +
> +static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	u32 val;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
> +	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
> +	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
> +	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
> +	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
> +
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
> +
> +	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
> +	I915_WRITE(GAM_ECOCHK,		s->ecochk);
> +	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
> +	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
> +
> +	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
> +	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
> +	I915_WRITE(GEN6_MBCTL,		s->mbctl);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
> +	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
> +	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
> +	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
> +	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
> +	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
> +	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
> +	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
> +	I915_WRITE(ECOBUS,		s->ecobus);
> +	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
> +	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
> +	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
> +	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
> +	I915_WRITE(VLV_RCEDATA,		s->rcedata);
> +	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	I915_WRITE(GTIMR,		s->gt_imr);
> +	I915_WRITE(GTIER,		s->gt_ier);
> +	I915_WRITE(GEN6_PMIIR,		s->pm_imr);
                           ^
M

> +	I915_WRITE(GEN6_PMIER,		s->pm_ier);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	I915_WRITE(TILECTL,			s->tilectl);
> +	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
> +	/*
> +	 * Preserve the GT allow wake and GFX force clock bit, they are not
> +	 * be restored, as they are used to control the s0ix suspend/resume
> +	 * sequence by the caller.
> +	 */
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= VLV_GTLC_ALLOWWAKEREQ;
> +	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	val &= VLV_GFX_CLK_FORCE_ON_BIT;
> +	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> +
> +	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
> +	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
> +	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
> +}
> +
>  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  {
>  	u32 val;
> @@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  #undef COND
>  }
>  
> +static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
> +{
> +	u32 val;
> +	int err = 0;
> +
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= ~VLV_GTLC_ALLOWWAKEREQ;
> +	if (allow)
> +		val |= VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +	POSTING_READ(VLV_GTLC_WAKE_CTRL);
> +
> +#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
> +	      allow)
> +	err = wait_for(COND, 1);
> +	if (err)
> +		DRM_ERROR("timeout disabling GT waking\n");
> +	return err;
> +#undef COND
> +}
> +
> +static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
> +				 bool wait_for_on)
> +{
> +	u32 mask;
> +	u32 val;
> +	int err;
> +
> +	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
> +	val = wait_for_on ? mask : 0;
> +#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
> +	if (COND)
> +		return 0;
> +
> +	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
> +			wait_for_on ? "on" : "off",
> +			I915_READ(VLV_GTLC_PW_STATUS));
> +
> +	/*
> +	 * RC6 transitioning can be delayed up to 2 msec (see
> +	 * valleyview_enable_rps), use 3 msec for safety.
> +	 */
> +	err = wait_for(COND, 3);
> +	if (err)
> +		DRM_ERROR("timeout waiting for GT wells to go %s\n",
> +			  wait_for_on ? "on" : "off");
> +
> +	return err;
> +#undef COND
> +}
> +
> +static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
> +{
> +	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
> +		return;
> +
> +	DRM_ERROR("GT register access while GT waking disabled\n");
> +	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
> +}
> +
> +static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
> +{
> +	u32 mask;
> +	int err;
> +
> +	/*
> +	 * Bspec defines the following GT well on flags as debug only, so
> +	 * don't treat them as hard failures.
> +	 */
> +	(void)vlv_wait_for_gt_wells(dev_priv, false);
> +
> +	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
> +	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, true);
> +	if (err)
> +		goto err1;
> +
> +	err = vlv_allow_gt_wake(dev_priv, false);
> +	if (err)
> +		goto err2;
> +	vlv_save_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (err)
> +		goto err2;
> +
> +	return 0;
> +
> +err2:
> +	/* For safety always re-enable waking and disable gfx clock forcing */
> +	vlv_allow_gt_wake(dev_priv, true);
> +err1:
> +	vlv_force_gfx_clock(dev_priv, false);
> +
> +	return err;
> +}
> +
> +static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	int err;
> +	int ret;
> +
> +	/*
> +	 * If any of the steps fail just try to continue, that's the best we
> +	 * can do at this point. Return the first error code (which will also
> +	 * leave RPM permanently disabled).
> +	 */
> +	ret = vlv_force_gfx_clock(dev_priv, true);
> +
> +	vlv_restore_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_allow_gt_wake(dev_priv, true);
> +	if (!ret)
> +		ret = err;
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (!ret)
> +		ret = err;
> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	intel_init_clock_gating(dev);
> +	i915_gem_restore_fences(dev);
> +
> +	return ret;
> +}
> +
>  static int intel_runtime_suspend(struct device *device)
>  {
>  	struct pci_dev *pdev = to_pci_dev(device);
> @@ -970,6 +1293,8 @@ static int intel_runtime_suspend(struct device *device)
>  		ret = 0;
>  	} if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_suspend(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_suspend(dev_priv);
>  	} else {
>  		ret = -ENODEV;
>  		WARN_ON(1);
> @@ -1018,6 +1343,8 @@ static int intel_runtime_resume(struct device *device)
>  		ret = snb_runtime_resume(dev_priv);
>  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_resume(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_resume(dev_priv);
>  	} else {
>  		WARN_ON(1);
>  		ret = -ENODEV;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3cac434..77cb7fc 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
>  	u32 savePCH_PORT_HOTPLUG;
>  };
>  
> +struct vlv_s0ix_state {
> +	/* GAM */
> +	u32 wr_watermark;
> +	u32 gfx_prio_ctrl;
> +	u32 arb_mode;
> +	u32 gfx_pend_tlb0;
> +	u32 gfx_pend_tlb1;
> +	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
> +	u32 media_max_req_count;
> +	u32 gfx_max_req_count;
> +	u32 render_hwsp;
> +	u32 ecochk;
> +	u32 bsd_hwsp;
> +	u32 blt_hwsp;
> +	u32 tlb_rd_addr;
> +
> +	/* MBC */
> +	u32 g3dctl;
> +	u32 gsckgctl;
> +	u32 mbctl;
> +
> +	/* GCP */
> +	u32 ucgctl1;
> +	u32 ucgctl3;
> +	u32 rcgctl1;
> +	u32 rcgctl2;
> +	u32 rstctl;
> +	u32 misccpctl;
> +
> +	/* GPM */
> +	u32 gfxpause;
> +	u32 rpdeuhwtc;
> +	u32 rpdeuc;
> +	u32 ecobus;
> +	u32 pwrdwnupctl;
> +	u32 rp_down_timeout;
> +	u32 rp_deucsw;
> +	u32 rcubmabdtmr;
> +	u32 rcedata;
> +	u32 spare2gh;
> +
> +	/* Display 1 CZ domain */
> +	u32 gt_imr;
> +	u32 gt_ier;
> +	u32 pm_imr;
> +	u32 pm_ier;
> +	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
> +
> +	/* GT SA CZ domain */
> +	u32 tilectl;
> +	u32 gt_fifoctl;
> +	u32 gtlc_wake_ctrl;
> +	u32 gtlc_survive;
> +	u32 pmwgicz;
> +
> +	/* Display 2 CZ domain */
> +	u32 gu_ctl0;
> +	u32 gu_ctl1;
> +	u32 clock_gate_dis2;
> +};
> +
>  struct intel_gen6_power_mgmt {
>  	/* work and pm_iir are protected by dev_priv->irq_lock */
>  	struct work_struct work;
> @@ -1447,6 +1508,7 @@ struct drm_i915_private {
>  
>  	u32 suspend_count;
>  	struct i915_suspend_saved_registers regfile;
> +	struct vlv_s0ix_state vlv_s0ix_state;
>  
>  	struct {
>  		/*
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place
  2014-04-16 12:22   ` Ville Syrjälä
@ 2014-04-16 12:57     ` Imre Deak
  2014-04-24 21:06       ` Rodrigo Vivi
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-16 12:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 2139 bytes --]

On Wed, 2014-04-16 at 15:22 +0300, Ville Syrjälä wrote:
> On Mon, Apr 14, 2014 at 08:24:31PM +0300, Imre Deak wrote:
> > While checking the error capture path I noticed that this register is
> > read twice for GEN2, so fix this and also move the read where it's done
> > for other platforms.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> > index 4865ade..ba79b59 100644
> > --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> > @@ -1053,9 +1053,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
> >  		error->gfx_mode = I915_READ(GFX_MODE);
> >  	}
> >  
> > -	if (IS_GEN2(dev))
> > -		error->ier = I915_READ16(IER);
> > -
> >  	/* 2: Registers which belong to multiple generations */
> >  	if (INTEL_INFO(dev)->gen >= 7)
> >  		error->forcewake = I915_READ(FORCEWAKE_MT);
> > @@ -1079,7 +1076,10 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
> >  	if (HAS_PCH_SPLIT(dev))
> >  		error->ier = I915_READ(DEIER) | I915_READ(GTIER);
> >  	else {
> > -		error->ier = I915_READ(IER);
> > +		if (IS_GEN2(dev))
> > +			error->ier = I915_READ16(IER);
> > +		else
> > +			error->ier = I915_READ(IER);
> >  		for_each_pipe(pipe)
> >  			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
> >  	}
> 
> The IER handling seems fairly bogus all around. On VLV and PCH platforms
> we smash both the display and GT IER into the same u32. So probably no
> one can make any sense of the result.
> 
> Also I don't know why we try to dump only these two interrupt registers
> but not the others.
> 
> So seems like there's more work that needs to be done here.

Right, haven't noticed those.

This patch could be still applied as it's just one step towards fixing
the other issues you mentioned, but I think it should be anyway kept
separate (being just a cleanup patch).

--Imre

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
  2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
  2014-04-16 12:39   ` Ville Syrjälä
@ 2014-04-16 14:53   ` Daniel Vetter
  2014-04-16 16:01     ` Imre Deak
  2014-04-22 17:28   ` [PATCH v3 " Imre Deak
  2 siblings, 1 reply; 85+ messages in thread
From: Daniel Vetter @ 2014-04-16 14:53 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
> Add runtime PM support for VLV, but leave it disabled. The next patch
> enables it.
> 
> The suspend/resume sequence used is based on [1] and [2]. In practice we
> depend on the GT RC6 mechanism to save the HW context depending on the
> render and media power wells. By the time we run the runtime suspend
> callback the display side is also off and the HW context for that is
> managed by the display power domain framework.
> 
> Besides the above there are Gunit registers that depend on a system-wide
> power well. This power well goes off once the device enters any of the
> S0i[R123] states. To handle this scenario, save/restore these Gunit
> registers. Note that this is not the complete register set dictated by
> [2], to remove some overhead, registers that are known not to be used are
> ignored. Also some registers are fully setup by initialization functions
> called during resume, these are not saved either. The list of registers
> can be further reduced, see the TODO note in the code.
> 
> [1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
> [2] VLV2_S0IXRegs
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
>  2 files changed, 389 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 08e210c..bc206dd 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +/*
> + * Save all Gunit registers that may be lost after a D3 and a subsequent
> + * S0i[R123] transition. The list of registers needing a save/restore is
> + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
> + * registers in the following way:
> + * - Driver: saved/restored by the driver
> + * - Punit : saved/restored by the Punit firmware
> + * - No, w/o marking: no need to save/restore, since the register is R/O or
> + *                    used internally by the HW in a way that doesn't depend
> + *                    keeping the content across a suspend/resume.
> + * - Debug : used for debugging
> + *
> + * We save/restore all registers marked with 'Driver', with the following
> + * exceptions:
> + * - Registers out of use, including also registers marked with 'Debug'.
> + *   These have no effect on the driver's operation, so we don't save/restore
> + *   them to reduce the overhead.
> + * - Registers that are fully setup by an initialization function called from
> + *   the resume path. For example many clock gating and RPS/RC6 registers.
> + * - Registers that provide the right functionality with their reset defaults.
> + *
> + * TODO: Except for registers that based on the above 3 criteria can be safely
> + * ignored, we save/restore all others, practically treating the HW context as
> + * a black-box for the driver. Further investigation is needed to reduce the
> + * saved/restored registers even further, by following the same 3 criteria.
> + */
> +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
> +	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
> +	s->arb_mode		= I915_READ(ARB_MODE);
> +	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
> +	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
> +
> +	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +
> +	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
> +	s->ecochk		= I915_READ(GAM_ECOCHK);
> +	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
> +	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
> +
> +	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	s->g3dctl		= I915_READ(GEN7_G3DCTL);
> +	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
> +	s->mbctl		= I915_READ(GEN6_MBCTL);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
> +	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
> +	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
> +	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
> +	s->rstctl		= I915_READ(GEN7_RSTCTL);
> +	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
> +	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
> +	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
> +	s->ecobus		= I915_READ(ECOBUS);
> +	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
> +	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
> +	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
> +	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
> +	s->rcedata		= I915_READ(VLV_RCEDATA);
> +	s->spare2gh		= I915_READ(VLV_SPAREG2H);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	s->gt_imr		= I915_READ(GTIMR);
> +	s->gt_ier		= I915_READ(GTIER);
> +	s->pm_imr		= I915_READ(GEN6_PMIIR);
> +	s->pm_ier		= I915_READ(GEN6_PMIER);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	s->tilectl		= I915_READ(TILECTL);
> +	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
> +	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
> +	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
> +	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
> +	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
> +
> +	/*
> +	 * Not saving any of:
> +	 * DFT,		0x9800-0x9EC0
> +	 * SARB,	0xB000-0xB1FC
> +	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
> +	 * PCI CFG
> +	 */
> +}

Ok somehow I've missed this, and it totally freaks me out ;-) I really
don't like large-scale register save/restore code since it tends to be
race and brittle. And a bunch of these (e.g. for the interrupt stuff)
should be handled already by simply running the interrupt code again.

Most of the others probably just work if we run the ring init code again.
Thanks to Chris' work to not tear down ring structures (unfortunately
patches stuck in review limbo) that boils down to a simple call to the
ring init functions.

For the remaining ones we either ok with the reset value, or we definitely
miss a w/a somewhere or it's placed at the wrong place (e.g. in the
clock_gating function instead of the right ring init function).

Not sure yet what to do whit this patch, but I'm voting for further
discussion. Imo all the others can already be pulled in ...

Also I wonder whether hsw/bdw _really_ don't need any of this, or whether
it would be better to manually load the ring state into the hardware again
too. Another reason for more unified runtime pm code ;-)

Cheers, Daniel

> +
> +static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	u32 val;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
> +	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
> +	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
> +	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
> +	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
> +
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
> +
> +	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
> +	I915_WRITE(GAM_ECOCHK,		s->ecochk);
> +	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
> +	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
> +
> +	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
> +	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
> +	I915_WRITE(GEN6_MBCTL,		s->mbctl);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
> +	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
> +	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
> +	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
> +	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
> +	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
> +	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
> +	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
> +	I915_WRITE(ECOBUS,		s->ecobus);
> +	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
> +	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
> +	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
> +	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
> +	I915_WRITE(VLV_RCEDATA,		s->rcedata);
> +	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	I915_WRITE(GTIMR,		s->gt_imr);
> +	I915_WRITE(GTIER,		s->gt_ier);
> +	I915_WRITE(GEN6_PMIIR,		s->pm_imr);
> +	I915_WRITE(GEN6_PMIER,		s->pm_ier);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	I915_WRITE(TILECTL,			s->tilectl);
> +	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
> +	/*
> +	 * Preserve the GT allow wake and GFX force clock bit, they are not
> +	 * be restored, as they are used to control the s0ix suspend/resume
> +	 * sequence by the caller.
> +	 */
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= VLV_GTLC_ALLOWWAKEREQ;
> +	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	val &= VLV_GFX_CLK_FORCE_ON_BIT;
> +	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> +
> +	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
> +	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
> +	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
> +}
> +
>  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  {
>  	u32 val;
> @@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  #undef COND
>  }
>  
> +static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
> +{
> +	u32 val;
> +	int err = 0;
> +
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= ~VLV_GTLC_ALLOWWAKEREQ;
> +	if (allow)
> +		val |= VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +	POSTING_READ(VLV_GTLC_WAKE_CTRL);
> +
> +#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
> +	      allow)
> +	err = wait_for(COND, 1);
> +	if (err)
> +		DRM_ERROR("timeout disabling GT waking\n");
> +	return err;
> +#undef COND
> +}
> +
> +static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
> +				 bool wait_for_on)
> +{
> +	u32 mask;
> +	u32 val;
> +	int err;
> +
> +	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
> +	val = wait_for_on ? mask : 0;
> +#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
> +	if (COND)
> +		return 0;
> +
> +	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
> +			wait_for_on ? "on" : "off",
> +			I915_READ(VLV_GTLC_PW_STATUS));
> +
> +	/*
> +	 * RC6 transitioning can be delayed up to 2 msec (see
> +	 * valleyview_enable_rps), use 3 msec for safety.
> +	 */
> +	err = wait_for(COND, 3);
> +	if (err)
> +		DRM_ERROR("timeout waiting for GT wells to go %s\n",
> +			  wait_for_on ? "on" : "off");
> +
> +	return err;
> +#undef COND
> +}
> +
> +static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
> +{
> +	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
> +		return;
> +
> +	DRM_ERROR("GT register access while GT waking disabled\n");
> +	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
> +}
> +
> +static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
> +{
> +	u32 mask;
> +	int err;
> +
> +	/*
> +	 * Bspec defines the following GT well on flags as debug only, so
> +	 * don't treat them as hard failures.
> +	 */
> +	(void)vlv_wait_for_gt_wells(dev_priv, false);
> +
> +	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
> +	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, true);
> +	if (err)
> +		goto err1;
> +
> +	err = vlv_allow_gt_wake(dev_priv, false);
> +	if (err)
> +		goto err2;
> +	vlv_save_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (err)
> +		goto err2;
> +
> +	return 0;
> +
> +err2:
> +	/* For safety always re-enable waking and disable gfx clock forcing */
> +	vlv_allow_gt_wake(dev_priv, true);
> +err1:
> +	vlv_force_gfx_clock(dev_priv, false);
> +
> +	return err;
> +}
> +
> +static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	int err;
> +	int ret;
> +
> +	/*
> +	 * If any of the steps fail just try to continue, that's the best we
> +	 * can do at this point. Return the first error code (which will also
> +	 * leave RPM permanently disabled).
> +	 */
> +	ret = vlv_force_gfx_clock(dev_priv, true);
> +
> +	vlv_restore_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_allow_gt_wake(dev_priv, true);
> +	if (!ret)
> +		ret = err;
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (!ret)
> +		ret = err;
> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	intel_init_clock_gating(dev);
> +	i915_gem_restore_fences(dev);
> +
> +	return ret;
> +}
> +
>  static int intel_runtime_suspend(struct device *device)
>  {
>  	struct pci_dev *pdev = to_pci_dev(device);
> @@ -970,6 +1293,8 @@ static int intel_runtime_suspend(struct device *device)
>  		ret = 0;
>  	} if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_suspend(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_suspend(dev_priv);
>  	} else {
>  		ret = -ENODEV;
>  		WARN_ON(1);
> @@ -1018,6 +1343,8 @@ static int intel_runtime_resume(struct device *device)
>  		ret = snb_runtime_resume(dev_priv);
>  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_resume(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_resume(dev_priv);
>  	} else {
>  		WARN_ON(1);
>  		ret = -ENODEV;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3cac434..77cb7fc 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
>  	u32 savePCH_PORT_HOTPLUG;
>  };
>  
> +struct vlv_s0ix_state {
> +	/* GAM */
> +	u32 wr_watermark;
> +	u32 gfx_prio_ctrl;
> +	u32 arb_mode;
> +	u32 gfx_pend_tlb0;
> +	u32 gfx_pend_tlb1;
> +	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
> +	u32 media_max_req_count;
> +	u32 gfx_max_req_count;
> +	u32 render_hwsp;
> +	u32 ecochk;
> +	u32 bsd_hwsp;
> +	u32 blt_hwsp;
> +	u32 tlb_rd_addr;
> +
> +	/* MBC */
> +	u32 g3dctl;
> +	u32 gsckgctl;
> +	u32 mbctl;
> +
> +	/* GCP */
> +	u32 ucgctl1;
> +	u32 ucgctl3;
> +	u32 rcgctl1;
> +	u32 rcgctl2;
> +	u32 rstctl;
> +	u32 misccpctl;
> +
> +	/* GPM */
> +	u32 gfxpause;
> +	u32 rpdeuhwtc;
> +	u32 rpdeuc;
> +	u32 ecobus;
> +	u32 pwrdwnupctl;
> +	u32 rp_down_timeout;
> +	u32 rp_deucsw;
> +	u32 rcubmabdtmr;
> +	u32 rcedata;
> +	u32 spare2gh;
> +
> +	/* Display 1 CZ domain */
> +	u32 gt_imr;
> +	u32 gt_ier;
> +	u32 pm_imr;
> +	u32 pm_ier;
> +	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
> +
> +	/* GT SA CZ domain */
> +	u32 tilectl;
> +	u32 gt_fifoctl;
> +	u32 gtlc_wake_ctrl;
> +	u32 gtlc_survive;
> +	u32 pmwgicz;
> +
> +	/* Display 2 CZ domain */
> +	u32 gu_ctl0;
> +	u32 gu_ctl1;
> +	u32 clock_gate_dis2;
> +};
> +
>  struct intel_gen6_power_mgmt {
>  	/* work and pm_iir are protected by dev_priv->irq_lock */
>  	struct work_struct work;
> @@ -1447,6 +1508,7 @@ struct drm_i915_private {
>  
>  	u32 suspend_count;
>  	struct i915_suspend_saved_registers regfile;
> +	struct vlv_s0ix_state vlv_s0ix_state;
>  
>  	struct {
>  		/*
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
  2014-04-16 14:53   ` Daniel Vetter
@ 2014-04-16 16:01     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-16 16:01 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 19300 bytes --]

On Wed, 2014-04-16 at 16:53 +0200, Daniel Vetter wrote:
> On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
> > Add runtime PM support for VLV, but leave it disabled. The next patch
> > enables it.
> > 
> > The suspend/resume sequence used is based on [1] and [2]. In practice we
> > depend on the GT RC6 mechanism to save the HW context depending on the
> > render and media power wells. By the time we run the runtime suspend
> > callback the display side is also off and the HW context for that is
> > managed by the display power domain framework.
> > 
> > Besides the above there are Gunit registers that depend on a system-wide
> > power well. This power well goes off once the device enters any of the
> > S0i[R123] states. To handle this scenario, save/restore these Gunit
> > registers. Note that this is not the complete register set dictated by
> > [2], to remove some overhead, registers that are known not to be used are
> > ignored. Also some registers are fully setup by initialization functions
> > called during resume, these are not saved either. The list of registers
> > can be further reduced, see the TODO note in the code.
> > 
> > [1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
> > [2] VLV2_S0IXRegs
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
> >  2 files changed, 389 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 08e210c..bc206dd 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
> >  	return 0;
> >  }
> >  
> > +/*
> > + * Save all Gunit registers that may be lost after a D3 and a subsequent
> > + * S0i[R123] transition. The list of registers needing a save/restore is
> > + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
> > + * registers in the following way:
> > + * - Driver: saved/restored by the driver
> > + * - Punit : saved/restored by the Punit firmware
> > + * - No, w/o marking: no need to save/restore, since the register is R/O or
> > + *                    used internally by the HW in a way that doesn't depend
> > + *                    keeping the content across a suspend/resume.
> > + * - Debug : used for debugging
> > + *
> > + * We save/restore all registers marked with 'Driver', with the following
> > + * exceptions:
> > + * - Registers out of use, including also registers marked with 'Debug'.
> > + *   These have no effect on the driver's operation, so we don't save/restore
> > + *   them to reduce the overhead.
> > + * - Registers that are fully setup by an initialization function called from
> > + *   the resume path. For example many clock gating and RPS/RC6 registers.
> > + * - Registers that provide the right functionality with their reset defaults.
> > + *
> > + * TODO: Except for registers that based on the above 3 criteria can be safely
> > + * ignored, we save/restore all others, practically treating the HW context as
> > + * a black-box for the driver. Further investigation is needed to reduce the
> > + * saved/restored registers even further, by following the same 3 criteria.
> > + */
> > +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> > +{
> > +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> > +	int i;
> > +
> > +	/* GAM 0x4000-0x4770 */
> > +	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
> > +	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
> > +	s->arb_mode		= I915_READ(ARB_MODE);
> > +	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
> > +	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> > +		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
> > +
> > +	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> > +	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> > +
> > +	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
> > +	s->ecochk		= I915_READ(GAM_ECOCHK);
> > +	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
> > +	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
> > +
> > +	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
> > +
> > +	/* MBC 0x9024-0x91D0, 0x8500 */
> > +	s->g3dctl		= I915_READ(GEN7_G3DCTL);
> > +	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
> > +	s->mbctl		= I915_READ(GEN6_MBCTL);
> > +
> > +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> > +	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
> > +	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
> > +	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
> > +	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
> > +	s->rstctl		= I915_READ(GEN7_RSTCTL);
> > +	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
> > +
> > +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> > +	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
> > +	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
> > +	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
> > +	s->ecobus		= I915_READ(ECOBUS);
> > +	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
> > +	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
> > +	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
> > +	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
> > +	s->rcedata		= I915_READ(VLV_RCEDATA);
> > +	s->spare2gh		= I915_READ(VLV_SPAREG2H);
> > +
> > +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> > +	s->gt_imr		= I915_READ(GTIMR);
> > +	s->gt_ier		= I915_READ(GTIER);
> > +	s->pm_imr		= I915_READ(GEN6_PMIIR);
> > +	s->pm_ier		= I915_READ(GEN6_PMIER);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> > +		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
> > +
> > +	/* GT SA CZ domain, 0x100000-0x138124 */
> > +	s->tilectl		= I915_READ(TILECTL);
> > +	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
> > +	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
> > +	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> > +	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
> > +
> > +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> > +	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
> > +	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
> > +	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
> > +
> > +	/*
> > +	 * Not saving any of:
> > +	 * DFT,		0x9800-0x9EC0
> > +	 * SARB,	0xB000-0xB1FC
> > +	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
> > +	 * PCI CFG
> > +	 */
> > +}
> 
> Ok somehow I've missed this, and it totally freaks me out ;-) I really
> don't like large-scale register save/restore code since it tends to be
> race and brittle. And a bunch of these (e.g. for the interrupt stuff)
> should be handled already by simply running the interrupt code again.

I don't like it either and that's why I put a TODO in the comment above
to further reduce the list. Note that I already removed a bunch of the
registers that the spec says we should save/restore. Those I found to be
safe, but for all others there is no guarantee that we can do away with
this code. It needs time to go through all this stuff, so I chose this
solution leaving a way to optimize things further over time.

> Most of the others probably just work if we run the ring init code again.
> Thanks to Chris' work to not tear down ring structures (unfortunately
> patches stuck in review limbo) that boils down to a simple call to the
> ring init functions.

Yes, I noticed that and once it gets merged and someone cross-checks it
against this reglist we can remove some further registers. Until that
this code is at worst unneeded overhead, I don't see how it can cause
any functional issues.

> For the remaining ones we either ok with the reset value, or we definitely
> miss a w/a somewhere or it's placed at the wrong place (e.g. in the
> clock_gating function instead of the right ring init function).

Yes, those need to be checked and fixed up one-by-one, but again until
that happens this code is at worst unneeded overhead. But in case the
BIOS sets some value to its non-reset value it can save things.  

> Not sure yet what to do whit this patch, but I'm voting for further
> discussion. Imo all the others can already be pulled in ...

I'd vote for inclusion with a promise from me that I reduce the reglist
here over time.

> Also I wonder whether hsw/bdw _really_ don't need any of this, or whether
> it would be better to manually load the ring state into the hardware again
> too. Another reason for more unified runtime pm code ;-)

In this patchset I made the first step for a more unified PM code, could
we continue from there on? :)

--Imre

> 
> Cheers, Daniel
> 
> > +
> > +static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> > +{
> > +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> > +	u32 val;
> > +	int i;
> > +
> > +	/* GAM 0x4000-0x4770 */
> > +	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
> > +	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
> > +	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
> > +	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
> > +	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> > +		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
> > +
> > +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
> > +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
> > +
> > +	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
> > +	I915_WRITE(GAM_ECOCHK,		s->ecochk);
> > +	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
> > +	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
> > +
> > +	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
> > +
> > +	/* MBC 0x9024-0x91D0, 0x8500 */
> > +	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
> > +	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
> > +	I915_WRITE(GEN6_MBCTL,		s->mbctl);
> > +
> > +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> > +	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
> > +	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
> > +	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
> > +	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
> > +	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
> > +	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
> > +
> > +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> > +	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
> > +	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
> > +	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
> > +	I915_WRITE(ECOBUS,		s->ecobus);
> > +	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
> > +	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
> > +	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
> > +	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
> > +	I915_WRITE(VLV_RCEDATA,		s->rcedata);
> > +	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
> > +
> > +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> > +	I915_WRITE(GTIMR,		s->gt_imr);
> > +	I915_WRITE(GTIER,		s->gt_ier);
> > +	I915_WRITE(GEN6_PMIIR,		s->pm_imr);
> > +	I915_WRITE(GEN6_PMIER,		s->pm_ier);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> > +		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
> > +
> > +	/* GT SA CZ domain, 0x100000-0x138124 */
> > +	I915_WRITE(TILECTL,			s->tilectl);
> > +	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
> > +	/*
> > +	 * Preserve the GT allow wake and GFX force clock bit, they are not
> > +	 * be restored, as they are used to control the s0ix suspend/resume
> > +	 * sequence by the caller.
> > +	 */
> > +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> > +	val &= VLV_GTLC_ALLOWWAKEREQ;
> > +	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
> > +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> > +
> > +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> > +	val &= VLV_GFX_CLK_FORCE_ON_BIT;
> > +	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
> > +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> > +
> > +	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
> > +
> > +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> > +	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
> > +	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
> > +	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
> > +}
> > +
> >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> >  {
> >  	u32 val;
> > @@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> >  #undef COND
> >  }
> >  
> > +static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
> > +{
> > +	u32 val;
> > +	int err = 0;
> > +
> > +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> > +	val &= ~VLV_GTLC_ALLOWWAKEREQ;
> > +	if (allow)
> > +		val |= VLV_GTLC_ALLOWWAKEREQ;
> > +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> > +	POSTING_READ(VLV_GTLC_WAKE_CTRL);
> > +
> > +#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
> > +	      allow)
> > +	err = wait_for(COND, 1);
> > +	if (err)
> > +		DRM_ERROR("timeout disabling GT waking\n");
> > +	return err;
> > +#undef COND
> > +}
> > +
> > +static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
> > +				 bool wait_for_on)
> > +{
> > +	u32 mask;
> > +	u32 val;
> > +	int err;
> > +
> > +	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
> > +	val = wait_for_on ? mask : 0;
> > +#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
> > +	if (COND)
> > +		return 0;
> > +
> > +	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
> > +			wait_for_on ? "on" : "off",
> > +			I915_READ(VLV_GTLC_PW_STATUS));
> > +
> > +	/*
> > +	 * RC6 transitioning can be delayed up to 2 msec (see
> > +	 * valleyview_enable_rps), use 3 msec for safety.
> > +	 */
> > +	err = wait_for(COND, 3);
> > +	if (err)
> > +		DRM_ERROR("timeout waiting for GT wells to go %s\n",
> > +			  wait_for_on ? "on" : "off");
> > +
> > +	return err;
> > +#undef COND
> > +}
> > +
> > +static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
> > +{
> > +	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
> > +		return;
> > +
> > +	DRM_ERROR("GT register access while GT waking disabled\n");
> > +	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
> > +}
> > +
> > +static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
> > +{
> > +	u32 mask;
> > +	int err;
> > +
> > +	/*
> > +	 * Bspec defines the following GT well on flags as debug only, so
> > +	 * don't treat them as hard failures.
> > +	 */
> > +	(void)vlv_wait_for_gt_wells(dev_priv, false);
> > +
> > +	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
> > +	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
> > +
> > +	vlv_check_no_gt_access(dev_priv);
> > +
> > +	err = vlv_force_gfx_clock(dev_priv, true);
> > +	if (err)
> > +		goto err1;
> > +
> > +	err = vlv_allow_gt_wake(dev_priv, false);
> > +	if (err)
> > +		goto err2;
> > +	vlv_save_gunit_s0ix_state(dev_priv);
> > +
> > +	err = vlv_force_gfx_clock(dev_priv, false);
> > +	if (err)
> > +		goto err2;
> > +
> > +	return 0;
> > +
> > +err2:
> > +	/* For safety always re-enable waking and disable gfx clock forcing */
> > +	vlv_allow_gt_wake(dev_priv, true);
> > +err1:
> > +	vlv_force_gfx_clock(dev_priv, false);
> > +
> > +	return err;
> > +}
> > +
> > +static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> > +{
> > +	struct drm_device *dev = dev_priv->dev;
> > +	int err;
> > +	int ret;
> > +
> > +	/*
> > +	 * If any of the steps fail just try to continue, that's the best we
> > +	 * can do at this point. Return the first error code (which will also
> > +	 * leave RPM permanently disabled).
> > +	 */
> > +	ret = vlv_force_gfx_clock(dev_priv, true);
> > +
> > +	vlv_restore_gunit_s0ix_state(dev_priv);
> > +
> > +	err = vlv_allow_gt_wake(dev_priv, true);
> > +	if (!ret)
> > +		ret = err;
> > +
> > +	err = vlv_force_gfx_clock(dev_priv, false);
> > +	if (!ret)
> > +		ret = err;
> > +
> > +	vlv_check_no_gt_access(dev_priv);
> > +
> > +	intel_init_clock_gating(dev);
> > +	i915_gem_restore_fences(dev);
> > +
> > +	return ret;
> > +}
> > +
> >  static int intel_runtime_suspend(struct device *device)
> >  {
> >  	struct pci_dev *pdev = to_pci_dev(device);
> > @@ -970,6 +1293,8 @@ static int intel_runtime_suspend(struct device *device)
> >  		ret = 0;
> >  	} if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> >  		ret = hsw_runtime_suspend(dev_priv);
> > +	} else if (IS_VALLEYVIEW(dev)) {
> > +		ret = vlv_runtime_suspend(dev_priv);
> >  	} else {
> >  		ret = -ENODEV;
> >  		WARN_ON(1);
> > @@ -1018,6 +1343,8 @@ static int intel_runtime_resume(struct device *device)
> >  		ret = snb_runtime_resume(dev_priv);
> >  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> >  		ret = hsw_runtime_resume(dev_priv);
> > +	} else if (IS_VALLEYVIEW(dev)) {
> > +		ret = vlv_runtime_resume(dev_priv);
> >  	} else {
> >  		WARN_ON(1);
> >  		ret = -ENODEV;
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 3cac434..77cb7fc 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
> >  	u32 savePCH_PORT_HOTPLUG;
> >  };
> >  
> > +struct vlv_s0ix_state {
> > +	/* GAM */
> > +	u32 wr_watermark;
> > +	u32 gfx_prio_ctrl;
> > +	u32 arb_mode;
> > +	u32 gfx_pend_tlb0;
> > +	u32 gfx_pend_tlb1;
> > +	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
> > +	u32 media_max_req_count;
> > +	u32 gfx_max_req_count;
> > +	u32 render_hwsp;
> > +	u32 ecochk;
> > +	u32 bsd_hwsp;
> > +	u32 blt_hwsp;
> > +	u32 tlb_rd_addr;
> > +
> > +	/* MBC */
> > +	u32 g3dctl;
> > +	u32 gsckgctl;
> > +	u32 mbctl;
> > +
> > +	/* GCP */
> > +	u32 ucgctl1;
> > +	u32 ucgctl3;
> > +	u32 rcgctl1;
> > +	u32 rcgctl2;
> > +	u32 rstctl;
> > +	u32 misccpctl;
> > +
> > +	/* GPM */
> > +	u32 gfxpause;
> > +	u32 rpdeuhwtc;
> > +	u32 rpdeuc;
> > +	u32 ecobus;
> > +	u32 pwrdwnupctl;
> > +	u32 rp_down_timeout;
> > +	u32 rp_deucsw;
> > +	u32 rcubmabdtmr;
> > +	u32 rcedata;
> > +	u32 spare2gh;
> > +
> > +	/* Display 1 CZ domain */
> > +	u32 gt_imr;
> > +	u32 gt_ier;
> > +	u32 pm_imr;
> > +	u32 pm_ier;
> > +	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
> > +
> > +	/* GT SA CZ domain */
> > +	u32 tilectl;
> > +	u32 gt_fifoctl;
> > +	u32 gtlc_wake_ctrl;
> > +	u32 gtlc_survive;
> > +	u32 pmwgicz;
> > +
> > +	/* Display 2 CZ domain */
> > +	u32 gu_ctl0;
> > +	u32 gu_ctl1;
> > +	u32 clock_gate_dis2;
> > +};
> > +
> >  struct intel_gen6_power_mgmt {
> >  	/* work and pm_iir are protected by dev_priv->irq_lock */
> >  	struct work_struct work;
> > @@ -1447,6 +1508,7 @@ struct drm_i915_private {
> >  
> >  	u32 suspend_count;
> >  	struct i915_suspend_saved_registers regfile;
> > +	struct vlv_s0ix_state vlv_s0ix_state;
> >  
> >  	struct {
> >  		/*
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq
  2014-04-14 17:24 ` [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq Imre Deak
@ 2014-04-16 17:31   ` Ville Syrjälä
  2014-04-18 13:16   ` [PATCH v3 " Imre Deak
  1 sibling, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 17:31 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:38PM +0300, Imre Deak wrote:
> This is needed by the next patch moving the call out from platform
> specific RPM callbacks to platform independent code.
> 
> No functional change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c      |  2 --
>  drivers/gpu/drm/i915/intel_display.c |  2 --
>  drivers/gpu/drm/i915/intel_pm.c      | 18 +++++++++++++++---
>  3 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index f3f9a33..afc31e3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -899,9 +899,7 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
>  
>  	intel_init_pch_refclk(dev);
>  	i915_gem_init_swizzling(dev);
> -	mutex_lock(&dev_priv->rps.hw_lock);
>  	gen6_update_ring_freq(dev);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
>  }
>  
>  static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index bda79ec..596ae69 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -7088,9 +7088,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
>  
>  	intel_prepare_ddi(dev);
>  	i915_gem_init_swizzling(dev);
> -	mutex_lock(&dev_priv->rps.hw_lock);
>  	gen6_update_ring_freq(dev);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
>  }
>  
>  static void snb_modeset_global_resources(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 3068f51..f88d64d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3522,7 +3522,7 @@ static void gen6_enable_rps(struct drm_device *dev)
>  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }
>  
> -void gen6_update_ring_freq(struct drm_device *dev)
> +static void __gen6_update_ring_freq(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int min_freq = 15;
> @@ -3592,6 +3592,18 @@ void gen6_update_ring_freq(struct drm_device *dev)
>  	}
>  }
>  
> +void gen6_update_ring_freq(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!(INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)))

This is a bit hard to parse.

if (gen < 6 || VLV)

would be easier.

> +		return;
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	__gen6_update_ring_freq(dev);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +}
> +
>  int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
>  {
>  	u32 val, rp0;
> @@ -4563,10 +4575,10 @@ static void intel_gen6_powersave_work(struct work_struct *work)
>  		valleyview_enable_rps(dev);
>  	} else if (IS_BROADWELL(dev)) {
>  		gen8_enable_rps(dev);
> -		gen6_update_ring_freq(dev);
> +		__gen6_update_ring_freq(dev);
>  	} else {
>  		gen6_enable_rps(dev);
> -		gen6_update_ring_freq(dev);
> +		__gen6_update_ring_freq(dev);
>  	}
>  	dev_priv->rps.enabled = true;
>  	mutex_unlock(&dev_priv->rps.hw_lock);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 19/25] drm/i915: reinit GT power save during resume
  2014-04-14 17:24 ` [PATCH v2 19/25] drm/i915: reinit GT power save during resume Imre Deak
@ 2014-04-16 17:46   ` Ville Syrjälä
  2014-04-18 10:51     ` Imre Deak
  2014-04-22 17:21   ` [PATCH v3 " Imre Deak
  1 sibling, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 17:46 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:40PM +0300, Imre Deak wrote:
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b87109c..1f88917 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -920,6 +920,7 @@ static int intel_runtime_suspend(struct device *device)
>  	DRM_DEBUG_KMS("Suspending device\n");
>  
>  	intel_runtime_pm_disable_interrupts(dev);
> +	cancel_work_sync(&dev_priv->rps.work);

What happens if the rps work still runs after
intel_runtime_pm_disable_interrupts()? To me it looks like it can hit
the WARN in snb_update_pm_irq(), or there's a race and it'll miss the
dev_priv->pm.irqs_disabled update and unmask something in PMIMR.

Hmm, I guess the same issue already exists in intel_disable_gt_powersave().

But since it's just PMIMR I guess it's not really dangerous since IER
isn't touched so we don't actually get any interrupts. But it feels a bit
fragile.

>  
>  	if (IS_GEN6(dev))
>  		;
> @@ -968,6 +969,7 @@ static int intel_runtime_resume(struct device *device)
>  
>  	i915_gem_init_swizzling(dev);
>  	gen6_update_ring_freq(dev);
> +	intel_reset_gt_powersave(dev);
>  
>  	intel_runtime_pm_restore_interrupts(dev);
>  
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock
  2014-04-14 17:24 ` [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock Imre Deak
@ 2014-04-16 17:49   ` Ville Syrjälä
  2014-04-18 13:35   ` [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off Imre Deak
  1 sibling, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-16 17:49 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:42PM +0300, Imre Deak wrote:
> This will be needed by the VLV runtime PM helpers too, so factor it out.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 37 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h |  1 +
>  drivers/gpu/drm/i915/intel_pm.c | 16 ++--------------
>  3 files changed, 40 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 1f88917..0609f77 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -905,6 +905,43 @@ static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  	hsw_disable_pc8(dev_priv);
>  }
>  
> +int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> +{
> +	u32 val;
> +	int err;
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
> +
> +#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
> +	/* Wait for a previous force on/off to settle */
> +	if (force_on) {
> +		err = wait_for(!COND, 5);
> +		if (err) {
> +			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
> +				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> +			return err;
> +		}
> +	}

We didn't do this part previously. Not sure if it's needed or not, but
maybe add a note to the commit message about this.

> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
> +	if (force_on)
> +		val |= VLV_GFX_CLK_FORCE_ON_BIT;
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> +
> +	if (!force_on)
> +		return 0;
> +
> +	err = wait_for(COND, 5);
> +	if (err)
> +		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
> +			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> +
> +	return err;
> +#undef COND
> +}
> +
>  static int intel_runtime_suspend(struct device *device)
>  {
>  	struct pci_dev *pdev = to_pci_dev(device);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 5254f4b..3cac434 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1968,6 +1968,7 @@ extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
>  extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
>  extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
>  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
> +int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
>  
>  extern void intel_console_resume(struct work_struct *work);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index bc38213..5a61075 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3129,16 +3129,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
>  	/* Mask turbo interrupt so that they will not come in between */
>  	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
>  
> -	/* Bring up the Gfx clock */
> -	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
> -				VLV_GFX_CLK_FORCE_ON_BIT);
> -
> -	if (wait_for(((VLV_GFX_CLK_STATUS_BIT &
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 5)) {
> -			DRM_ERROR("GFX_CLK_ON request timed out\n");
> -		return;
> -	}
> +	vlv_force_gfx_clock(dev_priv, true);
>  
>  	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
>  
> @@ -3149,10 +3140,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
>  				& GENFREQSTATUS) == 0, 5))
>  		DRM_ERROR("timed out waiting for Punit\n");
>  
> -	/* Release the Gfx clock */
> -	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
> -				~VLV_GFX_CLK_FORCE_ON_BIT);
> +	vlv_force_gfx_clock(dev_priv, false);
>  
>  	I915_WRITE(GEN6_PMINTRMSK,
>  		   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 00/25] vlv: add support for RPM
  2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
                   ` (25 preceding siblings ...)
  2014-04-14 17:41 ` [PATCH v2 26/25] drm/i915: vlv: enable runtime PM Imre Deak
@ 2014-04-17 11:00 ` Ville Syrjälä
  26 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-17 11:00 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:21PM +0300, Imre Deak wrote:
> For a description of this patchset see the previous cover letter [1].
> 
> Tested on HSW (non-ULT), VLV with igt/kms_flip and pm_pc8.
> 
> v2:
> - addressed comments about getting the proper runtime PM references in
>   debugfs (Daniel, Paulo, Ville)
> - disable RPM if RC6 is disabled for all platforms, not just VLV
>   (Daniel)
> - refactored the runtime PM callbacks pulling platform independent
>   teardown/re-init code to the generic runtime suspend/resume callbacks
>   (Daniel)
> - fixed a couple of issues I bumped into while checking the RC6/RPS
>   and the GPU reset error capturing path
> 
> [1]
> http://lists.freedesktop.org/archives/intel-gfx/2014-April/043208.html

For patches 01-08, 12-13, 15-16, 18, 20, 22, 24:
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

23,25,26 I didn't really look at so far, and the rest had some small
issues I pointed out.

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v2 19/25] drm/i915: reinit GT power save during resume
  2014-04-16 17:46   ` Ville Syrjälä
@ 2014-04-18 10:51     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-18 10:51 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, 2014-04-16 at 20:46 +0300, Ville Syrjälä wrote:
> On Mon, Apr 14, 2014 at 08:24:40PM +0300, Imre Deak wrote:
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index b87109c..1f88917 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -920,6 +920,7 @@ static int intel_runtime_suspend(struct device *device)
> >  	DRM_DEBUG_KMS("Suspending device\n");
> >  
> >  	intel_runtime_pm_disable_interrupts(dev);
> > +	cancel_work_sync(&dev_priv->rps.work);
> 
> What happens if the rps work still runs after
> intel_runtime_pm_disable_interrupts()? To me it looks like it can hit
> the WARN in snb_update_pm_irq(), or there's a race and it'll miss the
> dev_priv->pm.irqs_disabled update and unmask something in PMIMR.
> 
> Hmm, I guess the same issue already exists in intel_disable_gt_powersave().
> 
> But since it's just PMIMR I guess it's not really dangerous since IER
> isn't touched so we don't actually get any interrupts. But it feels a bit
> fragile.

Ok, this was subtle thanks for pointing it out.

I see now that the race you describe is present already before this
change both here and on the system suspend/driver cleanup path calling
intel_disable_gt_powersave(). I think it's not an issue during 
intel_disable_gt_powersave(), since it's called with all i915 interrupts
disabled.

Here we may get that WARN right after the
intel_runtime_pm_disable_interrupts() call, but other than that it is
the same scenario as with intel_disable_gt_powersave(), since we disable
all interrupts.

Otoh, it's also guaranteed that we don't get any RPS interrupts at this
point, since we get here only after gen6_rps_idle() has been called
after which the HW is supposed to stay quiescent with the minimum RPS
freq set. The next possible RPS interrupt is only at a subsequent GT
command we submit, but before that we'll get an RPM ref. So what I'd
suggest here to avoid the WARN (and the above race it entails) is to
change the order of intel_runtime_pm_disable_interrupts() and
cancel_work_sync(). After cancel_work_sync() it's guaranteed that the
work won't be rearmed since we can't get any RPS interrupts here. I
could also add a comment explaining this.

--Imre

> 
> >  
> >  	if (IS_GEN6(dev))
> >  		;
> > @@ -968,6 +969,7 @@ static int intel_runtime_resume(struct device *device)
> >  
> >  	i915_gem_init_swizzling(dev);
> >  	gen6_update_ring_freq(dev);
> > +	intel_reset_gt_powersave(dev);
> >  
> >  	intel_runtime_pm_restore_interrupts(dev);
> >  
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


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

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

* Re: [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg
  2014-04-16 12:17   ` Ville Syrjälä
@ 2014-04-18 11:44     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-18 11:44 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, 2014-04-16 at 15:17 +0300, Ville Syrjälä wrote:
> On Mon, Apr 14, 2014 at 08:24:32PM +0300, Imre Deak wrote:
> > While checking the error capture path I noticed that we lacked the
> > power domain-on check for PIPESTAT so fix this by moving that to where
> > the rest of pipe registers are captured.
> > 
> > The move also revealed that we actually don't include this register in
> > the error report, so fix that too.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h       | 1 -
> >  drivers/gpu/drm/i915/i915_gpu_error.c | 3 ---
> >  drivers/gpu/drm/i915/intel_display.c  | 3 +++
> >  3 files changed, 3 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 7d6acb4..5254f4b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -325,7 +325,6 @@ struct drm_i915_error_state {
> >  	u32 gab_ctl;
> >  	u32 gfx_mode;
> >  	u32 extra_instdone[I915_NUM_INSTDONE_REG];
> > -	u32 pipestat[I915_MAX_PIPES];
> >  	u64 fence[I915_MAX_NUM_FENCES];
> >  	struct intel_overlay_error_state *overlay;
> >  	struct intel_display_error_state *display;
> > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> > index ba79b59..7b5cc08 100644
> > --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> > @@ -1028,7 +1028,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
> >  				   struct drm_i915_error_state *error)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> > -	int pipe;
> >  
> >  	/* General organization
> >  	 * 1. Registers specific to a single generation
> > @@ -1080,8 +1079,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
> >  			error->ier = I915_READ16(IER);
> >  		else
> >  			error->ier = I915_READ(IER);
> > -		for_each_pipe(pipe)
> > -			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
> >  	}
> >  
> >  	/* 4: Everything else */
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 1390ab5..4d8d875 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -11925,6 +11925,7 @@ struct intel_display_error_state {
> >  	struct intel_pipe_error_state {
> >  		bool power_domain_on;
> >  		u32 source;
> > +		u32 stat;
> >  	} pipe[I915_MAX_PIPES];
> >  
> >  	struct intel_plane_error_state {
> > @@ -12006,6 +12007,7 @@ intel_display_capture_error_state(struct drm_device *dev)
> >  		}
> >  
> >  		error->pipe[i].source = I915_READ(PIPESRC(i));
> > +		error->pipe[i].stat = I915_READ(PIPESTAT(i));
> 
> This needs a !HAS_PCH_SPLIT check

Ok, forgot that. Also noticed now that it should be actually gen<=5 ||
vlv, I can fix that too while at it.

> 
> >  	}
> >  
> >  	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
> > @@ -12056,6 +12058,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
> >  		err_printf(m, "  Power: %s\n",
> >  			   error->pipe[i].power_domain_on ? "on" : "off");
> >  		err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
> > +		err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
> >  
> >  		err_printf(m, "Plane [%d]:\n", i);
> >  		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


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

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

* [PATCH v3] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-14 17:24 ` [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
  2014-04-16 12:11   ` Ville Syrjälä
@ 2014-04-18 12:47   ` Imre Deak
  2014-04-22 19:38     ` Daniel Vetter
  2014-04-22 22:13     ` [PATCH v4] " Imre Deak
  1 sibling, 2 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-18 12:47 UTC (permalink / raw)
  To: intel-gfx

Atm we can end up in the GPU reset deferred work in D3 state if the last
runtime PM reference is dropped between detecting a hang/scheduling the
work and executing the work. At least one such case I could trigger is
the simulated reset via the i915_wedged debugfs entry. Fix this by
disabling RPM before scheduling the work until the end of the work.

v2:
- Instead of getting/putting the RPM reference in the reset work itself,
  get it already before scheduling the work. By this we also prevent
  going to D3 before the work gets to run, in addition to making sure
  that we run the work itself in D0. (Ville, Daniel)
v3:
- fix inverted logic fail when putting the RPM ref on behalf of a
  cancelled GPU reset work (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
 drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 0b38f88..f792576 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
 
 	/* Free error state after interrupts are fully disabled. */
 	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
-	cancel_work_sync(&dev_priv->gpu_error.work);
+	if (cancel_work_sync(&dev_priv->gpu_error.work))
+		/*
+		 * The following won't make any difference in the PM state,
+		 * since RPM is disabled already, but do it still for
+		 * consistency.
+		 */
+		intel_runtime_pm_put(dev_priv);
 	i915_destroy_error_state(dev);
 
 	if (dev->pdev->msi_enabled)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a651d0d..5e079d8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
 		 */
 		i915_error_wake_up(dev_priv, true);
 	}
+
+	/* Drop the ref we took when scheduling this work. */
+	intel_runtime_pm_put(dev_priv);
 }
 
 static void i915_report_and_clear_eir(struct drm_device *dev)
@@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
 	 * state of outstanding pagelips). Hence it must not be run on our own
 	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
 	 * code will deadlock.
+	 *
+	 * It's guaranteed that here we are in D0 state, since we can only get
+	 * here via one of the following paths:
+	 * - From an IRQ handler's error detection. -> The driver must make
+	 *   sure that IRQs are unmasked only while holding an RPM ref.
+	 * - From hang-check due to a blocked request. -> The request holds an
+	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
+	 *   won't be called until the request is finished.
+	 * - From hang-check due to a flip hang. -> We have an RPM ref because
+	 *   of the active modeset.
+	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
+	 *   RPM ref.
+	 * Take here an atomic RPM ref still to make sure that we don't
+	 * re-enter D3 until the error work gets to run and completes the
+	 * reset.
 	 */
-	schedule_work(&dev_priv->gpu_error.work);
+	if (schedule_work(&dev_priv->gpu_error.work))
+		intel_runtime_pm_get_noresume(dev_priv);
 }
 
 static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
-- 
1.8.4

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

* [PATCH v3 11/25] drm/i915: add missing error capturing of the PIPESTAT reg
  2014-04-14 17:24 ` [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg Imre Deak
  2014-04-16 12:17   ` Ville Syrjälä
@ 2014-04-18 12:55   ` Imre Deak
  2014-04-23  7:53     ` Ville Syrjälä
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-18 12:55 UTC (permalink / raw)
  To: intel-gfx

While checking the error capture path I noticed that we lacked the
power domain-on check for PIPESTAT so fix this by moving that to where
the rest of pipe registers are captured.

The move also revealed that we actually don't include this register in
the error report, so fix that too.

v2:
- patch introduced in v2 of the patchset
v3:
- add back !HAS_PCH_SPLIT check (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>

[ Ignore my previous comment about the gen<=5 || vlv check, I realized
  that it's the same as !HAS_PCH_SPLIT. ] 

---
 drivers/gpu/drm/i915/i915_drv.h       | 1 -
 drivers/gpu/drm/i915/i915_gpu_error.c | 3 ---
 drivers/gpu/drm/i915/intel_display.c  | 5 +++++
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d6acb4..5254f4b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -325,7 +325,6 @@ struct drm_i915_error_state {
 	u32 gab_ctl;
 	u32 gfx_mode;
 	u32 extra_instdone[I915_NUM_INSTDONE_REG];
-	u32 pipestat[I915_MAX_PIPES];
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index ba79b59..7b5cc08 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1028,7 +1028,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 				   struct drm_i915_error_state *error)
 {
 	struct drm_device *dev = dev_priv->dev;
-	int pipe;
 
 	/* General organization
 	 * 1. Registers specific to a single generation
@@ -1080,8 +1079,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 			error->ier = I915_READ16(IER);
 		else
 			error->ier = I915_READ(IER);
-		for_each_pipe(pipe)
-			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 	}
 
 	/* 4: Everything else */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cd68a24..a2f3790 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11901,6 +11901,7 @@ struct intel_display_error_state {
 	struct intel_pipe_error_state {
 		bool power_domain_on;
 		u32 source;
+		u32 stat;
 	} pipe[I915_MAX_PIPES];
 
 	struct intel_plane_error_state {
@@ -11982,6 +11983,9 @@ intel_display_capture_error_state(struct drm_device *dev)
 		}
 
 		error->pipe[i].source = I915_READ(PIPESRC(i));
+
+		if (!HAS_PCH_SPLIT(dev))
+			error->pipe[i].stat = I915_READ(PIPESTAT(i));
 	}
 
 	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
@@ -12032,6 +12036,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 		err_printf(m, "  Power: %s\n",
 			   error->pipe[i].power_domain_on ? "on" : "off");
 		err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
+		err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
 
 		err_printf(m, "Plane [%d]:\n", i);
 		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
-- 
1.8.4

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

* [PATCH v3 14/25] drm/i915: sanitize enable_rc6 option
  2014-04-14 17:24 ` [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option Imre Deak
  2014-04-16 12:28   ` Ville Syrjälä
@ 2014-04-18 13:01   ` Imre Deak
  2014-04-23  7:58     ` Ville Syrjälä
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-18 13:01 UTC (permalink / raw)
  To: intel-gfx

Atm, an invalid enable_rc6 module option will be silently ignored, so
emit an info message about it. Doing an early sanitization we can also
reuse intel_enable_rc6() in a follow-up patch to see if RC6 is actually
enabled. Currently the caller would have to filter a non-zero return
value based on the platform we are running on. For example on VLV with
i915.enable_rc6 set to 2, RC6 won't be enabled but atm
intel_enable_rc6() would still return 2 in this case.

v2:
- simplify the platform check condition (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a56f6b1..075405a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3262,15 +3262,32 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
 		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
 }
 
-int intel_enable_rc6(const struct drm_device *dev)
+static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
 {
 	/* No RC6 before Ironlake */
 	if (INTEL_INFO(dev)->gen < 5)
 		return 0;
 
+	/* RC6 is only on Ironlake mobile not on desktop */
+	if (INTEL_INFO(dev)->gen == 5 && !IS_IRONLAKE_M(dev))
+		return 0;
+
 	/* Respect the kernel parameter if it is set */
-	if (i915.enable_rc6 >= 0)
-		return i915.enable_rc6;
+	if (enable_rc6 >= 0) {
+		int mask;
+
+		if (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
+			mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
+			       INTEL_RC6pp_ENABLE;
+		else
+			mask = INTEL_RC6_ENABLE;
+
+		if ((enable_rc6 & mask) != enable_rc6)
+			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
+				 enable_rc6, enable_rc6 & mask, mask);
+
+		return enable_rc6 & mask;
+	}
 
 	/* Disable RC6 on Ironlake */
 	if (INTEL_INFO(dev)->gen == 5)
@@ -3282,6 +3299,11 @@ int intel_enable_rc6(const struct drm_device *dev)
 	return INTEL_RC6_ENABLE;
 }
 
+int intel_enable_rc6(const struct drm_device *dev)
+{
+	return i915.enable_rc6;
+}
+
 static void gen6_enable_rps_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4496,6 +4518,8 @@ static void intel_init_emon(struct drm_device *dev)
 
 void intel_init_gt_powersave(struct drm_device *dev)
 {
+	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
+
 	if (IS_VALLEYVIEW(dev))
 		valleyview_setup_pctx(dev);
 }
-- 
1.8.4

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

* [PATCH v3 17/25] drm/i915: factor out gen6_update_ring_freq
  2014-04-14 17:24 ` [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq Imre Deak
  2014-04-16 17:31   ` Ville Syrjälä
@ 2014-04-18 13:16   ` Imre Deak
  2014-04-23  7:59     ` Ville Syrjälä
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-18 13:16 UTC (permalink / raw)
  To: intel-gfx

This is needed by the next patch moving the call out from platform
specific RPM callbacks to platform independent code.

No functional change.

v2:
- patch introduce in v2 of the patchset
v3:
- simplify platform check condition (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      |  2 --
 drivers/gpu/drm/i915/intel_display.c |  2 --
 drivers/gpu/drm/i915/intel_pm.c      | 18 +++++++++++++++---
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f3f9a33..afc31e3 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -899,9 +899,7 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
 
 	intel_init_pch_refclk(dev);
 	i915_gem_init_swizzling(dev);
-	mutex_lock(&dev_priv->rps.hw_lock);
 	gen6_update_ring_freq(dev);
-	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
 static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a902e13..bb7671d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7065,9 +7065,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 
 	intel_prepare_ddi(dev);
 	i915_gem_init_swizzling(dev);
-	mutex_lock(&dev_priv->rps.hw_lock);
 	gen6_update_ring_freq(dev);
-	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
 static void snb_modeset_global_resources(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 4e30b15..46f7b1a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3525,7 +3525,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
-void gen6_update_ring_freq(struct drm_device *dev)
+static void __gen6_update_ring_freq(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int min_freq = 15;
@@ -3595,6 +3595,18 @@ void gen6_update_ring_freq(struct drm_device *dev)
 	}
 }
 
+void gen6_update_ring_freq(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (INTEL_INFO(dev)->gen < 6 || IS_VALLEYVIEW(dev))
+		return;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	__gen6_update_ring_freq(dev);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
 int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
 {
 	u32 val, rp0;
@@ -4566,10 +4578,10 @@ static void intel_gen6_powersave_work(struct work_struct *work)
 		valleyview_enable_rps(dev);
 	} else if (IS_BROADWELL(dev)) {
 		gen8_enable_rps(dev);
-		gen6_update_ring_freq(dev);
+		__gen6_update_ring_freq(dev);
 	} else {
 		gen6_enable_rps(dev);
-		gen6_update_ring_freq(dev);
+		__gen6_update_ring_freq(dev);
 	}
 	dev_priv->rps.enabled = true;
 	mutex_unlock(&dev_priv->rps.hw_lock);
-- 
1.8.4

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

* [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off
  2014-04-14 17:24 ` [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock Imre Deak
  2014-04-16 17:49   ` Ville Syrjälä
@ 2014-04-18 13:35   ` Imre Deak
  2014-04-23  8:11     ` Ville Syrjälä
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-18 13:35 UTC (permalink / raw)
  To: intel-gfx

This will be needed by the VLV runtime PM helpers too, so factor it out.

Also add a safety check for the case where the previous force-off is
still pending, since I'm not sure if Punit can handle a new setting
while the previous one hasn't settled yet.

v2:
- unchanged
v3:
- add a note to the commit message about the safety check (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 37 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  1 +
 drivers/gpu/drm/i915/intel_pm.c | 16 ++--------------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 1f88917..795caea 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -905,6 +905,43 @@ static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
 	hsw_disable_pc8(dev_priv);
 }
 
+int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
+{
+	u32 val;
+	int err;
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
+
+#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
+	/* Wait for a previous force-off to settle */
+	if (force_on) {
+		err = wait_for(!COND, 5);
+		if (err) {
+			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
+				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
+			return err;
+		}
+	}
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
+	if (force_on)
+		val |= VLV_GFX_CLK_FORCE_ON_BIT;
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
+
+	if (!force_on)
+		return 0;
+
+	err = wait_for(COND, 5);
+	if (err)
+		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
+			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
+
+	return err;
+#undef COND
+}
+
 static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5254f4b..3cac434 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1968,6 +1968,7 @@ extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
+int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 
 extern void intel_console_resume(struct work_struct *work);
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c45e5c1..d64ac32 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3129,16 +3129,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 	/* Mask turbo interrupt so that they will not come in between */
 	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
 
-	/* Bring up the Gfx clock */
-	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
-				VLV_GFX_CLK_FORCE_ON_BIT);
-
-	if (wait_for(((VLV_GFX_CLK_STATUS_BIT &
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 5)) {
-			DRM_ERROR("GFX_CLK_ON request timed out\n");
-		return;
-	}
+	vlv_force_gfx_clock(dev_priv, true);
 
 	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
 
@@ -3149,10 +3140,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
 				& GENFREQSTATUS) == 0, 5))
 		DRM_ERROR("timed out waiting for Punit\n");
 
-	/* Release the Gfx clock */
-	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
-		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
-				~VLV_GFX_CLK_FORCE_ON_BIT);
+	vlv_force_gfx_clock(dev_priv, false);
 
 	I915_WRITE(GEN6_PMINTRMSK,
 		   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
-- 
1.8.4

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

* [PATCH v3 19/25] drm/i915: reinit GT power save during resume
  2014-04-14 17:24 ` [PATCH v2 19/25] drm/i915: reinit GT power save during resume Imre Deak
  2014-04-16 17:46   ` Ville Syrjälä
@ 2014-04-22 17:21   ` Imre Deak
  2014-04-23  8:06     ` Ville Syrjälä
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-22 17:21 UTC (permalink / raw)
  To: intel-gfx

During runtime suspend there can be a last pending rps.work, so make
sure it's canceled. Note that in the runtime suspend callback we can't
get any RPS interrupts since it's called only after the GPU goes idle
and we set the minimum RPS frequency. The next possibility for an RPS
interrupt is only after getting an RPM ref (for example because of a new
GPU command) and calling the RPM resume callback.

v2:
- patch introduced in v2 of the patchset
v3:
- Change the order of canceling the rps.work and disabling interrupts to
  avoid the race between interrupt disabling and the the rps.work. Race
  spotted by Ville.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b87109c..edd4ab8 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -919,6 +919,12 @@ static int intel_runtime_suspend(struct device *device)
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
+	/*
+	 * rps.work can't be rearmed here, since we get here only after making
+	 * sure the GPU is idle and the RPS freq is set to the minimum. See
+	 * intel_mark_idle().
+	 */
+	cancel_work_sync(&dev_priv->rps.work);
 	intel_runtime_pm_disable_interrupts(dev);
 
 	if (IS_GEN6(dev))
@@ -970,6 +976,7 @@ static int intel_runtime_resume(struct device *device)
 	gen6_update_ring_freq(dev);
 
 	intel_runtime_pm_restore_interrupts(dev);
+	intel_reset_gt_powersave(dev);
 
 	DRM_DEBUG_KMS("Device resumed\n");
 	return 0;
-- 
1.8.4

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

* [PATCH v3 25/25] drm/i915: vlv: add runtime PM support
  2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
  2014-04-16 12:39   ` Ville Syrjälä
  2014-04-16 14:53   ` Daniel Vetter
@ 2014-04-22 17:28   ` Imre Deak
  2014-04-22 22:09     ` [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
                       ` (2 more replies)
  2 siblings, 3 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-22 17:28 UTC (permalink / raw)
  To: intel-gfx

Add runtime PM support for VLV, but leave it disabled. The next patch
enables it.

The suspend/resume sequence used is based on [1] and [2]. In practice we
depend on the GT RC6 mechanism to save the HW context depending on the
render and media power wells. By the time we run the runtime suspend
callback the display side is also off and the HW context for that is
managed by the display power domain framework.

Besides the above there are Gunit registers that depend on a system-wide
power well. This power well goes off once the device enters any of the
S0i[R123] states. To handle this scenario, save/restore these Gunit
registers. Note that this is not the complete register set dictated by
[2], to remove some overhead, registers that are known not to be used are
ignored. Also some registers are fully setup by initialization functions
called during resume, these are not saved either. The list of registers
can be further reduced, see the TODO note in the code.

[1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
[2] VLV2_S0IXRegs

v2:
- unchanged
v3:
- fix s/GEN6_PMIIR/GEN6_PMIMR/ typo when saving/restoring registers
  (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
 2 files changed, 389 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 31988f6..0a96a5d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
+/*
+ * Save all Gunit registers that may be lost after a D3 and a subsequent
+ * S0i[R123] transition. The list of registers needing a save/restore is
+ * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
+ * registers in the following way:
+ * - Driver: saved/restored by the driver
+ * - Punit : saved/restored by the Punit firmware
+ * - No, w/o marking: no need to save/restore, since the register is R/O or
+ *                    used internally by the HW in a way that doesn't depend
+ *                    keeping the content across a suspend/resume.
+ * - Debug : used for debugging
+ *
+ * We save/restore all registers marked with 'Driver', with the following
+ * exceptions:
+ * - Registers out of use, including also registers marked with 'Debug'.
+ *   These have no effect on the driver's operation, so we don't save/restore
+ *   them to reduce the overhead.
+ * - Registers that are fully setup by an initialization function called from
+ *   the resume path. For example many clock gating and RPS/RC6 registers.
+ * - Registers that provide the right functionality with their reset defaults.
+ *
+ * TODO: Except for registers that based on the above 3 criteria can be safely
+ * ignored, we save/restore all others, practically treating the HW context as
+ * a black-box for the driver. Further investigation is needed to reduce the
+ * saved/restored registers even further, by following the same 3 criteria.
+ */
+static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
+	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
+	s->arb_mode		= I915_READ(ARB_MODE);
+	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
+	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
+
+	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+
+	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
+	s->ecochk		= I915_READ(GAM_ECOCHK);
+	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
+	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
+
+	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	s->g3dctl		= I915_READ(GEN7_G3DCTL);
+	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
+	s->mbctl		= I915_READ(GEN6_MBCTL);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
+	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
+	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
+	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
+	s->rstctl		= I915_READ(GEN7_RSTCTL);
+	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
+	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
+	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
+	s->ecobus		= I915_READ(ECOBUS);
+	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
+	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
+	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
+	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
+	s->rcedata		= I915_READ(VLV_RCEDATA);
+	s->spare2gh		= I915_READ(VLV_SPAREG2H);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	s->gt_imr		= I915_READ(GTIMR);
+	s->gt_ier		= I915_READ(GTIER);
+	s->pm_imr		= I915_READ(GEN6_PMIMR);
+	s->pm_ier		= I915_READ(GEN6_PMIER);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	s->tilectl		= I915_READ(TILECTL);
+	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
+	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
+	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
+	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
+	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
+
+	/*
+	 * Not saving any of:
+	 * DFT,		0x9800-0x9EC0
+	 * SARB,	0xB000-0xB1FC
+	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
+	 * PCI CFG
+	 */
+}
+
+static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	u32 val;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
+	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
+	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
+	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
+	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
+
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
+
+	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
+	I915_WRITE(GAM_ECOCHK,		s->ecochk);
+	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
+	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
+
+	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
+	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
+	I915_WRITE(GEN6_MBCTL,		s->mbctl);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
+	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
+	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
+	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
+	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
+	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
+	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
+	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
+	I915_WRITE(ECOBUS,		s->ecobus);
+	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
+	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
+	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
+	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
+	I915_WRITE(VLV_RCEDATA,		s->rcedata);
+	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	I915_WRITE(GTIMR,		s->gt_imr);
+	I915_WRITE(GTIER,		s->gt_ier);
+	I915_WRITE(GEN6_PMIMR,		s->pm_imr);
+	I915_WRITE(GEN6_PMIER,		s->pm_ier);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	I915_WRITE(TILECTL,			s->tilectl);
+	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
+	/*
+	 * Preserve the GT allow wake and GFX force clock bit, they are not
+	 * be restored, as they are used to control the s0ix suspend/resume
+	 * sequence by the caller.
+	 */
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= VLV_GTLC_ALLOWWAKEREQ;
+	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	val &= VLV_GFX_CLK_FORCE_ON_BIT;
+	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
+
+	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
+	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
+}
+
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 {
 	u32 val;
@@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 #undef COND
 }
 
+static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
+{
+	u32 val;
+	int err = 0;
+
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= ~VLV_GTLC_ALLOWWAKEREQ;
+	if (allow)
+		val |= VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+	POSTING_READ(VLV_GTLC_WAKE_CTRL);
+
+#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
+	      allow)
+	err = wait_for(COND, 1);
+	if (err)
+		DRM_ERROR("timeout disabling GT waking\n");
+	return err;
+#undef COND
+}
+
+static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
+				 bool wait_for_on)
+{
+	u32 mask;
+	u32 val;
+	int err;
+
+	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
+	val = wait_for_on ? mask : 0;
+#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
+	if (COND)
+		return 0;
+
+	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
+			wait_for_on ? "on" : "off",
+			I915_READ(VLV_GTLC_PW_STATUS));
+
+	/*
+	 * RC6 transitioning can be delayed up to 2 msec (see
+	 * valleyview_enable_rps), use 3 msec for safety.
+	 */
+	err = wait_for(COND, 3);
+	if (err)
+		DRM_ERROR("timeout waiting for GT wells to go %s\n",
+			  wait_for_on ? "on" : "off");
+
+	return err;
+#undef COND
+}
+
+static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
+{
+	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
+		return;
+
+	DRM_ERROR("GT register access while GT waking disabled\n");
+	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
+}
+
+static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	u32 mask;
+	int err;
+
+	/*
+	 * Bspec defines the following GT well on flags as debug only, so
+	 * don't treat them as hard failures.
+	 */
+	(void)vlv_wait_for_gt_wells(dev_priv, false);
+
+	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
+	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
+
+	vlv_check_no_gt_access(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, true);
+	if (err)
+		goto err1;
+
+	err = vlv_allow_gt_wake(dev_priv, false);
+	if (err)
+		goto err2;
+	vlv_save_gunit_s0ix_state(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (err)
+		goto err2;
+
+	return 0;
+
+err2:
+	/* For safety always re-enable waking and disable gfx clock forcing */
+	vlv_allow_gt_wake(dev_priv, true);
+err1:
+	vlv_force_gfx_clock(dev_priv, false);
+
+	return err;
+}
+
+static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int err;
+	int ret;
+
+	/*
+	 * If any of the steps fail just try to continue, that's the best we
+	 * can do at this point. Return the first error code (which will also
+	 * leave RPM permanently disabled).
+	 */
+	ret = vlv_force_gfx_clock(dev_priv, true);
+
+	vlv_restore_gunit_s0ix_state(dev_priv);
+
+	err = vlv_allow_gt_wake(dev_priv, true);
+	if (!ret)
+		ret = err;
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (!ret)
+		ret = err;
+
+	vlv_check_no_gt_access(dev_priv);
+
+	intel_init_clock_gating(dev);
+	i915_gem_restore_fences(dev);
+
+	return ret;
+}
+
 static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -975,6 +1298,8 @@ static int intel_runtime_suspend(struct device *device)
 		ret = 0;
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_suspend(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_suspend(dev_priv);
 	} else {
 		ret = -ENODEV;
 		WARN_ON(1);
@@ -1023,6 +1348,8 @@ static int intel_runtime_resume(struct device *device)
 		ret = snb_runtime_resume(dev_priv);
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_resume(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_resume(dev_priv);
 	} else {
 		WARN_ON(1);
 		ret = -ENODEV;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3cac434..77cb7fc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
 	u32 savePCH_PORT_HOTPLUG;
 };
 
+struct vlv_s0ix_state {
+	/* GAM */
+	u32 wr_watermark;
+	u32 gfx_prio_ctrl;
+	u32 arb_mode;
+	u32 gfx_pend_tlb0;
+	u32 gfx_pend_tlb1;
+	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
+	u32 media_max_req_count;
+	u32 gfx_max_req_count;
+	u32 render_hwsp;
+	u32 ecochk;
+	u32 bsd_hwsp;
+	u32 blt_hwsp;
+	u32 tlb_rd_addr;
+
+	/* MBC */
+	u32 g3dctl;
+	u32 gsckgctl;
+	u32 mbctl;
+
+	/* GCP */
+	u32 ucgctl1;
+	u32 ucgctl3;
+	u32 rcgctl1;
+	u32 rcgctl2;
+	u32 rstctl;
+	u32 misccpctl;
+
+	/* GPM */
+	u32 gfxpause;
+	u32 rpdeuhwtc;
+	u32 rpdeuc;
+	u32 ecobus;
+	u32 pwrdwnupctl;
+	u32 rp_down_timeout;
+	u32 rp_deucsw;
+	u32 rcubmabdtmr;
+	u32 rcedata;
+	u32 spare2gh;
+
+	/* Display 1 CZ domain */
+	u32 gt_imr;
+	u32 gt_ier;
+	u32 pm_imr;
+	u32 pm_ier;
+	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
+
+	/* GT SA CZ domain */
+	u32 tilectl;
+	u32 gt_fifoctl;
+	u32 gtlc_wake_ctrl;
+	u32 gtlc_survive;
+	u32 pmwgicz;
+
+	/* Display 2 CZ domain */
+	u32 gu_ctl0;
+	u32 gu_ctl1;
+	u32 clock_gate_dis2;
+};
+
 struct intel_gen6_power_mgmt {
 	/* work and pm_iir are protected by dev_priv->irq_lock */
 	struct work_struct work;
@@ -1447,6 +1508,7 @@ struct drm_i915_private {
 
 	u32 suspend_count;
 	struct i915_suspend_saved_registers regfile;
+	struct vlv_s0ix_state vlv_s0ix_state;
 
 	struct {
 		/*
-- 
1.8.4

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

* Re: [PATCH v3] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-18 12:47   ` [PATCH v3] " Imre Deak
@ 2014-04-22 19:38     ` Daniel Vetter
  2014-04-22 20:34       ` Imre Deak
  2014-04-22 22:13     ` [PATCH v4] " Imre Deak
  1 sibling, 1 reply; 85+ messages in thread
From: Daniel Vetter @ 2014-04-22 19:38 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 18, 2014 at 03:47:45PM +0300, Imre Deak wrote:
> Atm we can end up in the GPU reset deferred work in D3 state if the last
> runtime PM reference is dropped between detecting a hang/scheduling the
> work and executing the work. At least one such case I could trigger is
> the simulated reset via the i915_wedged debugfs entry. Fix this by
> disabling RPM before scheduling the work until the end of the work.
> 
> v2:
> - Instead of getting/putting the RPM reference in the reset work itself,
>   get it already before scheduling the work. By this we also prevent
>   going to D3 before the work gets to run, in addition to making sure
>   that we run the work itself in D0. (Ville, Daniel)
> v3:
> - fix inverted logic fail when putting the RPM ref on behalf of a
>   cancelled GPU reset work (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
>  drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 0b38f88..f792576 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
>  
>  	/* Free error state after interrupts are fully disabled. */
>  	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> -	cancel_work_sync(&dev_priv->gpu_error.work);
> +	if (cancel_work_sync(&dev_priv->gpu_error.work))
> +		/*
> +		 * The following won't make any difference in the PM state,
> +		 * since RPM is disabled already, but do it still for
> +		 * consistency.
> +		 */
> +		intel_runtime_pm_put(dev_priv);
>  	i915_destroy_error_state(dev);
>  
>  	if (dev->pdev->msi_enabled)
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a651d0d..5e079d8 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
>  		 */
>  		i915_error_wake_up(dev_priv, true);
>  	}
> +
> +	/* Drop the ref we took when scheduling this work. */
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  static void i915_report_and_clear_eir(struct drm_device *dev)
> @@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
>  	 * state of outstanding pagelips). Hence it must not be run on our own
>  	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
>  	 * code will deadlock.
> +	 *
> +	 * It's guaranteed that here we are in D0 state, since we can only get
> +	 * here via one of the following paths:
> +	 * - From an IRQ handler's error detection. -> The driver must make
> +	 *   sure that IRQs are unmasked only while holding an RPM ref.
> +	 * - From hang-check due to a blocked request. -> The request holds an
> +	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
> +	 *   won't be called until the request is finished.
> +	 * - From hang-check due to a flip hang. -> We have an RPM ref because
> +	 *   of the active modeset.
> +	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
> +	 *   RPM ref.
> +	 * Take here an atomic RPM ref still to make sure that we don't
> +	 * re-enter D3 until the error work gets to run and completes the
> +	 * reset.
>  	 */
> -	schedule_work(&dev_priv->gpu_error.work);
> +	if (schedule_work(&dev_priv->gpu_error.work))
> +		intel_runtime_pm_get_noresume(dev_priv);

Isn't this a bit racy? A 2nd gpu could immediately execute the work while
this one here gets interrupted by NMI ...

I think we need to grab the ref earlier before the schedule_work. Or we
just grab it in the reset work around the register access. Actually I
think this is the right fix since we can only hit this cause by
fake-injecting a hang through debugfs. For real hangs we'll be holding a
runtime pm ref until the last request is completed by the gpu, which won't
happen if the gpu is hung.

Doing the get/put in the worker only also avoids the need to do a get from
atomic context, which is fairly fragile.

We should have a comment in the reset work explaining why we need it
though.
-Daniel

>  }
>  
>  static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v3] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-22 19:38     ` Daniel Vetter
@ 2014-04-22 20:34       ` Imre Deak
  2014-04-22 21:05         ` Daniel Vetter
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-22 20:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 2014-04-22 at 21:38 +0200, Daniel Vetter wrote:
> On Fri, Apr 18, 2014 at 03:47:45PM +0300, Imre Deak wrote:
> > Atm we can end up in the GPU reset deferred work in D3 state if the last
> > runtime PM reference is dropped between detecting a hang/scheduling the
> > work and executing the work. At least one such case I could trigger is
> > the simulated reset via the i915_wedged debugfs entry. Fix this by
> > disabling RPM before scheduling the work until the end of the work.
> > 
> > v2:
> > - Instead of getting/putting the RPM reference in the reset work itself,
> >   get it already before scheduling the work. By this we also prevent
> >   going to D3 before the work gets to run, in addition to making sure
> >   that we run the work itself in D0. (Ville, Daniel)
> > v3:
> > - fix inverted logic fail when putting the RPM ref on behalf of a
> >   cancelled GPU reset work (Ville)
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
> >  drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
> >  2 files changed, 27 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > index 0b38f88..f792576 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
> >  
> >  	/* Free error state after interrupts are fully disabled. */
> >  	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> > -	cancel_work_sync(&dev_priv->gpu_error.work);
> > +	if (cancel_work_sync(&dev_priv->gpu_error.work))
> > +		/*
> > +		 * The following won't make any difference in the PM state,
> > +		 * since RPM is disabled already, but do it still for
> > +		 * consistency.
> > +		 */
> > +		intel_runtime_pm_put(dev_priv);
> >  	i915_destroy_error_state(dev);
> >  
> >  	if (dev->pdev->msi_enabled)
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index a651d0d..5e079d8 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
> >  		 */
> >  		i915_error_wake_up(dev_priv, true);
> >  	}
> > +
> > +	/* Drop the ref we took when scheduling this work. */
> > +	intel_runtime_pm_put(dev_priv);
> >  }
> >  
> >  static void i915_report_and_clear_eir(struct drm_device *dev)
> > @@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
> >  	 * state of outstanding pagelips). Hence it must not be run on our own
> >  	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
> >  	 * code will deadlock.
> > +	 *
> > +	 * It's guaranteed that here we are in D0 state, since we can only get
> > +	 * here via one of the following paths:
> > +	 * - From an IRQ handler's error detection. -> The driver must make
> > +	 *   sure that IRQs are unmasked only while holding an RPM ref.
> > +	 * - From hang-check due to a blocked request. -> The request holds an
> > +	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
> > +	 *   won't be called until the request is finished.
> > +	 * - From hang-check due to a flip hang. -> We have an RPM ref because
> > +	 *   of the active modeset.
> > +	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
> > +	 *   RPM ref.
> > +	 * Take here an atomic RPM ref still to make sure that we don't
> > +	 * re-enter D3 until the error work gets to run and completes the
> > +	 * reset.
> >  	 */
> > -	schedule_work(&dev_priv->gpu_error.work);
> > +	if (schedule_work(&dev_priv->gpu_error.work))
> > +		intel_runtime_pm_get_noresume(dev_priv);
> 
> Isn't this a bit racy? A 2nd gpu could immediately execute the work while
> this one here gets interrupted by NMI ...

It is, I didn't think about that case..

> I think we need to grab the ref earlier before the schedule_work. Or we
> just grab it in the reset work around the register access. Actually I
> think this is the right fix since we can only hit this cause by
> fake-injecting a hang through debugfs. For real hangs we'll be holding a
> runtime pm ref until the last request is completed by the gpu, which won't
> happen if the gpu is hung.
> 
> Doing the get/put in the worker only also avoids the need to do a get from
> atomic context, which is fairly fragile.

It's only an atomic inc.. But in case we get here through the interrupt
error detection path, there is no guarantee we have any pending GPU
work, so we could drop the last reference before the work is run.

> We should have a comment in the reset work explaining why we need it
> though.



> -Daniel
> 
> >  }
> >  
> >  static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe)
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

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

* Re: [PATCH v3] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-22 20:34       ` Imre Deak
@ 2014-04-22 21:05         ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-04-22 21:05 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Apr 22, 2014 at 11:34:01PM +0300, Imre Deak wrote:
> On Tue, 2014-04-22 at 21:38 +0200, Daniel Vetter wrote:
> > On Fri, Apr 18, 2014 at 03:47:45PM +0300, Imre Deak wrote:
> > > Atm we can end up in the GPU reset deferred work in D3 state if the last
> > > runtime PM reference is dropped between detecting a hang/scheduling the
> > > work and executing the work. At least one such case I could trigger is
> > > the simulated reset via the i915_wedged debugfs entry. Fix this by
> > > disabling RPM before scheduling the work until the end of the work.
> > > 
> > > v2:
> > > - Instead of getting/putting the RPM reference in the reset work itself,
> > >   get it already before scheduling the work. By this we also prevent
> > >   going to D3 before the work gets to run, in addition to making sure
> > >   that we run the work itself in D0. (Ville, Daniel)
> > > v3:
> > > - fix inverted logic fail when putting the RPM ref on behalf of a
> > >   cancelled GPU reset work (Ville)
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_dma.c |  8 +++++++-
> > >  drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++-
> > >  2 files changed, 27 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > > index 0b38f88..f792576 100644
> > > --- a/drivers/gpu/drm/i915/i915_dma.c
> > > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > > @@ -1823,7 +1823,13 @@ int i915_driver_unload(struct drm_device *dev)
> > >  
> > >  	/* Free error state after interrupts are fully disabled. */
> > >  	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> > > -	cancel_work_sync(&dev_priv->gpu_error.work);
> > > +	if (cancel_work_sync(&dev_priv->gpu_error.work))
> > > +		/*
> > > +		 * The following won't make any difference in the PM state,
> > > +		 * since RPM is disabled already, but do it still for
> > > +		 * consistency.
> > > +		 */
> > > +		intel_runtime_pm_put(dev_priv);
> > >  	i915_destroy_error_state(dev);
> > >  
> > >  	if (dev->pdev->msi_enabled)
> > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > > index a651d0d..5e079d8 100644
> > > --- a/drivers/gpu/drm/i915/i915_irq.c
> > > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > > @@ -2210,6 +2210,9 @@ static void i915_error_work_func(struct work_struct *work)
> > >  		 */
> > >  		i915_error_wake_up(dev_priv, true);
> > >  	}
> > > +
> > > +	/* Drop the ref we took when scheduling this work. */
> > > +	intel_runtime_pm_put(dev_priv);
> > >  }
> > >  
> > >  static void i915_report_and_clear_eir(struct drm_device *dev)
> > > @@ -2353,8 +2356,24 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
> > >  	 * state of outstanding pagelips). Hence it must not be run on our own
> > >  	 * dev-priv->wq work queue for otherwise the flush_work in the pageflip
> > >  	 * code will deadlock.
> > > +	 *
> > > +	 * It's guaranteed that here we are in D0 state, since we can only get
> > > +	 * here via one of the following paths:
> > > +	 * - From an IRQ handler's error detection. -> The driver must make
> > > +	 *   sure that IRQs are unmasked only while holding an RPM ref.
> > > +	 * - From hang-check due to a blocked request. -> The request holds an
> > > +	 *   RPM ref, that's only released in i915_gpu_idle() which in turn
> > > +	 *   won't be called until the request is finished.
> > > +	 * - From hang-check due to a flip hang. -> We have an RPM ref because
> > > +	 *   of the active modeset.
> > > +	 * - From debugfs i915_wedged_set(). -> The caller takes an explicit
> > > +	 *   RPM ref.
> > > +	 * Take here an atomic RPM ref still to make sure that we don't
> > > +	 * re-enter D3 until the error work gets to run and completes the
> > > +	 * reset.
> > >  	 */
> > > -	schedule_work(&dev_priv->gpu_error.work);
> > > +	if (schedule_work(&dev_priv->gpu_error.work))
> > > +		intel_runtime_pm_get_noresume(dev_priv);
> > 
> > Isn't this a bit racy? A 2nd gpu could immediately execute the work while
> > this one here gets interrupted by NMI ...
> 
> It is, I didn't think about that case..
> 
> > I think we need to grab the ref earlier before the schedule_work. Or we
> > just grab it in the reset work around the register access. Actually I
> > think this is the right fix since we can only hit this cause by
> > fake-injecting a hang through debugfs. For real hangs we'll be holding a
> > runtime pm ref until the last request is completed by the gpu, which won't
> > happen if the gpu is hung.
> > 
> > Doing the get/put in the worker only also avoids the need to do a get from
> > atomic context, which is fairly fragile.
> 
> It's only an atomic inc.. But in case we get here through the interrupt
> error detection path, there is no guarantee we have any pending GPU
> work, so we could drop the last reference before the work is run.

The interrupt based error handling is only wired up for pre-gen5. So not
really a concern for runtime pm. I still think that it would be better to
just grab a runtime pm ref around the reset function itself and don't do
crazy dances in the interrupt handler. Even if the underlying
implementation is a simple atomic inc ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-22 17:28   ` [PATCH v3 " Imre Deak
@ 2014-04-22 22:09     ` Imre Deak
  2014-04-24 21:02       ` Rodrigo Vivi
  2014-04-30 17:35     ` [PATCH v3 25/25] drm/i915: vlv: add runtime PM support Ville Syrjälä
  2014-05-05 12:19     ` [PATCH v4 " Imre Deak
  2 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-22 22:09 UTC (permalink / raw)
  To: intel-gfx

Atm we can end up in the GPU reset deferred work in D3 state if the last
runtime PM reference is dropped between detecting a hang/scheduling the
work and executing the work. At least one such case I could trigger is
the simulated reset via the i915_wedged debugfs entry. Fix this by
getting an RPM reference around accessing the HW in the reset work.

v2:
- Instead of getting/putting the RPM reference in the reset work itself,
  get it already before scheduling the work. By this we also prevent
  going to D3 before the work gets to run, in addition to making sure
  that we run the work itself in D0. (Ville, Daniel)
v3:
- fix inverted logic fail when putting the RPM ref on behalf of a
  cancelled GPU reset work (Ville)
v4:
- Taking the RPM ref in the interrupt handler isn't really needed b/c
  it's already guaranteed that we hold an RPM ref until the end of the
  reset work in all cases we care about. So take the ref in the reset
  work (for cases like i915_wedged_set). (Daniel)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a651d0d..0e47111 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
 				   reset_event);
 
 		/*
+		 * In most cases it's guaranteed that we get here with an RPM
+		 * reference held, for example because there is a pending GPU
+		 * request that won't finish until the reset is done. This
+		 * isn't the case at least when we get here by doing a
+		 * simulated reset via debugs, so get an RPM reference.
+		 */
+		intel_runtime_pm_get(dev_priv);
+		/*
 		 * All state reset _must_ be completed before we update the
 		 * reset counter, for otherwise waiters might miss the reset
 		 * pending state and not properly drop locks, resulting in
@@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
 
 		intel_display_handle_reset(dev);
 
+		intel_runtime_pm_put(dev_priv);
+
 		if (ret == 0) {
 			/*
 			 * After all the gem state is reset, increment the reset
-- 
1.8.4

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

* [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-18 12:47   ` [PATCH v3] " Imre Deak
  2014-04-22 19:38     ` Daniel Vetter
@ 2014-04-22 22:13     ` Imre Deak
  2014-04-23  7:07       ` Daniel Vetter
  1 sibling, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-22 22:13 UTC (permalink / raw)
  To: intel-gfx

Atm we can end up in the GPU reset deferred work in D3 state if the last
runtime PM reference is dropped between detecting a hang/scheduling the
work and executing the work. At least one such case I could trigger is
the simulated reset via the i915_wedged debugfs entry. Fix this by
getting an RPM reference around accessing the HW in the reset work.

v2:
- Instead of getting/putting the RPM reference in the reset work itself,
  get it already before scheduling the work. By this we also prevent
  going to D3 before the work gets to run, in addition to making sure
  that we run the work itself in D0. (Ville, Daniel)
v3:
- fix inverted logic fail when putting the RPM ref on behalf of a
  cancelled GPU reset work (Ville)
v4:
- Taking the RPM ref in the interrupt handler isn't really needed b/c
  it's already guaranteed that we hold an RPM ref until the end of the
  reset work in all cases we care about. So take the ref in the reset
  work (for cases like i915_wedged_set). (Daniel)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a651d0d..0e47111 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
 				   reset_event);
 
 		/*
+		 * In most cases it's guaranteed that we get here with an RPM
+		 * reference held, for example because there is a pending GPU
+		 * request that won't finish until the reset is done. This
+		 * isn't the case at least when we get here by doing a
+		 * simulated reset via debugs, so get an RPM reference.
+		 */
+		intel_runtime_pm_get(dev_priv);
+		/*
 		 * All state reset _must_ be completed before we update the
 		 * reset counter, for otherwise waiters might miss the reset
 		 * pending state and not properly drop locks, resulting in
@@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
 
 		intel_display_handle_reset(dev);
 
+		intel_runtime_pm_put(dev_priv);
+
 		if (ret == 0) {
 			/*
 			 * After all the gem state is reset, increment the reset
-- 
1.8.4

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

* Re: [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-22 22:13     ` [PATCH v4] " Imre Deak
@ 2014-04-23  7:07       ` Daniel Vetter
  2014-04-23  7:52         ` Imre Deak
  0 siblings, 1 reply; 85+ messages in thread
From: Daniel Vetter @ 2014-04-23  7:07 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Wed, Apr 23, 2014 at 01:13:40AM +0300, Imre Deak wrote:
> Atm we can end up in the GPU reset deferred work in D3 state if the last
> runtime PM reference is dropped between detecting a hang/scheduling the
> work and executing the work. At least one such case I could trigger is
> the simulated reset via the i915_wedged debugfs entry. Fix this by
> getting an RPM reference around accessing the HW in the reset work.
> 
> v2:
> - Instead of getting/putting the RPM reference in the reset work itself,
>   get it already before scheduling the work. By this we also prevent
>   going to D3 before the work gets to run, in addition to making sure
>   that we run the work itself in D0. (Ville, Daniel)
> v3:
> - fix inverted logic fail when putting the RPM ref on behalf of a
>   cancelled GPU reset work (Ville)
> v4:
> - Taking the RPM ref in the interrupt handler isn't really needed b/c
>   it's already guaranteed that we hold an RPM ref until the end of the
>   reset work in all cases we care about. So take the ref in the reset
>   work (for cases like i915_wedged_set). (Daniel)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a651d0d..0e47111 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
>  				   reset_event);
>  
>  		/*
> +		 * In most cases it's guaranteed that we get here with an RPM
> +		 * reference held, for example because there is a pending GPU
> +		 * request that won't finish until the reset is done. This
> +		 * isn't the case at least when we get here by doing a
> +		 * simulated reset via debugs, so get an RPM reference.

                                      ^debugfs

Also maybe "..., so get a RPM reference just to quiet the warnings."
-Daniel

> +		 */
> +		intel_runtime_pm_get(dev_priv);
> +		/*
>  		 * All state reset _must_ be completed before we update the
>  		 * reset counter, for otherwise waiters might miss the reset
>  		 * pending state and not properly drop locks, resulting in
> @@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
>  
>  		intel_display_handle_reset(dev);
>  
> +		intel_runtime_pm_put(dev_priv);
> +
>  		if (ret == 0) {
>  			/*
>  			 * After all the gem state is reset, increment the reset
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-23  7:07       ` Daniel Vetter
@ 2014-04-23  7:52         ` Imre Deak
  2014-04-25  8:00           ` Daniel Vetter
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-23  7:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, 2014-04-23 at 09:07 +0200, Daniel Vetter wrote:
> On Wed, Apr 23, 2014 at 01:13:40AM +0300, Imre Deak wrote:
> > Atm we can end up in the GPU reset deferred work in D3 state if the last
> > runtime PM reference is dropped between detecting a hang/scheduling the
> > work and executing the work. At least one such case I could trigger is
> > the simulated reset via the i915_wedged debugfs entry. Fix this by
> > getting an RPM reference around accessing the HW in the reset work.
> > 
> > v2:
> > - Instead of getting/putting the RPM reference in the reset work itself,
> >   get it already before scheduling the work. By this we also prevent
> >   going to D3 before the work gets to run, in addition to making sure
> >   that we run the work itself in D0. (Ville, Daniel)
> > v3:
> > - fix inverted logic fail when putting the RPM ref on behalf of a
> >   cancelled GPU reset work (Ville)
> > v4:
> > - Taking the RPM ref in the interrupt handler isn't really needed b/c
> >   it's already guaranteed that we hold an RPM ref until the end of the
> >   reset work in all cases we care about. So take the ref in the reset
> >   work (for cases like i915_wedged_set). (Daniel)
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index a651d0d..0e47111 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
> >  				   reset_event);
> >  
> >  		/*
> > +		 * In most cases it's guaranteed that we get here with an RPM
> > +		 * reference held, for example because there is a pending GPU
> > +		 * request that won't finish until the reset is done. This
> > +		 * isn't the case at least when we get here by doing a
> > +		 * simulated reset via debugs, so get an RPM reference.
> 
>                                       ^debugfs
> 
> Also maybe "..., so get a RPM reference just to quiet the warnings."

Do you mean it's not a problem to perform the reset in D3 state other
than getting warnings?

--Imre

> -Daniel
> 
> > +		 */
> > +		intel_runtime_pm_get(dev_priv);
> > +		/*
> >  		 * All state reset _must_ be completed before we update the
> >  		 * reset counter, for otherwise waiters might miss the reset
> >  		 * pending state and not properly drop locks, resulting in
> > @@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
> >  
> >  		intel_display_handle_reset(dev);
> >  
> > +		intel_runtime_pm_put(dev_priv);
> > +
> >  		if (ret == 0) {
> >  			/*
> >  			 * After all the gem state is reset, increment the reset
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

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

* Re: [PATCH v3 11/25] drm/i915: add missing error capturing of the PIPESTAT reg
  2014-04-18 12:55   ` [PATCH v3 " Imre Deak
@ 2014-04-23  7:53     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-23  7:53 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 18, 2014 at 03:55:04PM +0300, Imre Deak wrote:
> While checking the error capture path I noticed that we lacked the
> power domain-on check for PIPESTAT so fix this by moving that to where
> the rest of pipe registers are captured.
> 
> The move also revealed that we actually don't include this register in
> the error report, so fix that too.
> 
> v2:
> - patch introduced in v2 of the patchset
> v3:
> - add back !HAS_PCH_SPLIT check (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> 
> [ Ignore my previous comment about the gen<=5 || vlv check, I realized
>   that it's the same as !HAS_PCH_SPLIT. ] 
> 
> ---
>  drivers/gpu/drm/i915/i915_drv.h       | 1 -
>  drivers/gpu/drm/i915/i915_gpu_error.c | 3 ---
>  drivers/gpu/drm/i915/intel_display.c  | 5 +++++
>  3 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7d6acb4..5254f4b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -325,7 +325,6 @@ struct drm_i915_error_state {
>  	u32 gab_ctl;
>  	u32 gfx_mode;
>  	u32 extra_instdone[I915_NUM_INSTDONE_REG];
> -	u32 pipestat[I915_MAX_PIPES];
>  	u64 fence[I915_MAX_NUM_FENCES];
>  	struct intel_overlay_error_state *overlay;
>  	struct intel_display_error_state *display;
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index ba79b59..7b5cc08 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -1028,7 +1028,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  				   struct drm_i915_error_state *error)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> -	int pipe;
>  
>  	/* General organization
>  	 * 1. Registers specific to a single generation
> @@ -1080,8 +1079,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>  			error->ier = I915_READ16(IER);
>  		else
>  			error->ier = I915_READ(IER);
> -		for_each_pipe(pipe)
> -			error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
>  	}
>  
>  	/* 4: Everything else */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index cd68a24..a2f3790 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11901,6 +11901,7 @@ struct intel_display_error_state {
>  	struct intel_pipe_error_state {
>  		bool power_domain_on;
>  		u32 source;
> +		u32 stat;
>  	} pipe[I915_MAX_PIPES];
>  
>  	struct intel_plane_error_state {
> @@ -11982,6 +11983,9 @@ intel_display_capture_error_state(struct drm_device *dev)
>  		}
>  
>  		error->pipe[i].source = I915_READ(PIPESRC(i));
> +
> +		if (!HAS_PCH_SPLIT(dev))
> +			error->pipe[i].stat = I915_READ(PIPESTAT(i));
>  	}
>  
>  	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
> @@ -12032,6 +12036,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
>  		err_printf(m, "  Power: %s\n",
>  			   error->pipe[i].power_domain_on ? "on" : "off");
>  		err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
> +		err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
>  
>  		err_printf(m, "Plane [%d]:\n", i);
>  		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 14/25] drm/i915: sanitize enable_rc6 option
  2014-04-18 13:01   ` [PATCH v3 " Imre Deak
@ 2014-04-23  7:58     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-23  7:58 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 18, 2014 at 04:01:02PM +0300, Imre Deak wrote:
> Atm, an invalid enable_rc6 module option will be silently ignored, so
> emit an info message about it. Doing an early sanitization we can also
> reuse intel_enable_rc6() in a follow-up patch to see if RC6 is actually
> enabled. Currently the caller would have to filter a non-zero return
> value based on the platform we are running on. For example on VLV with
> i915.enable_rc6 set to 2, RC6 won't be enabled but atm
> intel_enable_rc6() would still return 2 in this case.
> 
> v2:
> - simplify the platform check condition (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 30 +++++++++++++++++++++++++++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index a56f6b1..075405a 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3262,15 +3262,32 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
>  		 (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
>  }
>  
> -int intel_enable_rc6(const struct drm_device *dev)
> +static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
>  {
>  	/* No RC6 before Ironlake */
>  	if (INTEL_INFO(dev)->gen < 5)
>  		return 0;
>  
> +	/* RC6 is only on Ironlake mobile not on desktop */
> +	if (INTEL_INFO(dev)->gen == 5 && !IS_IRONLAKE_M(dev))
> +		return 0;
> +
>  	/* Respect the kernel parameter if it is set */
> -	if (i915.enable_rc6 >= 0)
> -		return i915.enable_rc6;
> +	if (enable_rc6 >= 0) {
> +		int mask;
> +
> +		if (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
> +			mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
> +			       INTEL_RC6pp_ENABLE;
> +		else
> +			mask = INTEL_RC6_ENABLE;
> +
> +		if ((enable_rc6 & mask) != enable_rc6)
> +			DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
> +				 enable_rc6, enable_rc6 & mask, mask);
> +
> +		return enable_rc6 & mask;
> +	}
>  
>  	/* Disable RC6 on Ironlake */
>  	if (INTEL_INFO(dev)->gen == 5)
> @@ -3282,6 +3299,11 @@ int intel_enable_rc6(const struct drm_device *dev)
>  	return INTEL_RC6_ENABLE;
>  }
>  
> +int intel_enable_rc6(const struct drm_device *dev)
> +{
> +	return i915.enable_rc6;
> +}
> +
>  static void gen6_enable_rps_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -4496,6 +4518,8 @@ static void intel_init_emon(struct drm_device *dev)
>  
>  void intel_init_gt_powersave(struct drm_device *dev)
>  {
> +	i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
> +
>  	if (IS_VALLEYVIEW(dev))
>  		valleyview_setup_pctx(dev);
>  }
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 17/25] drm/i915: factor out gen6_update_ring_freq
  2014-04-18 13:16   ` [PATCH v3 " Imre Deak
@ 2014-04-23  7:59     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-23  7:59 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 18, 2014 at 04:16:23PM +0300, Imre Deak wrote:
> This is needed by the next patch moving the call out from platform
> specific RPM callbacks to platform independent code.
> 
> No functional change.
> 
> v2:
> - patch introduce in v2 of the patchset
> v3:
> - simplify platform check condition (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.c      |  2 --
>  drivers/gpu/drm/i915/intel_display.c |  2 --
>  drivers/gpu/drm/i915/intel_pm.c      | 18 +++++++++++++++---
>  3 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index f3f9a33..afc31e3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -899,9 +899,7 @@ static void snb_runtime_resume(struct drm_i915_private *dev_priv)
>  
>  	intel_init_pch_refclk(dev);
>  	i915_gem_init_swizzling(dev);
> -	mutex_lock(&dev_priv->rps.hw_lock);
>  	gen6_update_ring_freq(dev);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
>  }
>  
>  static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a902e13..bb7671d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -7065,9 +7065,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
>  
>  	intel_prepare_ddi(dev);
>  	i915_gem_init_swizzling(dev);
> -	mutex_lock(&dev_priv->rps.hw_lock);
>  	gen6_update_ring_freq(dev);
> -	mutex_unlock(&dev_priv->rps.hw_lock);
>  }
>  
>  static void snb_modeset_global_resources(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 4e30b15..46f7b1a 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3525,7 +3525,7 @@ static void gen6_enable_rps(struct drm_device *dev)
>  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }
>  
> -void gen6_update_ring_freq(struct drm_device *dev)
> +static void __gen6_update_ring_freq(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int min_freq = 15;
> @@ -3595,6 +3595,18 @@ void gen6_update_ring_freq(struct drm_device *dev)
>  	}
>  }
>  
> +void gen6_update_ring_freq(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (INTEL_INFO(dev)->gen < 6 || IS_VALLEYVIEW(dev))
> +		return;
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +	__gen6_update_ring_freq(dev);
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +}
> +
>  int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
>  {
>  	u32 val, rp0;
> @@ -4566,10 +4578,10 @@ static void intel_gen6_powersave_work(struct work_struct *work)
>  		valleyview_enable_rps(dev);
>  	} else if (IS_BROADWELL(dev)) {
>  		gen8_enable_rps(dev);
> -		gen6_update_ring_freq(dev);
> +		__gen6_update_ring_freq(dev);
>  	} else {
>  		gen6_enable_rps(dev);
> -		gen6_update_ring_freq(dev);
> +		__gen6_update_ring_freq(dev);
>  	}
>  	dev_priv->rps.enabled = true;
>  	mutex_unlock(&dev_priv->rps.hw_lock);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 19/25] drm/i915: reinit GT power save during resume
  2014-04-22 17:21   ` [PATCH v3 " Imre Deak
@ 2014-04-23  8:06     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-23  8:06 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Apr 22, 2014 at 08:21:07PM +0300, Imre Deak wrote:
> During runtime suspend there can be a last pending rps.work, so make
> sure it's canceled. Note that in the runtime suspend callback we can't
> get any RPS interrupts since it's called only after the GPU goes idle
> and we set the minimum RPS frequency. The next possibility for an RPS
> interrupt is only after getting an RPM ref (for example because of a new
> GPU command) and calling the RPM resume callback.
> 
> v2:
> - patch introduced in v2 of the patchset
> v3:
> - Change the order of canceling the rps.work and disabling interrupts to
>   avoid the race between interrupt disabling and the the rps.work. Race
>   spotted by Ville.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b87109c..edd4ab8 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -919,6 +919,12 @@ static int intel_runtime_suspend(struct device *device)
>  
>  	DRM_DEBUG_KMS("Suspending device\n");
>  
> +	/*
> +	 * rps.work can't be rearmed here, since we get here only after making
> +	 * sure the GPU is idle and the RPS freq is set to the minimum. See
> +	 * intel_mark_idle().
> +	 */
> +	cancel_work_sync(&dev_priv->rps.work);

Yeah makes sense. Well, unless the hardware is bonkers and
generates an UP interrupt while idle.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  	intel_runtime_pm_disable_interrupts(dev);
>  
>  	if (IS_GEN6(dev))
> @@ -970,6 +976,7 @@ static int intel_runtime_resume(struct device *device)
>  	gen6_update_ring_freq(dev);
>  
>  	intel_runtime_pm_restore_interrupts(dev);
> +	intel_reset_gt_powersave(dev);
>  
>  	DRM_DEBUG_KMS("Device resumed\n");
>  	return 0;
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off
  2014-04-18 13:35   ` [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off Imre Deak
@ 2014-04-23  8:11     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-23  8:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 18, 2014 at 04:35:02PM +0300, Imre Deak wrote:
> This will be needed by the VLV runtime PM helpers too, so factor it out.
> 
> Also add a safety check for the case where the previous force-off is
> still pending, since I'm not sure if Punit can handle a new setting
> while the previous one hasn't settled yet.
> 
> v2:
> - unchanged
> v3:
> - add a note to the commit message about the safety check (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.c | 37 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h |  1 +
>  drivers/gpu/drm/i915/intel_pm.c | 16 ++--------------
>  3 files changed, 40 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 1f88917..795caea 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -905,6 +905,43 @@ static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  	hsw_disable_pc8(dev_priv);
>  }
>  
> +int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> +{
> +	u32 val;
> +	int err;
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	WARN_ON(!!(val & VLV_GFX_CLK_FORCE_ON_BIT) == force_on);
> +
> +#define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
> +	/* Wait for a previous force-off to settle */
> +	if (force_on) {
> +		err = wait_for(!COND, 5);
> +		if (err) {
> +			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
> +				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> +			return err;
> +		}
> +	}
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
> +	if (force_on)
> +		val |= VLV_GFX_CLK_FORCE_ON_BIT;
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> +
> +	if (!force_on)
> +		return 0;
> +
> +	err = wait_for(COND, 5);
> +	if (err)
> +		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
> +			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> +
> +	return err;
> +#undef COND
> +}
> +
>  static int intel_runtime_suspend(struct device *device)
>  {
>  	struct pci_dev *pdev = to_pci_dev(device);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 5254f4b..3cac434 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1968,6 +1968,7 @@ extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
>  extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
>  extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
>  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
> +int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
>  
>  extern void intel_console_resume(struct work_struct *work);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c45e5c1..d64ac32 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3129,16 +3129,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
>  	/* Mask turbo interrupt so that they will not come in between */
>  	I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
>  
> -	/* Bring up the Gfx clock */
> -	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG) |
> -				VLV_GFX_CLK_FORCE_ON_BIT);
> -
> -	if (wait_for(((VLV_GFX_CLK_STATUS_BIT &
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG)) != 0), 5)) {
> -			DRM_ERROR("GFX_CLK_ON request timed out\n");
> -		return;
> -	}
> +	vlv_force_gfx_clock(dev_priv, true);
>  
>  	dev_priv->rps.cur_freq = dev_priv->rps.min_freq_softlimit;
>  
> @@ -3149,10 +3140,7 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
>  				& GENFREQSTATUS) == 0, 5))
>  		DRM_ERROR("timed out waiting for Punit\n");
>  
> -	/* Release the Gfx clock */
> -	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG,
> -		I915_READ(VLV_GTLC_SURVIVABILITY_REG) &
> -				~VLV_GFX_CLK_FORCE_ON_BIT);
> +	vlv_force_gfx_clock(dev_priv, false);
>  
>  	I915_WRITE(GEN6_PMINTRMSK,
>  		   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-22 22:09     ` [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
@ 2014-04-24 21:02       ` Rodrigo Vivi
  0 siblings, 0 replies; 85+ messages in thread
From: Rodrigo Vivi @ 2014-04-24 21:02 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

Makes sense for me, so
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Tue, Apr 22, 2014 at 7:09 PM, Imre Deak <imre.deak@intel.com> wrote:
> Atm we can end up in the GPU reset deferred work in D3 state if the last
> runtime PM reference is dropped between detecting a hang/scheduling the
> work and executing the work. At least one such case I could trigger is
> the simulated reset via the i915_wedged debugfs entry. Fix this by
> getting an RPM reference around accessing the HW in the reset work.
>
> v2:
> - Instead of getting/putting the RPM reference in the reset work itself,
>   get it already before scheduling the work. By this we also prevent
>   going to D3 before the work gets to run, in addition to making sure
>   that we run the work itself in D0. (Ville, Daniel)
> v3:
> - fix inverted logic fail when putting the RPM ref on behalf of a
>   cancelled GPU reset work (Ville)
> v4:
> - Taking the RPM ref in the interrupt handler isn't really needed b/c
>   it's already guaranteed that we hold an RPM ref until the end of the
>   reset work in all cases we care about. So take the ref in the reset
>   work (for cases like i915_wedged_set). (Daniel)
>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index a651d0d..0e47111 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
>                                    reset_event);
>
>                 /*
> +                * In most cases it's guaranteed that we get here with an RPM
> +                * reference held, for example because there is a pending GPU
> +                * request that won't finish until the reset is done. This
> +                * isn't the case at least when we get here by doing a
> +                * simulated reset via debugs, so get an RPM reference.
> +                */
> +               intel_runtime_pm_get(dev_priv);
> +               /*
>                  * All state reset _must_ be completed before we update the
>                  * reset counter, for otherwise waiters might miss the reset
>                  * pending state and not properly drop locks, resulting in
> @@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
>
>                 intel_display_handle_reset(dev);
>
> +               intel_runtime_pm_put(dev_priv);
> +
>                 if (ret == 0) {
>                         /*
>                          * After all the gem state is reset, increment the reset
> --
> 1.8.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros
  2014-04-14 17:24 ` [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros Imre Deak
@ 2014-04-24 21:04   ` Rodrigo Vivi
  0 siblings, 0 replies; 85+ messages in thread
From: Rodrigo Vivi @ 2014-04-24 21:04 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

Apparently Ville already Reviewed this one, but since I was checking
the doc and it was right feel free to also use: Reviewed-by: Rodrigo
Vivi <rodrigo.vivi@gmail.com>

same for next 2 patches.

On Mon, Apr 14, 2014 at 2:24 PM, Imre Deak <imre.deak@intel.com> wrote:
> These will be needed by the upcoming VLV RPM helpers.
>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c |  5 +++--
>  drivers/gpu/drm/i915/i915_reg.h | 10 ++++++++--
>  2 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 8f5ffab..af8493a 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -4459,8 +4459,9 @@ int i915_gem_init(struct drm_device *dev)
>
>         if (IS_VALLEYVIEW(dev)) {
>                 /* VLVA0 (potential hack), BIOS isn't actually waking us */
> -               I915_WRITE(VLV_GTLC_WAKE_CTRL, 1);
> -               if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) & 1) == 1, 10))
> +               I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
> +               if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
> +                             VLV_GTLC_ALLOWWAKEACK), 10))
>                         DRM_DEBUG_DRIVER("allow wake ack timed out\n");
>         }
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8f84555..ee768f0 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4996,9 +4996,15 @@ enum punit_power_well {
>  #define  FORCEWAKE_ACK_HSW                     0x130044
>  #define  FORCEWAKE_ACK                         0x130090
>  #define  VLV_GTLC_WAKE_CTRL                    0x130090
> +#define   VLV_GTLC_RENDER_CTX_EXISTS           (1 << 25)
> +#define   VLV_GTLC_MEDIA_CTX_EXISTS            (1 << 24)
> +#define   VLV_GTLC_ALLOWWAKEREQ                        (1 << 0)
> +
>  #define  VLV_GTLC_PW_STATUS                    0x130094
> -#define VLV_GTLC_PW_RENDER_STATUS_MASK         0x80
> -#define VLV_GTLC_PW_MEDIA_STATUS_MASK          0x20
> +#define   VLV_GTLC_ALLOWWAKEACK                        (1 << 0)
> +#define   VLV_GTLC_ALLOWWAKEERR                        (1 << 1)
> +#define   VLV_GTLC_PW_MEDIA_STATUS_MASK                (1 << 5)
> +#define   VLV_GTLC_PW_RENDER_STATUS_MASK       (1 << 7)
>  #define  FORCEWAKE_MT                          0xa188 /* multi-threaded */
>  #define   FORCEWAKE_KERNEL                     0x1
>  #define   FORCEWAKE_USER                       0x2
> --
> 1.8.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place
  2014-04-16 12:57     ` Imre Deak
@ 2014-04-24 21:06       ` Rodrigo Vivi
  0 siblings, 0 replies; 85+ messages in thread
From: Rodrigo Vivi @ 2014-04-24 21:06 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

Although there are more work to be done I don't see any issue or
damage by putting it already to the correct place.
So, feel free to use: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Apr 16, 2014 at 9:57 AM, Imre Deak <imre.deak@intel.com> wrote:
> On Wed, 2014-04-16 at 15:22 +0300, Ville Syrjälä wrote:
>> On Mon, Apr 14, 2014 at 08:24:31PM +0300, Imre Deak wrote:
>> > While checking the error capture path I noticed that this register is
>> > read twice for GEN2, so fix this and also move the read where it's done
>> > for other platforms.
>> >
>> > Signed-off-by: Imre Deak <imre.deak@intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++----
>> >  1 file changed, 4 insertions(+), 4 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
>> > index 4865ade..ba79b59 100644
>> > --- a/drivers/gpu/drm/i915/i915_gpu_error.c
>> > +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
>> > @@ -1053,9 +1053,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>> >             error->gfx_mode = I915_READ(GFX_MODE);
>> >     }
>> >
>> > -   if (IS_GEN2(dev))
>> > -           error->ier = I915_READ16(IER);
>> > -
>> >     /* 2: Registers which belong to multiple generations */
>> >     if (INTEL_INFO(dev)->gen >= 7)
>> >             error->forcewake = I915_READ(FORCEWAKE_MT);
>> > @@ -1079,7 +1076,10 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
>> >     if (HAS_PCH_SPLIT(dev))
>> >             error->ier = I915_READ(DEIER) | I915_READ(GTIER);
>> >     else {
>> > -           error->ier = I915_READ(IER);
>> > +           if (IS_GEN2(dev))
>> > +                   error->ier = I915_READ16(IER);
>> > +           else
>> > +                   error->ier = I915_READ(IER);
>> >             for_each_pipe(pipe)
>> >                     error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
>> >     }
>>
>> The IER handling seems fairly bogus all around. On VLV and PCH platforms
>> we smash both the display and GT IER into the same u32. So probably no
>> one can make any sense of the result.
>>
>> Also I don't know why we try to dump only these two interrupt registers
>> but not the others.
>>
>> So seems like there's more work that needs to be done here.
>
> Right, haven't noticed those.
>
> This patch could be still applied as it's just one step towards fixing
> the other issues you mentioned, but I think it should be anyway kept
> separate (being just a cleanup patch).
>
> --Imre
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>



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

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

* Re: [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
@ 2014-04-24 21:17   ` Rodrigo Vivi
  2014-04-24 21:49     ` Imre Deak
  2014-04-30 14:32   ` Ville Syrjälä
  2014-05-05 12:13   ` [PATCH v3 " Imre Deak
  2 siblings, 1 reply; 85+ messages in thread
From: Rodrigo Vivi @ 2014-04-24 21:17 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

Honestly I don't like patches that adds regs definitions without
actually using them.
But also,

On Mon, Apr 14, 2014 at 2:24 PM, Imre Deak <imre.deak@intel.com> wrote:
> Needed by the VLV S0ix context save/restore helpers.
>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h | 43 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f183746..cba0afd 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -92,6 +92,9 @@
>  #define   GEN6_MBC_SNPCR_LOW   (2<<21)
>  #define   GEN6_MBC_SNPCR_MIN   (3<<21) /* only 1/16th of the cache is shared */
>
> +#define GEN7_G3DCTL            0x9024
> +#define GEN7_GSCKGCTL          0x9028

 I couldn't find 0x9024 and 0x9028 at BSpec.

> +
>  #define GEN6_MBCTL             0x0907c
>  #define   GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4)
>  #define   GEN6_MBCTL_CTX_FETCH_NEEDED  (1 << 3)
> @@ -785,9 +788,20 @@ enum punit_power_well {
>  #define RING_MAX_IDLE(base)    ((base)+0x54)
>  #define RING_HWS_PGA(base)     ((base)+0x80)
>  #define RING_HWS_PGA_GEN6(base)        ((base)+0x2080)
> -#define ARB_MODE               0x04030

And I didn't get why to add unused regs and removed this unused one?
Also I believe this line would be good for another patch as removal
since this patch subject only mentions add.

> +
> +#define GEN7_WR_WATERMARK      0x4028
> +#define GEN7_GFX_PRIO_CTRL     0x402C
> +#define ARB_MODE               0x4030
>  #define   ARB_MODE_SWIZZLE_SNB (1<<4)
>  #define   ARB_MODE_SWIZZLE_IVB (1<<5)
> +#define GEN7_GFX_PEND_TLB0     0x4034
> +#define GEN7_GFX_PEND_TLB1     0x4038
> +/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
> +#define GEN7_LRA_LIMITS_BASE   0x403C
> +#define GEN7_LRA_LIMITS_REG_NUM        13
> +#define GEN7_MEDIA_MAX_REQ_COUNT       0x4070
> +#define GEN7_GFX_MAX_REQ_COUNT         0x4074
> +
>  #define GAMTARBMODE            0x04a08
>  #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
>  #define   ARB_MODE_SWIZZLE_BDW (1<<1)
> @@ -822,6 +836,9 @@ enum punit_power_well {
>  #define   RING_WAIT_I8XX       (1<<0) /* gen2, PRBx_HEAD */
>  #define   RING_WAIT            (1<<11) /* gen3+, PRBx_CTL */
>  #define   RING_WAIT_SEMAPHORE  (1<<10) /* gen6+ */
> +
> +#define GEN7_TLB_RD_ADDR       0x4700
> +
>  #if 0
>  #define PRB0_TAIL      0x02030
>  #define PRB0_HEAD      0x02034
> @@ -948,6 +965,8 @@ enum punit_power_well {
>
>  #define VLV_DISPLAY_BASE 0x180000
>
> +#define VLV_GU_CTL0    (VLV_DISPLAY_BASE + 0x2030)
> +#define VLV_GU_CTL1    (VLV_DISPLAY_BASE + 0x2034)
>  #define SCPD0          0x0209c /* 915+ only */
>  #define IER            0x020a0
>  #define IIR            0x020a4
> @@ -955,6 +974,7 @@ enum punit_power_well {
>  #define ISR            0x020ac
>  #define VLV_GUNIT_CLOCK_GATE   (VLV_DISPLAY_BASE + 0x2060)
>  #define   GCFG_DIS             (1<<8)
> +#define VLV_GUNIT_CLOCK_GATE2  (VLV_DISPLAY_BASE + 0x2064)
>  #define VLV_IIR_RW     (VLV_DISPLAY_BASE + 0x2084)
>  #define VLV_IER                (VLV_DISPLAY_BASE + 0x20a0)
>  #define VLV_IIR                (VLV_DISPLAY_BASE + 0x20a4)
> @@ -4988,6 +5008,8 @@ enum punit_power_well {
>
>  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB       (0x3f<<22)
>
> +#define  VLV_PMWGICZ                           0x1300a4
> +
>  #define  FORCEWAKE                             0xA18C
>  #define  FORCEWAKE_VLV                         0x1300b0
>  #define  FORCEWAKE_ACK_VLV                     0x1300b4
> @@ -5011,6 +5033,7 @@ enum punit_power_well {
>  #define  FORCEWAKE_MT_ACK                      0x130040
>  #define  ECOBUS                                        0xa180
>  #define    FORCEWAKE_MT_ENABLE                 (1<<5)
> +#define  VLV_SPAREG2H                          0xA194
>
>  #define  GTFIFODBG                             0x120000
>  #define    GT_FIFO_SBDROPERR                   (1<<6)
> @@ -5040,12 +5063,24 @@ enum punit_power_well {
>  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
>  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
>
> +#define GEN7_UCGCTL3                           0x9408
> +
>  #define GEN7_UCGCTL4                           0x940c
>  #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE      (1<<25)
>
> +#define GEN7_RCGCTL1                           0x9410
> +#define GEN7_RCGCTL2                           0x9414
> +#define GEN7_RSTCTL                            0x9420
> +
>  #define GEN8_UCGCTL6                           0x9430
>  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE      (1<<14)
>
> +#define GEN7_GFXPAUSE                          0xA000
> +#define GEN7_RPDEUHWTC                         0xA080
> +#define GEN7_RPDEUC                            0xA084
> +
> +#define VLV_PWRDWNUPCTL                                0xA294
> +
>  #define GEN6_RPNSWREQ                          0xA008
>  #define   GEN6_TURBO_DISABLE                   (1<<31)
>  #define   GEN6_FREQUENCY(x)                    ((x)<<25)
> @@ -5098,6 +5133,7 @@ enum punit_power_well {
>  #define GEN6_RP_UP_EI                          0xA068
>  #define GEN6_RP_DOWN_EI                                0xA06C
>  #define GEN6_RP_IDLE_HYSTERSIS                 0xA070
> +#define GEN7_RPDEUCSW                          0xA088
>  #define GEN6_RC_STATE                          0xA094
>  #define GEN6_RC1_WAKE_RATE_LIMIT               0xA098
>  #define GEN6_RC6_WAKE_RATE_LIMIT               0xA09C
> @@ -5105,9 +5141,11 @@ enum punit_power_well {
>  #define GEN6_RC_EVALUATION_INTERVAL            0xA0A8
>  #define GEN6_RC_IDLE_HYSTERSIS                 0xA0AC
>  #define GEN6_RC_SLEEP                          0xA0B0
> +#define VLV_RCUBMABDTMR                                0xA0B0
>  #define GEN6_RC1e_THRESHOLD                    0xA0B4
>  #define GEN6_RC6_THRESHOLD                     0xA0B8
>  #define GEN6_RC6p_THRESHOLD                    0xA0BC
> +#define VLV_RCEDATA                            0xA0BC
>  #define GEN6_RC6pp_THRESHOLD                   0xA0C0
>  #define GEN6_PMINTRMSK                         0xA168
>
> @@ -5126,6 +5164,9 @@ enum punit_power_well {
>                                                  GEN6_PM_RP_DOWN_THRESHOLD | \
>                                                  GEN6_PM_RP_DOWN_TIMEOUT)
>
> +#define GEN7_GT_SCRATCH_BASE                   0x4F100
> +#define GEN7_GT_SCRATCH_REG_NUM                        8
> +
>  #define VLV_GTLC_SURVIVABILITY_REG              0x130098
>  #define VLV_GFX_CLK_STATUS_BIT                 (1<<3)
>  #define VLV_GFX_CLK_FORCE_ON_BIT               (1<<2)
> --
> 1.8.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-24 21:17   ` Rodrigo Vivi
@ 2014-04-24 21:49     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-04-24 21:49 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

On Thu, 2014-04-24 at 18:17 -0300, Rodrigo Vivi wrote:
> Honestly I don't like patches that adds regs definitions without
> actually using them.

I usually add them too in the patch using them first. In this case I
thought that since there are quite a lot of them, it's easier for the
reviewer since you can focus on checking only the offsets in this patch.
Also these will probably be needed regardless of the s0ix save/restore
helpers, since in the future we want to initialize all (or at least
most) of these registers explicitly, so I felt it's fine to add them
separately.

> But also,
> 
> On Mon, Apr 14, 2014 at 2:24 PM, Imre Deak <imre.deak@intel.com> wrote:
> > Needed by the VLV S0ix context save/restore helpers.
> >
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h | 43 ++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 42 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index f183746..cba0afd 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -92,6 +92,9 @@
> >  #define   GEN6_MBC_SNPCR_LOW   (2<<21)
> >  #define   GEN6_MBC_SNPCR_MIN   (3<<21) /* only 1/16th of the cache is shared */
> >
> > +#define GEN7_G3DCTL            0x9024
> > +#define GEN7_GSCKGCTL          0x9028
> 
>  I couldn't find 0x9024 and 0x9028 at BSpec.

You can find them by offset in the bspec bxml tool, or by searching for
G3DCTL/GSCKGCTL.

> 
> > +
> >  #define GEN6_MBCTL             0x0907c
> >  #define   GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4)
> >  #define   GEN6_MBCTL_CTX_FETCH_NEEDED  (1 << 3)
> > @@ -785,9 +788,20 @@ enum punit_power_well {
> >  #define RING_MAX_IDLE(base)    ((base)+0x54)
> >  #define RING_HWS_PGA(base)     ((base)+0x80)
> >  #define RING_HWS_PGA_GEN6(base)        ((base)+0x2080)
> > -#define ARB_MODE               0x04030
> 
> And I didn't get why to add unused regs and removed this unused one?
> Also I believe this line would be good for another patch as removal
> since this patch subject only mentions add.

ARB_MODE is added back below. I notice now that I also removed there the
leading 0, as I used everywhere the same format for the new offsets.

--Imre  

> 
> > +
> > +#define GEN7_WR_WATERMARK      0x4028
> > +#define GEN7_GFX_PRIO_CTRL     0x402C
> > +#define ARB_MODE               0x4030
> >  #define   ARB_MODE_SWIZZLE_SNB (1<<4)
> >  #define   ARB_MODE_SWIZZLE_IVB (1<<5)
> > +#define GEN7_GFX_PEND_TLB0     0x4034
> > +#define GEN7_GFX_PEND_TLB1     0x4038
> > +/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
> > +#define GEN7_LRA_LIMITS_BASE   0x403C
> > +#define GEN7_LRA_LIMITS_REG_NUM        13
> > +#define GEN7_MEDIA_MAX_REQ_COUNT       0x4070
> > +#define GEN7_GFX_MAX_REQ_COUNT         0x4074
> > +
> >  #define GAMTARBMODE            0x04a08
> >  #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
> >  #define   ARB_MODE_SWIZZLE_BDW (1<<1)
> > @@ -822,6 +836,9 @@ enum punit_power_well {
> >  #define   RING_WAIT_I8XX       (1<<0) /* gen2, PRBx_HEAD */
> >  #define   RING_WAIT            (1<<11) /* gen3+, PRBx_CTL */
> >  #define   RING_WAIT_SEMAPHORE  (1<<10) /* gen6+ */
> > +
> > +#define GEN7_TLB_RD_ADDR       0x4700
> > +
> >  #if 0
> >  #define PRB0_TAIL      0x02030
> >  #define PRB0_HEAD      0x02034
> > @@ -948,6 +965,8 @@ enum punit_power_well {
> >
> >  #define VLV_DISPLAY_BASE 0x180000
> >
> > +#define VLV_GU_CTL0    (VLV_DISPLAY_BASE + 0x2030)
> > +#define VLV_GU_CTL1    (VLV_DISPLAY_BASE + 0x2034)
> >  #define SCPD0          0x0209c /* 915+ only */
> >  #define IER            0x020a0
> >  #define IIR            0x020a4
> > @@ -955,6 +974,7 @@ enum punit_power_well {
> >  #define ISR            0x020ac
> >  #define VLV_GUNIT_CLOCK_GATE   (VLV_DISPLAY_BASE + 0x2060)
> >  #define   GCFG_DIS             (1<<8)
> > +#define VLV_GUNIT_CLOCK_GATE2  (VLV_DISPLAY_BASE + 0x2064)
> >  #define VLV_IIR_RW     (VLV_DISPLAY_BASE + 0x2084)
> >  #define VLV_IER                (VLV_DISPLAY_BASE + 0x20a0)
> >  #define VLV_IIR                (VLV_DISPLAY_BASE + 0x20a4)
> > @@ -4988,6 +5008,8 @@ enum punit_power_well {
> >
> >  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB       (0x3f<<22)
> >
> > +#define  VLV_PMWGICZ                           0x1300a4
> > +
> >  #define  FORCEWAKE                             0xA18C
> >  #define  FORCEWAKE_VLV                         0x1300b0
> >  #define  FORCEWAKE_ACK_VLV                     0x1300b4
> > @@ -5011,6 +5033,7 @@ enum punit_power_well {
> >  #define  FORCEWAKE_MT_ACK                      0x130040
> >  #define  ECOBUS                                        0xa180
> >  #define    FORCEWAKE_MT_ENABLE                 (1<<5)
> > +#define  VLV_SPAREG2H                          0xA194
> >
> >  #define  GTFIFODBG                             0x120000
> >  #define    GT_FIFO_SBDROPERR                   (1<<6)
> > @@ -5040,12 +5063,24 @@ enum punit_power_well {
> >  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
> >  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
> >
> > +#define GEN7_UCGCTL3                           0x9408
> > +
> >  #define GEN7_UCGCTL4                           0x940c
> >  #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE      (1<<25)
> >
> > +#define GEN7_RCGCTL1                           0x9410
> > +#define GEN7_RCGCTL2                           0x9414
> > +#define GEN7_RSTCTL                            0x9420
> > +
> >  #define GEN8_UCGCTL6                           0x9430
> >  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE      (1<<14)
> >
> > +#define GEN7_GFXPAUSE                          0xA000
> > +#define GEN7_RPDEUHWTC                         0xA080
> > +#define GEN7_RPDEUC                            0xA084
> > +
> > +#define VLV_PWRDWNUPCTL                                0xA294
> > +
> >  #define GEN6_RPNSWREQ                          0xA008
> >  #define   GEN6_TURBO_DISABLE                   (1<<31)
> >  #define   GEN6_FREQUENCY(x)                    ((x)<<25)
> > @@ -5098,6 +5133,7 @@ enum punit_power_well {
> >  #define GEN6_RP_UP_EI                          0xA068
> >  #define GEN6_RP_DOWN_EI                                0xA06C
> >  #define GEN6_RP_IDLE_HYSTERSIS                 0xA070
> > +#define GEN7_RPDEUCSW                          0xA088
> >  #define GEN6_RC_STATE                          0xA094
> >  #define GEN6_RC1_WAKE_RATE_LIMIT               0xA098
> >  #define GEN6_RC6_WAKE_RATE_LIMIT               0xA09C
> > @@ -5105,9 +5141,11 @@ enum punit_power_well {
> >  #define GEN6_RC_EVALUATION_INTERVAL            0xA0A8
> >  #define GEN6_RC_IDLE_HYSTERSIS                 0xA0AC
> >  #define GEN6_RC_SLEEP                          0xA0B0
> > +#define VLV_RCUBMABDTMR                                0xA0B0
> >  #define GEN6_RC1e_THRESHOLD                    0xA0B4
> >  #define GEN6_RC6_THRESHOLD                     0xA0B8
> >  #define GEN6_RC6p_THRESHOLD                    0xA0BC
> > +#define VLV_RCEDATA                            0xA0BC
> >  #define GEN6_RC6pp_THRESHOLD                   0xA0C0
> >  #define GEN6_PMINTRMSK                         0xA168
> >
> > @@ -5126,6 +5164,9 @@ enum punit_power_well {
> >                                                  GEN6_PM_RP_DOWN_THRESHOLD | \
> >                                                  GEN6_PM_RP_DOWN_TIMEOUT)
> >
> > +#define GEN7_GT_SCRATCH_BASE                   0x4F100
> > +#define GEN7_GT_SCRATCH_REG_NUM                        8
> > +
> >  #define VLV_GTLC_SURVIVABILITY_REG              0x130098
> >  #define VLV_GFX_CLK_STATUS_BIT                 (1<<3)
> >  #define VLV_GFX_CLK_FORCE_ON_BIT               (1<<2)
> > --
> > 1.8.4
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 

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

* Re: [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  2014-04-14 17:24 ` [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling Imre Deak
@ 2014-04-25  7:59   ` Daniel Vetter
  2014-04-25  8:14     ` Imre Deak
  2014-04-25  8:01   ` Daniel Vetter
  1 sibling, 1 reply; 85+ messages in thread
From: Daniel Vetter @ 2014-04-25  7:59 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:29PM +0300, Imre Deak wrote:
> At least on VLV but probably on other platforms too we depend on RC6
> being enabled for RPM, so disable RPM until the delayed RC6 enabling
> completes.
> 
> v2:
> - explain the reason for the _noresume version of RPM get (Daniel)
> - use the simpler 'if (schedule_work()) rpm_get();' instead of
>   'if (!cancel_work_sync()) rpm_get(); schedule_work();'
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c  |  5 ++++-
>  drivers/gpu/drm/i915/intel_drv.h |  2 ++
>  drivers/gpu/drm/i915/intel_pm.c  | 34 ++++++++++++++++++++++++++++++++--
>  3 files changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index a821608..a20d2d1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -754,7 +754,7 @@ int i915_reset(struct drm_device *dev)
>  		 * previous concerns that it doesn't respond well to some forms
>  		 * of re-init after reset. */
>  		if (INTEL_INFO(dev)->gen > 5)
> -			intel_enable_gt_powersave(dev);
> +			intel_reset_gt_powersave(dev);
>  
>  		intel_hpd_init(dev);
>  	} else {
> @@ -923,6 +923,9 @@ static int intel_runtime_suspend(struct device *device)
>  	struct drm_device *dev = pci_get_drvdata(pdev);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> +	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
> +		return -ENODEV;
> +
>  	WARN_ON(!HAS_RUNTIME_PM(dev));
>  	assert_force_wake_inactive(dev_priv);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c551472..618d05a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -924,6 +924,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
>  void intel_cleanup_gt_powersave(struct drm_device *dev);
>  void intel_enable_gt_powersave(struct drm_device *dev);
>  void intel_disable_gt_powersave(struct drm_device *dev);
> +void intel_reset_gt_powersave(struct drm_device *dev);
>  void ironlake_teardown_rc6(struct drm_device *dev);
>  void gen6_update_ring_freq(struct drm_device *dev);
>  void gen6_rps_idle(struct drm_i915_private *dev_priv);
> @@ -931,6 +932,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
>  void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
>  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e5b9f08..0e8b263 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -4549,6 +4549,8 @@ static void intel_gen6_powersave_work(struct work_struct *work)
>  	}
>  	dev_priv->rps.enabled = true;
>  	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  void intel_enable_gt_powersave(struct drm_device *dev)
> @@ -4566,12 +4568,28 @@ void intel_enable_gt_powersave(struct drm_device *dev)
>  		 * PCU communication is slow and this doesn't need to be
>  		 * done at any specific time, so do this out of our fast path
>  		 * to make resume and init faster.
> +		 *
> +		 * We depend on the HW RC6 power context save/restore
> +		 * mechanism when entering D3 through runtime PM suspend. So
> +		 * disable RPM until RPS/RC6 is properly setup. We can only
> +		 * get here via the driver load/system resume/runtime resume
> +		 * paths, so the _noresume version is enough (and in case of
> +		 * runtime resume it's necessary).
>  		 */
> -		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> -				      round_jiffies_up_relative(HZ));
> +		if (schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> +					   round_jiffies_up_relative(HZ)))
> +			intel_runtime_pm_get_noresume(dev_priv);
>  	}
>  }
>  
> +void intel_reset_gt_powersave(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	dev_priv->rps.enabled = false;
> +	intel_enable_gt_powersave(dev);
> +}
> +
>  static void ibx_init_clock_gating(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -6025,6 +6043,18 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>  	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
>  }
>  
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");

Do we really need our own tracking in dev_priv->pm.suspended, is there
nothing in the runtime pm core which we could use instaed?
-Daniel

> +	pm_runtime_get_noresume(device);
> +}
> +
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work
  2014-04-23  7:52         ` Imre Deak
@ 2014-04-25  8:00           ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-04-25  8:00 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Wed, Apr 23, 2014 at 10:52:10AM +0300, Imre Deak wrote:
> On Wed, 2014-04-23 at 09:07 +0200, Daniel Vetter wrote:
> > On Wed, Apr 23, 2014 at 01:13:40AM +0300, Imre Deak wrote:
> > > Atm we can end up in the GPU reset deferred work in D3 state if the last
> > > runtime PM reference is dropped between detecting a hang/scheduling the
> > > work and executing the work. At least one such case I could trigger is
> > > the simulated reset via the i915_wedged debugfs entry. Fix this by
> > > getting an RPM reference around accessing the HW in the reset work.
> > > 
> > > v2:
> > > - Instead of getting/putting the RPM reference in the reset work itself,
> > >   get it already before scheduling the work. By this we also prevent
> > >   going to D3 before the work gets to run, in addition to making sure
> > >   that we run the work itself in D0. (Ville, Daniel)
> > > v3:
> > > - fix inverted logic fail when putting the RPM ref on behalf of a
> > >   cancelled GPU reset work (Ville)
> > > v4:
> > > - Taking the RPM ref in the interrupt handler isn't really needed b/c
> > >   it's already guaranteed that we hold an RPM ref until the end of the
> > >   reset work in all cases we care about. So take the ref in the reset
> > >   work (for cases like i915_wedged_set). (Daniel)
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_irq.c | 10 ++++++++++
> > >  1 file changed, 10 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > > index a651d0d..0e47111 100644
> > > --- a/drivers/gpu/drm/i915/i915_irq.c
> > > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > > @@ -2175,6 +2175,14 @@ static void i915_error_work_func(struct work_struct *work)
> > >  				   reset_event);
> > >  
> > >  		/*
> > > +		 * In most cases it's guaranteed that we get here with an RPM
> > > +		 * reference held, for example because there is a pending GPU
> > > +		 * request that won't finish until the reset is done. This
> > > +		 * isn't the case at least when we get here by doing a
> > > +		 * simulated reset via debugs, so get an RPM reference.
> > 
> >                                       ^debugfs
> > 
> > Also maybe "..., so get a RPM reference just to quiet the warnings."
> 
> Do you mean it's not a problem to perform the reset in D3 state other
> than getting warnings?

Ah right, we actually touch the hardware ;-) So your comment as-is is good
enough.
-Daniel

> 
> --Imre
> 
> > -Daniel
> > 
> > > +		 */
> > > +		intel_runtime_pm_get(dev_priv);
> > > +		/*
> > >  		 * All state reset _must_ be completed before we update the
> > >  		 * reset counter, for otherwise waiters might miss the reset
> > >  		 * pending state and not properly drop locks, resulting in
> > > @@ -2184,6 +2192,8 @@ static void i915_error_work_func(struct work_struct *work)
> > >  
> > >  		intel_display_handle_reset(dev);
> > >  
> > > +		intel_runtime_pm_put(dev_priv);
> > > +
> > >  		if (ret == 0) {
> > >  			/*
> > >  			 * After all the gem state is reset, increment the reset
> > > -- 
> > > 1.8.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  2014-04-14 17:24 ` [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling Imre Deak
  2014-04-25  7:59   ` Daniel Vetter
@ 2014-04-25  8:01   ` Daniel Vetter
  1 sibling, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-04-25  8:01 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:29PM +0300, Imre Deak wrote:
> At least on VLV but probably on other platforms too we depend on RC6
> being enabled for RPM, so disable RPM until the delayed RC6 enabling
> completes.
> 
> v2:
> - explain the reason for the _noresume version of RPM get (Daniel)
> - use the simpler 'if (schedule_work()) rpm_get();' instead of
>   'if (!cancel_work_sync()) rpm_get(); schedule_work();'
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Merged up to this patch, thanks.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c  |  5 ++++-
>  drivers/gpu/drm/i915/intel_drv.h |  2 ++
>  drivers/gpu/drm/i915/intel_pm.c  | 34 ++++++++++++++++++++++++++++++++--
>  3 files changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index a821608..a20d2d1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -754,7 +754,7 @@ int i915_reset(struct drm_device *dev)
>  		 * previous concerns that it doesn't respond well to some forms
>  		 * of re-init after reset. */
>  		if (INTEL_INFO(dev)->gen > 5)
> -			intel_enable_gt_powersave(dev);
> +			intel_reset_gt_powersave(dev);
>  
>  		intel_hpd_init(dev);
>  	} else {
> @@ -923,6 +923,9 @@ static int intel_runtime_suspend(struct device *device)
>  	struct drm_device *dev = pci_get_drvdata(pdev);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> +	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
> +		return -ENODEV;
> +
>  	WARN_ON(!HAS_RUNTIME_PM(dev));
>  	assert_force_wake_inactive(dev_priv);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c551472..618d05a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -924,6 +924,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
>  void intel_cleanup_gt_powersave(struct drm_device *dev);
>  void intel_enable_gt_powersave(struct drm_device *dev);
>  void intel_disable_gt_powersave(struct drm_device *dev);
> +void intel_reset_gt_powersave(struct drm_device *dev);
>  void ironlake_teardown_rc6(struct drm_device *dev);
>  void gen6_update_ring_freq(struct drm_device *dev);
>  void gen6_rps_idle(struct drm_i915_private *dev_priv);
> @@ -931,6 +932,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
>  void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
>  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e5b9f08..0e8b263 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -4549,6 +4549,8 @@ static void intel_gen6_powersave_work(struct work_struct *work)
>  	}
>  	dev_priv->rps.enabled = true;
>  	mutex_unlock(&dev_priv->rps.hw_lock);
> +
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  void intel_enable_gt_powersave(struct drm_device *dev)
> @@ -4566,12 +4568,28 @@ void intel_enable_gt_powersave(struct drm_device *dev)
>  		 * PCU communication is slow and this doesn't need to be
>  		 * done at any specific time, so do this out of our fast path
>  		 * to make resume and init faster.
> +		 *
> +		 * We depend on the HW RC6 power context save/restore
> +		 * mechanism when entering D3 through runtime PM suspend. So
> +		 * disable RPM until RPS/RC6 is properly setup. We can only
> +		 * get here via the driver load/system resume/runtime resume
> +		 * paths, so the _noresume version is enough (and in case of
> +		 * runtime resume it's necessary).
>  		 */
> -		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> -				      round_jiffies_up_relative(HZ));
> +		if (schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> +					   round_jiffies_up_relative(HZ)))
> +			intel_runtime_pm_get_noresume(dev_priv);
>  	}
>  }
>  
> +void intel_reset_gt_powersave(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	dev_priv->rps.enabled = false;
> +	intel_enable_gt_powersave(dev);
> +}
> +
>  static void ibx_init_clock_gating(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -6025,6 +6043,18 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>  	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
>  }
>  
> +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
> +	pm_runtime_get_noresume(device);
> +}
> +
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  2014-04-25  7:59   ` Daniel Vetter
@ 2014-04-25  8:14     ` Imre Deak
  2014-04-25  9:09       ` Daniel Vetter
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-25  8:14 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 6118 bytes --]

On Fri, 2014-04-25 at 09:59 +0200, Daniel Vetter wrote:
> On Mon, Apr 14, 2014 at 08:24:29PM +0300, Imre Deak wrote:
> > At least on VLV but probably on other platforms too we depend on RC6
> > being enabled for RPM, so disable RPM until the delayed RC6 enabling
> > completes.
> > 
> > v2:
> > - explain the reason for the _noresume version of RPM get (Daniel)
> > - use the simpler 'if (schedule_work()) rpm_get();' instead of
> >   'if (!cancel_work_sync()) rpm_get(); schedule_work();'
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c  |  5 ++++-
> >  drivers/gpu/drm/i915/intel_drv.h |  2 ++
> >  drivers/gpu/drm/i915/intel_pm.c  | 34 ++++++++++++++++++++++++++++++++--
> >  3 files changed, 38 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index a821608..a20d2d1 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -754,7 +754,7 @@ int i915_reset(struct drm_device *dev)
> >  		 * previous concerns that it doesn't respond well to some forms
> >  		 * of re-init after reset. */
> >  		if (INTEL_INFO(dev)->gen > 5)
> > -			intel_enable_gt_powersave(dev);
> > +			intel_reset_gt_powersave(dev);
> >  
> >  		intel_hpd_init(dev);
> >  	} else {
> > @@ -923,6 +923,9 @@ static int intel_runtime_suspend(struct device *device)
> >  	struct drm_device *dev = pci_get_drvdata(pdev);
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  
> > +	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
> > +		return -ENODEV;
> > +
> >  	WARN_ON(!HAS_RUNTIME_PM(dev));
> >  	assert_force_wake_inactive(dev_priv);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index c551472..618d05a 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -924,6 +924,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
> >  void intel_cleanup_gt_powersave(struct drm_device *dev);
> >  void intel_enable_gt_powersave(struct drm_device *dev);
> >  void intel_disable_gt_powersave(struct drm_device *dev);
> > +void intel_reset_gt_powersave(struct drm_device *dev);
> >  void ironlake_teardown_rc6(struct drm_device *dev);
> >  void gen6_update_ring_freq(struct drm_device *dev);
> >  void gen6_rps_idle(struct drm_i915_private *dev_priv);
> > @@ -931,6 +932,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv);
> >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> >  void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> > +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
> >  void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> >  void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> >  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index e5b9f08..0e8b263 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -4549,6 +4549,8 @@ static void intel_gen6_powersave_work(struct work_struct *work)
> >  	}
> >  	dev_priv->rps.enabled = true;
> >  	mutex_unlock(&dev_priv->rps.hw_lock);
> > +
> > +	intel_runtime_pm_put(dev_priv);
> >  }
> >  
> >  void intel_enable_gt_powersave(struct drm_device *dev)
> > @@ -4566,12 +4568,28 @@ void intel_enable_gt_powersave(struct drm_device *dev)
> >  		 * PCU communication is slow and this doesn't need to be
> >  		 * done at any specific time, so do this out of our fast path
> >  		 * to make resume and init faster.
> > +		 *
> > +		 * We depend on the HW RC6 power context save/restore
> > +		 * mechanism when entering D3 through runtime PM suspend. So
> > +		 * disable RPM until RPS/RC6 is properly setup. We can only
> > +		 * get here via the driver load/system resume/runtime resume
> > +		 * paths, so the _noresume version is enough (and in case of
> > +		 * runtime resume it's necessary).
> >  		 */
> > -		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> > -				      round_jiffies_up_relative(HZ));
> > +		if (schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> > +					   round_jiffies_up_relative(HZ)))
> > +			intel_runtime_pm_get_noresume(dev_priv);
> >  	}
> >  }
> >  
> > +void intel_reset_gt_powersave(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +
> > +	dev_priv->rps.enabled = false;
> > +	intel_enable_gt_powersave(dev);
> > +}
> > +
> >  static void ibx_init_clock_gating(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > @@ -6025,6 +6043,18 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> >  	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> >  }
> >  
> > +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> > +{
> > +	struct drm_device *dev = dev_priv->dev;
> > +	struct device *device = &dev->pdev->dev;
> > +
> > +	if (!HAS_RUNTIME_PM(dev))
> > +		return;
> > +
> > +	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
> 
> Do we really need our own tracking in dev_priv->pm.suspended, is there
> nothing in the runtime pm core which we could use instaed?

Hm, yes by a quick look pm_runtime_suspended() seems like what we could
use instead. But this was just copy&paste, and the rest of the spots
would need changing too, so could we do it as a follow-up?

--Imre

> -Daniel
> 
> > +	pm_runtime_get_noresume(device);
> > +}
> > +
> >  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling
  2014-04-25  8:14     ` Imre Deak
@ 2014-04-25  9:09       ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-04-25  9:09 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Fri, Apr 25, 2014 at 11:14:26AM +0300, Imre Deak wrote:
> On Fri, 2014-04-25 at 09:59 +0200, Daniel Vetter wrote:
> > On Mon, Apr 14, 2014 at 08:24:29PM +0300, Imre Deak wrote:
> > > At least on VLV but probably on other platforms too we depend on RC6
> > > being enabled for RPM, so disable RPM until the delayed RC6 enabling
> > > completes.
> > > 
> > > v2:
> > > - explain the reason for the _noresume version of RPM get (Daniel)
> > > - use the simpler 'if (schedule_work()) rpm_get();' instead of
> > >   'if (!cancel_work_sync()) rpm_get(); schedule_work();'
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_drv.c  |  5 ++++-
> > >  drivers/gpu/drm/i915/intel_drv.h |  2 ++
> > >  drivers/gpu/drm/i915/intel_pm.c  | 34 ++++++++++++++++++++++++++++++++--
> > >  3 files changed, 38 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > > index a821608..a20d2d1 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.c
> > > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > > @@ -754,7 +754,7 @@ int i915_reset(struct drm_device *dev)
> > >  		 * previous concerns that it doesn't respond well to some forms
> > >  		 * of re-init after reset. */
> > >  		if (INTEL_INFO(dev)->gen > 5)
> > > -			intel_enable_gt_powersave(dev);
> > > +			intel_reset_gt_powersave(dev);
> > >  
> > >  		intel_hpd_init(dev);
> > >  	} else {
> > > @@ -923,6 +923,9 @@ static int intel_runtime_suspend(struct device *device)
> > >  	struct drm_device *dev = pci_get_drvdata(pdev);
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > >  
> > > +	if (WARN_ON_ONCE(!dev_priv->rps.enabled))
> > > +		return -ENODEV;
> > > +
> > >  	WARN_ON(!HAS_RUNTIME_PM(dev));
> > >  	assert_force_wake_inactive(dev_priv);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index c551472..618d05a 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -924,6 +924,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
> > >  void intel_cleanup_gt_powersave(struct drm_device *dev);
> > >  void intel_enable_gt_powersave(struct drm_device *dev);
> > >  void intel_disable_gt_powersave(struct drm_device *dev);
> > > +void intel_reset_gt_powersave(struct drm_device *dev);
> > >  void ironlake_teardown_rc6(struct drm_device *dev);
> > >  void gen6_update_ring_freq(struct drm_device *dev);
> > >  void gen6_rps_idle(struct drm_i915_private *dev_priv);
> > > @@ -931,6 +932,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv);
> > >  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
> > >  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> > >  void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> > > +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
> > >  void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> > >  void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> > >  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index e5b9f08..0e8b263 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -4549,6 +4549,8 @@ static void intel_gen6_powersave_work(struct work_struct *work)
> > >  	}
> > >  	dev_priv->rps.enabled = true;
> > >  	mutex_unlock(&dev_priv->rps.hw_lock);
> > > +
> > > +	intel_runtime_pm_put(dev_priv);
> > >  }
> > >  
> > >  void intel_enable_gt_powersave(struct drm_device *dev)
> > > @@ -4566,12 +4568,28 @@ void intel_enable_gt_powersave(struct drm_device *dev)
> > >  		 * PCU communication is slow and this doesn't need to be
> > >  		 * done at any specific time, so do this out of our fast path
> > >  		 * to make resume and init faster.
> > > +		 *
> > > +		 * We depend on the HW RC6 power context save/restore
> > > +		 * mechanism when entering D3 through runtime PM suspend. So
> > > +		 * disable RPM until RPS/RC6 is properly setup. We can only
> > > +		 * get here via the driver load/system resume/runtime resume
> > > +		 * paths, so the _noresume version is enough (and in case of
> > > +		 * runtime resume it's necessary).
> > >  		 */
> > > -		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> > > -				      round_jiffies_up_relative(HZ));
> > > +		if (schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
> > > +					   round_jiffies_up_relative(HZ)))
> > > +			intel_runtime_pm_get_noresume(dev_priv);
> > >  	}
> > >  }
> > >  
> > > +void intel_reset_gt_powersave(struct drm_device *dev)
> > > +{
> > > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > > +
> > > +	dev_priv->rps.enabled = false;
> > > +	intel_enable_gt_powersave(dev);
> > > +}
> > > +
> > >  static void ibx_init_clock_gating(struct drm_device *dev)
> > >  {
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > @@ -6025,6 +6043,18 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> > >  	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> > >  }
> > >  
> > > +void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
> > > +{
> > > +	struct drm_device *dev = dev_priv->dev;
> > > +	struct device *device = &dev->pdev->dev;
> > > +
> > > +	if (!HAS_RUNTIME_PM(dev))
> > > +		return;
> > > +
> > > +	WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
> > 
> > Do we really need our own tracking in dev_priv->pm.suspended, is there
> > nothing in the runtime pm core which we could use instaed?
> 
> Hm, yes by a quick look pm_runtime_suspended() seems like what we could
> use instead. But this was just copy&paste, and the rest of the spots
> would need changing too, so could we do it as a follow-up?

Sure, and then we could remove them all. Was just something I've spotted
since in general I don't like it if we track the same state in multiple
places - sooner or later it will get out of sync and lead to subtile bugs.

dev_priv->pm.irqs_enabled is also a bit a tricky bit since we already have
dev->irqs_enable. But they do track something slightly different, so we
need to keep that one. Still confusing at first glance.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock
  2014-04-14 17:24 ` [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock Imre Deak
@ 2014-04-25 14:04   ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-04-25 14:04 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:43PM +0300, Imre Deak wrote:
> I've seen latencies up to 15msec, so increase the timeout to 20msec.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Merged up to this patch here, thanks.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 0609f77..845e1e1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -916,7 +916,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  #define COND (I915_READ(VLV_GTLC_SURVIVABILITY_REG) & VLV_GFX_CLK_STATUS_BIT)
>  	/* Wait for a previous force on/off to settle */
>  	if (force_on) {
> -		err = wait_for(!COND, 5);
> +		err = wait_for(!COND, 20);
>  		if (err) {
>  			DRM_ERROR("timeout waiting for GFX clock force-off (%08x)\n",
>  				  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> @@ -933,7 +933,7 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  	if (!force_on)
>  		return 0;
>  
> -	err = wait_for(COND, 5);
> +	err = wait_for(COND, 20);
>  	if (err)
>  		DRM_ERROR("timeout waiting for GFX clock force-on (%08x)\n",
>  			  I915_READ(VLV_GTLC_SURVIVABILITY_REG));
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
  2014-04-24 21:17   ` Rodrigo Vivi
@ 2014-04-30 14:32   ` Ville Syrjälä
  2014-05-05 11:43     ` Imre Deak
  2014-05-05 12:13   ` [PATCH v3 " Imre Deak
  2 siblings, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-30 14:32 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:24:44PM +0300, Imre Deak wrote:
> Needed by the VLV S0ix context save/restore helpers.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h | 43 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f183746..cba0afd 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -92,6 +92,9 @@
>  #define   GEN6_MBC_SNPCR_LOW	(2<<21)
>  #define   GEN6_MBC_SNPCR_MIN	(3<<21) /* only 1/16th of the cache is shared */
>  
> +#define GEN7_G3DCTL		0x9024
> +#define GEN7_GSCKGCTL		0x9028

AFAICS these are VLV specific. There are some other registers at
the same offset on other platforms.

> +
>  #define GEN6_MBCTL		0x0907c
>  #define   GEN6_MBCTL_ENABLE_BOOT_FETCH	(1 << 4)
>  #define   GEN6_MBCTL_CTX_FETCH_NEEDED	(1 << 3)
> @@ -785,9 +788,20 @@ enum punit_power_well {
>  #define RING_MAX_IDLE(base)	((base)+0x54)
>  #define RING_HWS_PGA(base)	((base)+0x80)
>  #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
> -#define ARB_MODE		0x04030
> +
> +#define GEN7_WR_WATERMARK	0x4028
> +#define GEN7_GFX_PRIO_CTRL	0x402C
> +#define ARB_MODE		0x4030
>  #define   ARB_MODE_SWIZZLE_SNB	(1<<4)
>  #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
> +#define GEN7_GFX_PEND_TLB0	0x4034
> +#define GEN7_GFX_PEND_TLB1	0x4038

I was going to say these are already in gen6, but looks like the offset
changed slightly in gen7. So the gen7 name is good here.

> +/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
> +#define GEN7_LRA_LIMITS_BASE	0x403C
> +#define GEN7_LRA_LIMITS_REG_NUM	13
> +#define GEN7_MEDIA_MAX_REQ_COUNT	0x4070
> +#define GEN7_GFX_MAX_REQ_COUNT		0x4074
> +
>  #define GAMTARBMODE		0x04a08
>  #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
>  #define   ARB_MODE_SWIZZLE_BDW	(1<<1)
> @@ -822,6 +836,9 @@ enum punit_power_well {
>  #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
>  #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
>  #define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
> +
> +#define GEN7_TLB_RD_ADDR	0x4700
> +
>  #if 0
>  #define PRB0_TAIL	0x02030
>  #define PRB0_HEAD	0x02034
> @@ -948,6 +965,8 @@ enum punit_power_well {
>  
>  #define VLV_DISPLAY_BASE 0x180000
>  
> +#define VLV_GU_CTL0	(VLV_DISPLAY_BASE + 0x2030)
> +#define VLV_GU_CTL1	(VLV_DISPLAY_BASE + 0x2034)
>  #define SCPD0		0x0209c /* 915+ only */
>  #define IER		0x020a0
>  #define IIR		0x020a4
> @@ -955,6 +974,7 @@ enum punit_power_well {
>  #define ISR		0x020ac
>  #define VLV_GUNIT_CLOCK_GATE	(VLV_DISPLAY_BASE + 0x2060)
>  #define   GCFG_DIS		(1<<8)
> +#define VLV_GUNIT_CLOCK_GATE2	(VLV_DISPLAY_BASE + 0x2064)
>  #define VLV_IIR_RW	(VLV_DISPLAY_BASE + 0x2084)
>  #define VLV_IER		(VLV_DISPLAY_BASE + 0x20a0)
>  #define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
> @@ -4988,6 +5008,8 @@ enum punit_power_well {
>  
>  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
>  
> +#define  VLV_PMWGICZ				0x1300a4
> +
>  #define  FORCEWAKE				0xA18C
>  #define  FORCEWAKE_VLV				0x1300b0
>  #define  FORCEWAKE_ACK_VLV			0x1300b4
> @@ -5011,6 +5033,7 @@ enum punit_power_well {
>  #define  FORCEWAKE_MT_ACK			0x130040
>  #define  ECOBUS					0xa180
>  #define    FORCEWAKE_MT_ENABLE			(1<<5)
> +#define  VLV_SPAREG2H				0xA194
>  
>  #define  GTFIFODBG				0x120000
>  #define    GT_FIFO_SBDROPERR			(1<<6)
> @@ -5040,12 +5063,24 @@ enum punit_power_well {
>  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
>  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
>  
> +#define GEN7_UCGCTL3				0x9408
> +
>  #define GEN7_UCGCTL4				0x940c
>  #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)

SNB already has UCGCTL3 and 4. So even the old name is a bit wrong.

>  
> +#define GEN7_RCGCTL1				0x9410
> +#define GEN7_RCGCTL2				0x9414
> +#define GEN7_RSTCTL				0x9420

These too already exist on gen6.

Same for GEN7_MISCCPCTL which should probably also be moved here and
renamed.

> +
>  #define GEN8_UCGCTL6				0x9430
>  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE	(1<<14)
>  
> +#define GEN7_GFXPAUSE				0xA000
> +#define GEN7_RPDEUHWTC				0xA080
> +#define GEN7_RPDEUC				0xA084

These three are already listed in my snb pm guide, so gen6. Also
should be inserted into the correct spot numerically.

> +
> +#define VLV_PWRDWNUPCTL				0xA294
> +
>  #define GEN6_RPNSWREQ				0xA008
>  #define   GEN6_TURBO_DISABLE			(1<<31)
>  #define   GEN6_FREQUENCY(x)			((x)<<25)
> @@ -5098,6 +5133,7 @@ enum punit_power_well {
>  #define GEN6_RP_UP_EI				0xA068
>  #define GEN6_RP_DOWN_EI				0xA06C
>  #define GEN6_RP_IDLE_HYSTERSIS			0xA070
> +#define GEN7_RPDEUCSW				0xA088

This one isn't listed in the snb pm guide, but I get the impression
it should also say gen6 here.

>  #define GEN6_RC_STATE				0xA094
>  #define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
>  #define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
> @@ -5105,9 +5141,11 @@ enum punit_power_well {
>  #define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
>  #define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
>  #define GEN6_RC_SLEEP				0xA0B0
> +#define VLV_RCUBMABDTMR				0xA0B0

Also seems like it should be gen6.

All the rest look fine.

>  #define GEN6_RC1e_THRESHOLD			0xA0B4
>  #define GEN6_RC6_THRESHOLD			0xA0B8
>  #define GEN6_RC6p_THRESHOLD			0xA0BC
> +#define VLV_RCEDATA				0xA0BC
>  #define GEN6_RC6pp_THRESHOLD			0xA0C0
>  #define GEN6_PMINTRMSK				0xA168
>  
> @@ -5126,6 +5164,9 @@ enum punit_power_well {
>  						 GEN6_PM_RP_DOWN_THRESHOLD | \
>  						 GEN6_PM_RP_DOWN_TIMEOUT)
>  
> +#define GEN7_GT_SCRATCH_BASE			0x4F100
> +#define GEN7_GT_SCRATCH_REG_NUM			8
> +
>  #define VLV_GTLC_SURVIVABILITY_REG              0x130098
>  #define VLV_GFX_CLK_STATUS_BIT			(1<<3)
>  #define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 25/25] drm/i915: vlv: add runtime PM support
  2014-04-22 17:28   ` [PATCH v3 " Imre Deak
  2014-04-22 22:09     ` [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
@ 2014-04-30 17:35     ` Ville Syrjälä
  2014-05-05  9:33       ` Daniel Vetter
  2014-05-05 12:19     ` [PATCH v4 " Imre Deak
  2 siblings, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-30 17:35 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Apr 22, 2014 at 08:28:33PM +0300, Imre Deak wrote:
> Add runtime PM support for VLV, but leave it disabled. The next patch
> enables it.
> 
> The suspend/resume sequence used is based on [1] and [2]. In practice we
> depend on the GT RC6 mechanism to save the HW context depending on the
> render and media power wells. By the time we run the runtime suspend
> callback the display side is also off and the HW context for that is
> managed by the display power domain framework.
> 
> Besides the above there are Gunit registers that depend on a system-wide
> power well. This power well goes off once the device enters any of the
> S0i[R123] states. To handle this scenario, save/restore these Gunit
> registers. Note that this is not the complete register set dictated by
> [2], to remove some overhead, registers that are known not to be used are
> ignored. Also some registers are fully setup by initialization functions
> called during resume, these are not saved either. The list of registers
> can be further reduced, see the TODO note in the code.
> 
> [1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
> [2] VLV2_S0IXRegs
> 
> v2:
> - unchanged
> v3:
> - fix s/GEN6_PMIIR/GEN6_PMIMR/ typo when saving/restoring registers
>   (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
>  2 files changed, 389 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 31988f6..0a96a5d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +/*
> + * Save all Gunit registers that may be lost after a D3 and a subsequent
> + * S0i[R123] transition. The list of registers needing a save/restore is
> + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
> + * registers in the following way:
> + * - Driver: saved/restored by the driver
> + * - Punit : saved/restored by the Punit firmware
> + * - No, w/o marking: no need to save/restore, since the register is R/O or
> + *                    used internally by the HW in a way that doesn't depend
> + *                    keeping the content across a suspend/resume.
> + * - Debug : used for debugging
> + *
> + * We save/restore all registers marked with 'Driver', with the following
> + * exceptions:
> + * - Registers out of use, including also registers marked with 'Debug'.
> + *   These have no effect on the driver's operation, so we don't save/restore
> + *   them to reduce the overhead.
> + * - Registers that are fully setup by an initialization function called from
> + *   the resume path. For example many clock gating and RPS/RC6 registers.
> + * - Registers that provide the right functionality with their reset defaults.
> + *
> + * TODO: Except for registers that based on the above 3 criteria can be safely
> + * ignored, we save/restore all others, practically treating the HW context as
> + * a black-box for the driver. Further investigation is needed to reduce the
> + * saved/restored registers even further, by following the same 3 criteria.
> + */
> +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
> +	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
> +	s->arb_mode		= I915_READ(ARB_MODE);
> +	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
> +	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
> +
> +	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
> +
> +	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
> +	s->ecochk		= I915_READ(GAM_ECOCHK);
> +	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
> +	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
> +
> +	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	s->g3dctl		= I915_READ(GEN7_G3DCTL);
> +	s->gsckgctl		= I915_READ(GEN7_GSCKGCTL);
> +	s->mbctl		= I915_READ(GEN6_MBCTL);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
> +	s->ucgctl3		= I915_READ(GEN7_UCGCTL3);
> +	s->rcgctl1		= I915_READ(GEN7_RCGCTL1);
> +	s->rcgctl2		= I915_READ(GEN7_RCGCTL2);
> +	s->rstctl		= I915_READ(GEN7_RSTCTL);
> +	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	s->gfxpause		= I915_READ(GEN7_GFXPAUSE);
> +	s->rpdeuhwtc		= I915_READ(GEN7_RPDEUHWTC);
> +	s->rpdeuc		= I915_READ(GEN7_RPDEUC);
> +	s->ecobus		= I915_READ(ECOBUS);
> +	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
> +	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
> +	s->rp_deucsw		= I915_READ(GEN7_RPDEUCSW);
> +	s->rcubmabdtmr		= I915_READ(VLV_RCUBMABDTMR);
> +	s->rcedata		= I915_READ(VLV_RCEDATA);
> +	s->spare2gh		= I915_READ(VLV_SPAREG2H);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	s->gt_imr		= I915_READ(GTIMR);
> +	s->gt_ier		= I915_READ(GTIER);
> +	s->pm_imr		= I915_READ(GEN6_PMIMR);
> +	s->pm_ier		= I915_READ(GEN6_PMIER);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	s->tilectl		= I915_READ(TILECTL);
> +	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
> +	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
> +	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
> +	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
> +	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
> +
> +	/*
> +	 * Not saving any of:
> +	 * DFT,		0x9800-0x9EC0
> +	 * SARB,	0xB000-0xB1FC
> +	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
> +	 * PCI CFG
> +	 */
> +}
> +
> +static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
> +{
> +	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
> +	u32 val;
> +	int i;
> +
> +	/* GAM 0x4000-0x4770 */
> +	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
> +	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
> +	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
> +	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
> +	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
> +		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
> +
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
> +	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
> +
> +	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
> +	I915_WRITE(GAM_ECOCHK,		s->ecochk);
> +	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
> +	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
> +
> +	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
> +
> +	/* MBC 0x9024-0x91D0, 0x8500 */
> +	I915_WRITE(GEN7_G3DCTL,		s->g3dctl);
> +	I915_WRITE(GEN7_GSCKGCTL,	s->gsckgctl);
> +	I915_WRITE(GEN6_MBCTL,		s->mbctl);
> +
> +	/* GCP 0x9400-0x9424, 0x8100-0x810C */
> +	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
> +	I915_WRITE(GEN7_UCGCTL3,	s->ucgctl3);
> +	I915_WRITE(GEN7_RCGCTL1,	s->rcgctl1);
> +	I915_WRITE(GEN7_RCGCTL2,	s->rcgctl2);
> +	I915_WRITE(GEN7_RSTCTL,		s->rstctl);
> +	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
> +
> +	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
> +	I915_WRITE(GEN7_GFXPAUSE,	s->gfxpause);
> +	I915_WRITE(GEN7_RPDEUHWTC,	s->rpdeuhwtc);
> +	I915_WRITE(GEN7_RPDEUC,		s->rpdeuc);
> +	I915_WRITE(ECOBUS,		s->ecobus);
> +	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
> +	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
> +	I915_WRITE(GEN7_RPDEUCSW,	s->rp_deucsw);
> +	I915_WRITE(VLV_RCUBMABDTMR,	s->rcubmabdtmr);
> +	I915_WRITE(VLV_RCEDATA,		s->rcedata);
> +	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
> +
> +	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
> +	I915_WRITE(GTIMR,		s->gt_imr);
> +	I915_WRITE(GTIER,		s->gt_ier);
> +	I915_WRITE(GEN6_PMIMR,		s->pm_imr);
> +	I915_WRITE(GEN6_PMIER,		s->pm_ier);
> +
> +	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
> +		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
> +
> +	/* GT SA CZ domain, 0x100000-0x138124 */
> +	I915_WRITE(TILECTL,			s->tilectl);
> +	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
> +	/*
> +	 * Preserve the GT allow wake and GFX force clock bit, they are not
> +	 * be restored, as they are used to control the s0ix suspend/resume
> +	 * sequence by the caller.
> +	 */
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= VLV_GTLC_ALLOWWAKEREQ;
> +	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +
> +	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
> +	val &= VLV_GFX_CLK_FORCE_ON_BIT;
> +	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
> +	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
> +
> +	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
> +
> +	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
> +	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
> +	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
> +	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
> +}

I know Daniel hates this stuff, but I don't really want to bikeshed it
now. As we've discussed we should get the thing to enter some s0ix state
where we actually lost the context and then dump a ton of registers and
figure out what really gets lost, and if the reset values are
sufficient or not. So I think merging this as is is good enough and then
we can figure out the rest later once s0ix works.

> +
>  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  {
>  	u32 val;
> @@ -948,6 +1140,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
>  #undef COND
>  }
>  
> +static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
> +{
> +	u32 val;
> +	int err = 0;
> +
> +	val = I915_READ(VLV_GTLC_WAKE_CTRL);
> +	val &= ~VLV_GTLC_ALLOWWAKEREQ;
> +	if (allow)
> +		val |= VLV_GTLC_ALLOWWAKEREQ;
> +	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
> +	POSTING_READ(VLV_GTLC_WAKE_CTRL);
> +
> +#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
> +	      allow)
> +	err = wait_for(COND, 1);
> +	if (err)
> +		DRM_ERROR("timeout disabling GT waking\n");
> +	return err;
> +#undef COND
> +}
> +
> +static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
> +				 bool wait_for_on)
> +{
> +	u32 mask;
> +	u32 val;
> +	int err;
> +
> +	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
> +	val = wait_for_on ? mask : 0;
> +#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
> +	if (COND)
> +		return 0;
> +
> +	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
> +			wait_for_on ? "on" : "off",
> +			I915_READ(VLV_GTLC_PW_STATUS));
> +
> +	/*
> +	 * RC6 transitioning can be delayed up to 2 msec (see
> +	 * valleyview_enable_rps), use 3 msec for safety.
> +	 */
> +	err = wait_for(COND, 3);
> +	if (err)
> +		DRM_ERROR("timeout waiting for GT wells to go %s\n",
> +			  wait_for_on ? "on" : "off");
> +
> +	return err;
> +#undef COND
> +}
> +
> +static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
> +{
> +	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
> +		return;
> +
> +	DRM_ERROR("GT register access while GT waking disabled\n");
> +	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
> +}
> +
> +static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
> +{
> +	u32 mask;
> +	int err;
> +
> +	/*
> +	 * Bspec defines the following GT well on flags as debug only, so
> +	 * don't treat them as hard failures.
> +	 */
> +	(void)vlv_wait_for_gt_wells(dev_priv, false);
> +
> +	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
> +	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, true);
> +	if (err)
> +		goto err1;
> +
> +	err = vlv_allow_gt_wake(dev_priv, false);
> +	if (err)
> +		goto err2;
> +	vlv_save_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (err)
> +		goto err2;
> +
> +	return 0;
> +
> +err2:
> +	/* For safety always re-enable waking and disable gfx clock forcing */
> +	vlv_allow_gt_wake(dev_priv, true);
> +err1:
> +	vlv_force_gfx_clock(dev_priv, false);
> +
> +	return err;
> +}
> +
> +static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	int err;
> +	int ret;
> +
> +	/*
> +	 * If any of the steps fail just try to continue, that's the best we
> +	 * can do at this point. Return the first error code (which will also
> +	 * leave RPM permanently disabled).
> +	 */
> +	ret = vlv_force_gfx_clock(dev_priv, true);
> +
> +	vlv_restore_gunit_s0ix_state(dev_priv);
> +
> +	err = vlv_allow_gt_wake(dev_priv, true);
> +	if (!ret)
> +		ret = err;
> +
> +	err = vlv_force_gfx_clock(dev_priv, false);
> +	if (!ret)
> +		ret = err;

The doc tells us to release the gfx_clock before setting ALLOWWAKEREQ.
But that's not symmetric with the disable so it seems a bit funky. If
the symmetric sequence works, then it seems more sane to me.

The other oddball thing about the documents is that it tells us to
do all the resume stuff before the device is back in D0. So again
not symmetric and also just seems wrong. The punit looks at the PCI
power state of the device to determine if s0ix is possible so surely
we should set it back to D0 before doing much of anything else. Also
since that part is done by the common pci code we can't do it quite
like to doc says.

So I think this patch is just fine as is:
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +
> +	vlv_check_no_gt_access(dev_priv);
> +
> +	intel_init_clock_gating(dev);
> +	i915_gem_restore_fences(dev);
> +
> +	return ret;
> +}
> +
>  static int intel_runtime_suspend(struct device *device)
>  {
>  	struct pci_dev *pdev = to_pci_dev(device);
> @@ -975,6 +1298,8 @@ static int intel_runtime_suspend(struct device *device)
>  		ret = 0;
>  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_suspend(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_suspend(dev_priv);
>  	} else {
>  		ret = -ENODEV;
>  		WARN_ON(1);
> @@ -1023,6 +1348,8 @@ static int intel_runtime_resume(struct device *device)
>  		ret = snb_runtime_resume(dev_priv);
>  	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		ret = hsw_runtime_resume(dev_priv);
> +	} else if (IS_VALLEYVIEW(dev)) {
> +		ret = vlv_runtime_resume(dev_priv);
>  	} else {
>  		WARN_ON(1);
>  		ret = -ENODEV;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3cac434..77cb7fc 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
>  	u32 savePCH_PORT_HOTPLUG;
>  };
>  
> +struct vlv_s0ix_state {
> +	/* GAM */
> +	u32 wr_watermark;
> +	u32 gfx_prio_ctrl;
> +	u32 arb_mode;
> +	u32 gfx_pend_tlb0;
> +	u32 gfx_pend_tlb1;
> +	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
> +	u32 media_max_req_count;
> +	u32 gfx_max_req_count;
> +	u32 render_hwsp;
> +	u32 ecochk;
> +	u32 bsd_hwsp;
> +	u32 blt_hwsp;
> +	u32 tlb_rd_addr;
> +
> +	/* MBC */
> +	u32 g3dctl;
> +	u32 gsckgctl;
> +	u32 mbctl;
> +
> +	/* GCP */
> +	u32 ucgctl1;
> +	u32 ucgctl3;
> +	u32 rcgctl1;
> +	u32 rcgctl2;
> +	u32 rstctl;
> +	u32 misccpctl;
> +
> +	/* GPM */
> +	u32 gfxpause;
> +	u32 rpdeuhwtc;
> +	u32 rpdeuc;
> +	u32 ecobus;
> +	u32 pwrdwnupctl;
> +	u32 rp_down_timeout;
> +	u32 rp_deucsw;
> +	u32 rcubmabdtmr;
> +	u32 rcedata;
> +	u32 spare2gh;
> +
> +	/* Display 1 CZ domain */
> +	u32 gt_imr;
> +	u32 gt_ier;
> +	u32 pm_imr;
> +	u32 pm_ier;
> +	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
> +
> +	/* GT SA CZ domain */
> +	u32 tilectl;
> +	u32 gt_fifoctl;
> +	u32 gtlc_wake_ctrl;
> +	u32 gtlc_survive;
> +	u32 pmwgicz;
> +
> +	/* Display 2 CZ domain */
> +	u32 gu_ctl0;
> +	u32 gu_ctl1;
> +	u32 clock_gate_dis2;
> +};
> +
>  struct intel_gen6_power_mgmt {
>  	/* work and pm_iir are protected by dev_priv->irq_lock */
>  	struct work_struct work;
> @@ -1447,6 +1508,7 @@ struct drm_i915_private {
>  
>  	u32 suspend_count;
>  	struct i915_suspend_saved_registers regfile;
> +	struct vlv_s0ix_state vlv_s0ix_state;
>  
>  	struct {
>  		/*
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-04-15 13:39   ` [PATCH v3 " Imre Deak
@ 2014-04-30 18:05     ` Ville Syrjälä
  2014-04-30 18:53       ` Imre Deak
  0 siblings, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-04-30 18:05 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Apr 15, 2014 at 04:39:45PM +0300, Imre Deak wrote:
> Atm, none of the RPM callbacks can fail, but the next patch adding
> RPM support for VLV changes this, so prepare for it.
> 
> In case one of these callbacks return error RPM will get permanently
> disabled until the error is explicitly cleared. In the future we could
> add support for re-enabling it, for example after resetting the HW, but
> for now - hopefully - we can live with the simpler solution.
> 
> v2:
> - propagate the error from the resume callbacks too (Paulo)
> v3:
> - fix rebase fail typo around IS_GEN6() check in intel_runtime_suspend()
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
>  1 file changed, 42 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 845e1e1..aeb7dec 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
>  	return i915_drm_freeze(drm_dev);
>  }
>  
> -static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
>  {
>  	hsw_enable_pc8(dev_priv);
> +
> +	return 0;
>  }
>  
> -static void snb_runtime_resume(struct drm_i915_private *dev_priv)
> +static int snb_runtime_resume(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
>  
>  	intel_init_pch_refclk(dev);
> +
> +	return 0;
>  }
>  
> -static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
>  {
>  	hsw_disable_pc8(dev_priv);
> +
> +	return 0;
>  }
>  
>  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> @@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
>  	struct pci_dev *pdev = to_pci_dev(device);
>  	struct drm_device *dev = pci_get_drvdata(pdev);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int ret;
>  
>  	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
>  		return -ENODEV;
> @@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
>  	intel_runtime_pm_disable_interrupts(dev);
>  	cancel_work_sync(&dev_priv->rps.work);
>  
> -	if (IS_GEN6(dev))
> -		;
> -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> -		hsw_runtime_suspend(dev_priv);
> -	else
> +	if (IS_GEN6(dev)) {
> +		ret = 0;
> +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> +		ret = hsw_runtime_suspend(dev_priv);
> +	} else {
> +		ret = -ENODEV;
>  		WARN_ON(1);
> +	}
> +
> +	if (ret) {
> +		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
> +		intel_runtime_pm_restore_interrupts(dev);
> +
> +		return ret;
> +	}
>  
>  	i915_gem_release_all_mmaps(dev_priv);

Not strictly related to this patch, but shouldn't we nuke the mmaps before
calling the platform specific runtime suspend function?

This patch itself looks ok to me:
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  
> @@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
>  	struct pci_dev *pdev = to_pci_dev(device);
>  	struct drm_device *dev = pci_get_drvdata(pdev);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int ret;
>  
>  	WARN_ON(!HAS_RUNTIME_PM(dev));
>  
> @@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
>  	intel_opregion_notify_adapter(dev, PCI_D0);
>  	dev_priv->pm.suspended = false;
>  
> -	if (IS_GEN6(dev))
> -		snb_runtime_resume(dev_priv);
> -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> -		hsw_runtime_resume(dev_priv);
> -	else
> +	if (IS_GEN6(dev)) {
> +		ret = snb_runtime_resume(dev_priv);
> +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> +		ret = hsw_runtime_resume(dev_priv);
> +	} else {
>  		WARN_ON(1);
> +		ret = -ENODEV;
> +	}
>  
> +	/*
> +	 * No point of rolling back things in case of an error, as the best
> +	 * we can do is to hope that things will still work (and disable RPM).
> +	 */
>  	i915_gem_init_swizzling(dev);
>  	gen6_update_ring_freq(dev);
>  	intel_reset_gt_powersave(dev);
>  
>  	intel_runtime_pm_restore_interrupts(dev);
>  
> -	DRM_DEBUG_KMS("Device resumed\n");
> -	return 0;
> +	if (ret)
> +		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
> +	else
> +		DRM_DEBUG_KMS("Device resumed\n");
> +
> +	return ret;
>  }
>  
>  static const struct dev_pm_ops i915_pm_ops = {
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-04-30 18:05     ` Ville Syrjälä
@ 2014-04-30 18:53       ` Imre Deak
  2014-05-05 12:44         ` Ville Syrjälä
  0 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-04-30 18:53 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, 2014-04-30 at 21:05 +0300, Ville Syrjälä wrote:
> On Tue, Apr 15, 2014 at 04:39:45PM +0300, Imre Deak wrote:
> > Atm, none of the RPM callbacks can fail, but the next patch adding
> > RPM support for VLV changes this, so prepare for it.
> > 
> > In case one of these callbacks return error RPM will get permanently
> > disabled until the error is explicitly cleared. In the future we could
> > add support for re-enabling it, for example after resetting the HW, but
> > for now - hopefully - we can live with the simpler solution.
> > 
> > v2:
> > - propagate the error from the resume callbacks too (Paulo)
> > v3:
> > - fix rebase fail typo around IS_GEN6() check in intel_runtime_suspend()
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
> >  1 file changed, 42 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 845e1e1..aeb7dec 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
> >  	return i915_drm_freeze(drm_dev);
> >  }
> >  
> > -static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> > +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> >  {
> >  	hsw_enable_pc8(dev_priv);
> > +
> > +	return 0;
> >  }
> >  
> > -static void snb_runtime_resume(struct drm_i915_private *dev_priv)
> > +static int snb_runtime_resume(struct drm_i915_private *dev_priv)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> >  
> >  	intel_init_pch_refclk(dev);
> > +
> > +	return 0;
> >  }
> >  
> > -static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> > +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
> >  {
> >  	hsw_disable_pc8(dev_priv);
> > +
> > +	return 0;
> >  }
> >  
> >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> > @@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
> >  	struct pci_dev *pdev = to_pci_dev(device);
> >  	struct drm_device *dev = pci_get_drvdata(pdev);
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	int ret;
> >  
> >  	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
> >  		return -ENODEV;
> > @@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
> >  	intel_runtime_pm_disable_interrupts(dev);
> >  	cancel_work_sync(&dev_priv->rps.work);
> >  
> > -	if (IS_GEN6(dev))
> > -		;
> > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > -		hsw_runtime_suspend(dev_priv);
> > -	else
> > +	if (IS_GEN6(dev)) {
> > +		ret = 0;
> > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > +		ret = hsw_runtime_suspend(dev_priv);
> > +	} else {
> > +		ret = -ENODEV;
> >  		WARN_ON(1);
> > +	}
> > +
> > +	if (ret) {
> > +		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
> > +		intel_runtime_pm_restore_interrupts(dev);
> > +
> > +		return ret;
> > +	}
> >  
> >  	i915_gem_release_all_mmaps(dev_priv);
> 
> Not strictly related to this patch, but shouldn't we nuke the mmaps before
> calling the platform specific runtime suspend function?

We take an RPM ref on the fault path, so at least this couldn't race
with user space either way. But if you meant that the platform hooks
could save/restore some stale state because of this ordering, then I
agree it'd be safer to move it before calling the platform hook. But I
don't see what this state would be.

--Imre

> This patch itself looks ok to me:
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> >  
> > @@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
> >  	struct pci_dev *pdev = to_pci_dev(device);
> >  	struct drm_device *dev = pci_get_drvdata(pdev);
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	int ret;
> >  
> >  	WARN_ON(!HAS_RUNTIME_PM(dev));
> >  
> > @@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
> >  	intel_opregion_notify_adapter(dev, PCI_D0);
> >  	dev_priv->pm.suspended = false;
> >  
> > -	if (IS_GEN6(dev))
> > -		snb_runtime_resume(dev_priv);
> > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > -		hsw_runtime_resume(dev_priv);
> > -	else
> > +	if (IS_GEN6(dev)) {
> > +		ret = snb_runtime_resume(dev_priv);
> > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > +		ret = hsw_runtime_resume(dev_priv);
> > +	} else {
> >  		WARN_ON(1);
> > +		ret = -ENODEV;
> > +	}
> >  
> > +	/*
> > +	 * No point of rolling back things in case of an error, as the best
> > +	 * we can do is to hope that things will still work (and disable RPM).
> > +	 */
> >  	i915_gem_init_swizzling(dev);
> >  	gen6_update_ring_freq(dev);
> >  	intel_reset_gt_powersave(dev);
> >  
> >  	intel_runtime_pm_restore_interrupts(dev);
> >  
> > -	DRM_DEBUG_KMS("Device resumed\n");
> > -	return 0;
> > +	if (ret)
> > +		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
> > +	else
> > +		DRM_DEBUG_KMS("Device resumed\n");
> > +
> > +	return ret;
> >  }
> >  
> >  static const struct dev_pm_ops i915_pm_ops = {
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


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

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

* Re: [PATCH v3 25/25] drm/i915: vlv: add runtime PM support
  2014-04-30 17:35     ` [PATCH v3 25/25] drm/i915: vlv: add runtime PM support Ville Syrjälä
@ 2014-05-05  9:33       ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-05-05  9:33 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Apr 30, 2014 at 7:35 PM, Ville Syrjälä
<ville.syrjala@linux.intel.com> wrote:
> I know Daniel hates this stuff, but I don't really want to bikeshed it
> now. As we've discussed we should get the thing to enter some s0ix state
> where we actually lost the context and then dump a ton of registers and
> figure out what really gets lost, and if the reset values are
> sufficient or not. So I think merging this as is is good enough and then
> we can figure out the rest later once s0ix works.

Yeah, from a quick read there's a few things we should look into:
- Stuff which seems fully redundant like the irq registers - we
already run the relevant functions on runtime pm exit, and if there's
something missing we need to do it here.
- Stuff which duplicates logic we already have, like all the ring
registers. Imo we should just stop/restart rings on all platforms.
Some of those registers writes might need to be moved around, e.g. out
of the clock_gating_init functions into other places.
- Registers we only ever read or completely ignore (like gtfifo_ctl or
the various tlb registers). We need to check whether we really must
store something there and if that's the case, we need to store
something fixed instead of whatever's been there at suspend. E.g. if
gtfifo_ctl indeed needs to be reset to prevent the hw from throwing
fits we should just write the right value in there.

But I guess we can do this as a follow-up. But expect me to be
annoying about this ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-30 14:32   ` Ville Syrjälä
@ 2014-05-05 11:43     ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-05-05 11:43 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, 2014-04-30 at 17:32 +0300, Ville Syrjälä wrote:
> On Mon, Apr 14, 2014 at 08:24:44PM +0300, Imre Deak wrote:
> > Needed by the VLV S0ix context save/restore helpers.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h | 43 ++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 42 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index f183746..cba0afd 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -92,6 +92,9 @@
> >  #define   GEN6_MBC_SNPCR_LOW	(2<<21)
> >  #define   GEN6_MBC_SNPCR_MIN	(3<<21) /* only 1/16th of the cache is shared */
> >  
> > +#define GEN7_G3DCTL		0x9024
> > +#define GEN7_GSCKGCTL		0x9028
> 
> AFAICS these are VLV specific. There are some other registers at
> the same offset on other platforms.
> 
> > +
> >  #define GEN6_MBCTL		0x0907c
> >  #define   GEN6_MBCTL_ENABLE_BOOT_FETCH	(1 << 4)
> >  #define   GEN6_MBCTL_CTX_FETCH_NEEDED	(1 << 3)
> > @@ -785,9 +788,20 @@ enum punit_power_well {
> >  #define RING_MAX_IDLE(base)	((base)+0x54)
> >  #define RING_HWS_PGA(base)	((base)+0x80)
> >  #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
> > -#define ARB_MODE		0x04030
> > +
> > +#define GEN7_WR_WATERMARK	0x4028
> > +#define GEN7_GFX_PRIO_CTRL	0x402C
> > +#define ARB_MODE		0x4030
> >  #define   ARB_MODE_SWIZZLE_SNB	(1<<4)
> >  #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
> > +#define GEN7_GFX_PEND_TLB0	0x4034
> > +#define GEN7_GFX_PEND_TLB1	0x4038
> 
> I was going to say these are already in gen6, but looks like the offset
> changed slightly in gen7. So the gen7 name is good here.
> 
> > +/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
> > +#define GEN7_LRA_LIMITS_BASE	0x403C
> > +#define GEN7_LRA_LIMITS_REG_NUM	13
> > +#define GEN7_MEDIA_MAX_REQ_COUNT	0x4070
> > +#define GEN7_GFX_MAX_REQ_COUNT		0x4074
> > +
> >  #define GAMTARBMODE		0x04a08
> >  #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
> >  #define   ARB_MODE_SWIZZLE_BDW	(1<<1)
> > @@ -822,6 +836,9 @@ enum punit_power_well {
> >  #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
> >  #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
> >  #define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
> > +
> > +#define GEN7_TLB_RD_ADDR	0x4700
> > +
> >  #if 0
> >  #define PRB0_TAIL	0x02030
> >  #define PRB0_HEAD	0x02034
> > @@ -948,6 +965,8 @@ enum punit_power_well {
> >  
> >  #define VLV_DISPLAY_BASE 0x180000
> >  
> > +#define VLV_GU_CTL0	(VLV_DISPLAY_BASE + 0x2030)
> > +#define VLV_GU_CTL1	(VLV_DISPLAY_BASE + 0x2034)
> >  #define SCPD0		0x0209c /* 915+ only */
> >  #define IER		0x020a0
> >  #define IIR		0x020a4
> > @@ -955,6 +974,7 @@ enum punit_power_well {
> >  #define ISR		0x020ac
> >  #define VLV_GUNIT_CLOCK_GATE	(VLV_DISPLAY_BASE + 0x2060)
> >  #define   GCFG_DIS		(1<<8)
> > +#define VLV_GUNIT_CLOCK_GATE2	(VLV_DISPLAY_BASE + 0x2064)
> >  #define VLV_IIR_RW	(VLV_DISPLAY_BASE + 0x2084)
> >  #define VLV_IER		(VLV_DISPLAY_BASE + 0x20a0)
> >  #define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
> > @@ -4988,6 +5008,8 @@ enum punit_power_well {
> >  
> >  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
> >  
> > +#define  VLV_PMWGICZ				0x1300a4
> > +
> >  #define  FORCEWAKE				0xA18C
> >  #define  FORCEWAKE_VLV				0x1300b0
> >  #define  FORCEWAKE_ACK_VLV			0x1300b4
> > @@ -5011,6 +5033,7 @@ enum punit_power_well {
> >  #define  FORCEWAKE_MT_ACK			0x130040
> >  #define  ECOBUS					0xa180
> >  #define    FORCEWAKE_MT_ENABLE			(1<<5)
> > +#define  VLV_SPAREG2H				0xA194
> >  
> >  #define  GTFIFODBG				0x120000
> >  #define    GT_FIFO_SBDROPERR			(1<<6)
> > @@ -5040,12 +5063,24 @@ enum punit_power_well {
> >  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
> >  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
> >  
> > +#define GEN7_UCGCTL3				0x9408
> > +
> >  #define GEN7_UCGCTL4				0x940c
> >  #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)
> 
> SNB already has UCGCTL3 and 4. So even the old name is a bit wrong.
> 
> >  
> > +#define GEN7_RCGCTL1				0x9410
> > +#define GEN7_RCGCTL2				0x9414
> > +#define GEN7_RSTCTL				0x9420
> 
> These too already exist on gen6.
> 
> Same for GEN7_MISCCPCTL which should probably also be moved here and
> renamed.

I'd do this renaming in a follow-up patch.

> 
> > +
> >  #define GEN8_UCGCTL6				0x9430
> >  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE	(1<<14)
> >  
> > +#define GEN7_GFXPAUSE				0xA000
> > +#define GEN7_RPDEUHWTC				0xA080
> > +#define GEN7_RPDEUC				0xA084
> 
> These three are already listed in my snb pm guide, so gen6. Also
> should be inserted into the correct spot numerically.
> 
> > +
> > +#define VLV_PWRDWNUPCTL				0xA294
> > +
> >  #define GEN6_RPNSWREQ				0xA008
> >  #define   GEN6_TURBO_DISABLE			(1<<31)
> >  #define   GEN6_FREQUENCY(x)			((x)<<25)
> > @@ -5098,6 +5133,7 @@ enum punit_power_well {
> >  #define GEN6_RP_UP_EI				0xA068
> >  #define GEN6_RP_DOWN_EI				0xA06C
> >  #define GEN6_RP_IDLE_HYSTERSIS			0xA070
> > +#define GEN7_RPDEUCSW				0xA088
> 
> This one isn't listed in the snb pm guide, but I get the impression
> it should also say gen6 here.

Yep, I found it in an old (pre-reorg) SNB Graphics Voltage doc. Btw in
general, in most of the cases I missed the correct prefix because the
relevant registers are not tagged for GEN6 in the latest bspec. I fixed
the ones you commented on in this patch and will check the old docs too
in the future .. 

> >  #define GEN6_RC_STATE				0xA094
> >  #define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
> >  #define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
> > @@ -5105,9 +5141,11 @@ enum punit_power_well {
> >  #define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
> >  #define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
> >  #define GEN6_RC_SLEEP				0xA0B0
> > +#define VLV_RCUBMABDTMR				0xA0B0
> 
> Also seems like it should be gen6.

This is a bit odd, since I haven't found any register named RC_SLEEP.
RCUBMABDTMR is the correct name for GEN6+. So I'll change the above
prefix now to GEN6 and in a follow-up patch rename RC_SLEEP to
RCUBMABDTMR.

Also for BDW+ this register is called RC_WAKE_HYSTERESIS. Since it has
the same bit field definitions as RCUBMABDTMR, I guess it's ok to just
use RCUBMABDTMR for BDW+ too.

--Imre

> 
> All the rest look fine.
> 
> >  #define GEN6_RC1e_THRESHOLD			0xA0B4
> >  #define GEN6_RC6_THRESHOLD			0xA0B8
> >  #define GEN6_RC6p_THRESHOLD			0xA0BC
> > +#define VLV_RCEDATA				0xA0BC
> >  #define GEN6_RC6pp_THRESHOLD			0xA0C0
> >  #define GEN6_PMINTRMSK				0xA168
> >  
> > @@ -5126,6 +5164,9 @@ enum punit_power_well {
> >  						 GEN6_PM_RP_DOWN_THRESHOLD | \
> >  						 GEN6_PM_RP_DOWN_TIMEOUT)
> >  
> > +#define GEN7_GT_SCRATCH_BASE			0x4F100
> > +#define GEN7_GT_SCRATCH_REG_NUM			8
> > +
> >  #define VLV_GTLC_SURVIVABILITY_REG              0x130098
> >  #define VLV_GFX_CLK_STATUS_BIT			(1<<3)
> >  #define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


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

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

* [PATCH v3 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
  2014-04-24 21:17   ` Rodrigo Vivi
  2014-04-30 14:32   ` Ville Syrjälä
@ 2014-05-05 12:13   ` Imre Deak
  2014-05-05 12:21     ` Ville Syrjälä
  2 siblings, 1 reply; 85+ messages in thread
From: Imre Deak @ 2014-05-05 12:13 UTC (permalink / raw)
  To: intel-gfx

Needed by the VLV S0ix context save/restore helpers.

v2:
- unchanged
v3:
- use proper GEN register prefixes (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f183746..4762391 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -92,6 +92,9 @@
 #define   GEN6_MBC_SNPCR_LOW	(2<<21)
 #define   GEN6_MBC_SNPCR_MIN	(3<<21) /* only 1/16th of the cache is shared */
 
+#define VLV_G3DCTL		0x9024
+#define VLV_GSCKGCTL		0x9028
+
 #define GEN6_MBCTL		0x0907c
 #define   GEN6_MBCTL_ENABLE_BOOT_FETCH	(1 << 4)
 #define   GEN6_MBCTL_CTX_FETCH_NEEDED	(1 << 3)
@@ -785,9 +788,20 @@ enum punit_power_well {
 #define RING_MAX_IDLE(base)	((base)+0x54)
 #define RING_HWS_PGA(base)	((base)+0x80)
 #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
-#define ARB_MODE		0x04030
+
+#define GEN7_WR_WATERMARK	0x4028
+#define GEN7_GFX_PRIO_CTRL	0x402C
+#define ARB_MODE		0x4030
 #define   ARB_MODE_SWIZZLE_SNB	(1<<4)
 #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
+#define GEN7_GFX_PEND_TLB0	0x4034
+#define GEN7_GFX_PEND_TLB1	0x4038
+/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
+#define GEN7_LRA_LIMITS_BASE	0x403C
+#define GEN7_LRA_LIMITS_REG_NUM	13
+#define GEN7_MEDIA_MAX_REQ_COUNT	0x4070
+#define GEN7_GFX_MAX_REQ_COUNT		0x4074
+
 #define GAMTARBMODE		0x04a08
 #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
 #define   ARB_MODE_SWIZZLE_BDW	(1<<1)
@@ -822,6 +836,9 @@ enum punit_power_well {
 #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
 #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
 #define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
+
+#define GEN7_TLB_RD_ADDR	0x4700
+
 #if 0
 #define PRB0_TAIL	0x02030
 #define PRB0_HEAD	0x02034
@@ -948,6 +965,8 @@ enum punit_power_well {
 
 #define VLV_DISPLAY_BASE 0x180000
 
+#define VLV_GU_CTL0	(VLV_DISPLAY_BASE + 0x2030)
+#define VLV_GU_CTL1	(VLV_DISPLAY_BASE + 0x2034)
 #define SCPD0		0x0209c /* 915+ only */
 #define IER		0x020a0
 #define IIR		0x020a4
@@ -955,6 +974,7 @@ enum punit_power_well {
 #define ISR		0x020ac
 #define VLV_GUNIT_CLOCK_GATE	(VLV_DISPLAY_BASE + 0x2060)
 #define   GCFG_DIS		(1<<8)
+#define VLV_GUNIT_CLOCK_GATE2	(VLV_DISPLAY_BASE + 0x2064)
 #define VLV_IIR_RW	(VLV_DISPLAY_BASE + 0x2084)
 #define VLV_IER		(VLV_DISPLAY_BASE + 0x20a0)
 #define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
@@ -4988,6 +5008,8 @@ enum punit_power_well {
 
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
 
+#define  VLV_PMWGICZ				0x1300a4
+
 #define  FORCEWAKE				0xA18C
 #define  FORCEWAKE_VLV				0x1300b0
 #define  FORCEWAKE_ACK_VLV			0x1300b4
@@ -5011,6 +5033,7 @@ enum punit_power_well {
 #define  FORCEWAKE_MT_ACK			0x130040
 #define  ECOBUS					0xa180
 #define    FORCEWAKE_MT_ENABLE			(1<<5)
+#define  VLV_SPAREG2H				0xA194
 
 #define  GTFIFODBG				0x120000
 #define    GT_FIFO_SBDROPERR			(1<<6)
@@ -5040,12 +5063,19 @@ enum punit_power_well {
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
 # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
 
+#define GEN6_UCGCTL3				0x9408
+
 #define GEN7_UCGCTL4				0x940c
 #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)
 
+#define GEN6_RCGCTL1				0x9410
+#define GEN6_RCGCTL2				0x9414
+#define GEN6_RSTCTL				0x9420
+
 #define GEN8_UCGCTL6				0x9430
 #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE	(1<<14)
 
+#define GEN6_GFXPAUSE				0xA000
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
 #define   GEN6_FREQUENCY(x)			((x)<<25)
@@ -5098,6 +5128,9 @@ enum punit_power_well {
 #define GEN6_RP_UP_EI				0xA068
 #define GEN6_RP_DOWN_EI				0xA06C
 #define GEN6_RP_IDLE_HYSTERSIS			0xA070
+#define GEN6_RPDEUHWTC				0xA080
+#define GEN6_RPDEUC				0xA084
+#define GEN6_RPDEUCSW				0xA088
 #define GEN6_RC_STATE				0xA094
 #define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
 #define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
@@ -5105,11 +5138,14 @@ enum punit_power_well {
 #define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
 #define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
 #define GEN6_RC_SLEEP				0xA0B0
+#define GEN6_RCUBMABDTMR			0xA0B0
 #define GEN6_RC1e_THRESHOLD			0xA0B4
 #define GEN6_RC6_THRESHOLD			0xA0B8
 #define GEN6_RC6p_THRESHOLD			0xA0BC
+#define VLV_RCEDATA				0xA0BC
 #define GEN6_RC6pp_THRESHOLD			0xA0C0
 #define GEN6_PMINTRMSK				0xA168
+#define VLV_PWRDWNUPCTL				0xA294
 
 #define GEN6_PMISR				0x44020
 #define GEN6_PMIMR				0x44024 /* rps_lock */
@@ -5126,6 +5162,9 @@ enum punit_power_well {
 						 GEN6_PM_RP_DOWN_THRESHOLD | \
 						 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define GEN7_GT_SCRATCH_BASE			0x4F100
+#define GEN7_GT_SCRATCH_REG_NUM			8
+
 #define VLV_GTLC_SURVIVABILITY_REG              0x130098
 #define VLV_GFX_CLK_STATUS_BIT			(1<<3)
 #define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
-- 
1.8.4

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

* [PATCH v4 25/25] drm/i915: vlv: add runtime PM support
  2014-04-22 17:28   ` [PATCH v3 " Imre Deak
  2014-04-22 22:09     ` [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
  2014-04-30 17:35     ` [PATCH v3 25/25] drm/i915: vlv: add runtime PM support Ville Syrjälä
@ 2014-05-05 12:19     ` Imre Deak
  2 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-05-05 12:19 UTC (permalink / raw)
  To: intel-gfx

Add runtime PM support for VLV, but leave it disabled. The next patch
enables it.

The suspend/resume sequence used is based on [1] and [2]. In practice we
depend on the GT RC6 mechanism to save the HW context depending on the
render and media power wells. By the time we run the runtime suspend
callback the display side is also off and the HW context for that is
managed by the display power domain framework.

Besides the above there are Gunit registers that depend on a system-wide
power well. This power well goes off once the device enters any of the
S0i[R123] states. To handle this scenario, save/restore these Gunit
registers. Note that this is not the complete register set dictated by
[2], to remove some overhead, registers that are known not to be used are
ignored. Also some registers are fully setup by initialization functions
called during resume, these are not saved either. The list of registers
can be further reduced, see the TODO note in the code.

[1] VLV_gfx_clocking_PM_reset_y12w21d3 / "Driver D3 entry/exit"
[2] VLV2_S0IXRegs

v2:
- unchanged
v3:
- fix s/GEN6_PMIIR/GEN6_PMIMR/ typo when saving/restoring registers
  (Ville)
v4:
- rebased on the previous patch fixing GEN register prefixes

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
[ rebased (according to v4) ]
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 327 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  62 ++++++++
 2 files changed, 389 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3144a12..cc84b9a 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -912,6 +912,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
+/*
+ * Save all Gunit registers that may be lost after a D3 and a subsequent
+ * S0i[R123] transition. The list of registers needing a save/restore is
+ * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
+ * registers in the following way:
+ * - Driver: saved/restored by the driver
+ * - Punit : saved/restored by the Punit firmware
+ * - No, w/o marking: no need to save/restore, since the register is R/O or
+ *                    used internally by the HW in a way that doesn't depend
+ *                    keeping the content across a suspend/resume.
+ * - Debug : used for debugging
+ *
+ * We save/restore all registers marked with 'Driver', with the following
+ * exceptions:
+ * - Registers out of use, including also registers marked with 'Debug'.
+ *   These have no effect on the driver's operation, so we don't save/restore
+ *   them to reduce the overhead.
+ * - Registers that are fully setup by an initialization function called from
+ *   the resume path. For example many clock gating and RPS/RC6 registers.
+ * - Registers that provide the right functionality with their reset defaults.
+ *
+ * TODO: Except for registers that based on the above 3 criteria can be safely
+ * ignored, we save/restore all others, practically treating the HW context as
+ * a black-box for the driver. Further investigation is needed to reduce the
+ * saved/restored registers even further, by following the same 3 criteria.
+ */
+static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	s->wr_watermark		= I915_READ(GEN7_WR_WATERMARK);
+	s->gfx_prio_ctrl	= I915_READ(GEN7_GFX_PRIO_CTRL);
+	s->arb_mode		= I915_READ(ARB_MODE);
+	s->gfx_pend_tlb0	= I915_READ(GEN7_GFX_PEND_TLB0);
+	s->gfx_pend_tlb1	= I915_READ(GEN7_GFX_PEND_TLB1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
+
+	s->media_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+	s->gfx_max_req_count	= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+
+	s->render_hwsp		= I915_READ(RENDER_HWS_PGA_GEN7);
+	s->ecochk		= I915_READ(GAM_ECOCHK);
+	s->bsd_hwsp		= I915_READ(BSD_HWS_PGA_GEN7);
+	s->blt_hwsp		= I915_READ(BLT_HWS_PGA_GEN7);
+
+	s->tlb_rd_addr		= I915_READ(GEN7_TLB_RD_ADDR);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	s->g3dctl		= I915_READ(VLV_G3DCTL);
+	s->gsckgctl		= I915_READ(VLV_GSCKGCTL);
+	s->mbctl		= I915_READ(GEN6_MBCTL);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	s->ucgctl1		= I915_READ(GEN6_UCGCTL1);
+	s->ucgctl3		= I915_READ(GEN6_UCGCTL3);
+	s->rcgctl1		= I915_READ(GEN6_RCGCTL1);
+	s->rcgctl2		= I915_READ(GEN6_RCGCTL2);
+	s->rstctl		= I915_READ(GEN6_RSTCTL);
+	s->misccpctl		= I915_READ(GEN7_MISCCPCTL);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	s->gfxpause		= I915_READ(GEN6_GFXPAUSE);
+	s->rpdeuhwtc		= I915_READ(GEN6_RPDEUHWTC);
+	s->rpdeuc		= I915_READ(GEN6_RPDEUC);
+	s->ecobus		= I915_READ(ECOBUS);
+	s->pwrdwnupctl		= I915_READ(VLV_PWRDWNUPCTL);
+	s->rp_down_timeout	= I915_READ(GEN6_RP_DOWN_TIMEOUT);
+	s->rp_deucsw		= I915_READ(GEN6_RPDEUCSW);
+	s->rcubmabdtmr		= I915_READ(GEN6_RCUBMABDTMR);
+	s->rcedata		= I915_READ(VLV_RCEDATA);
+	s->spare2gh		= I915_READ(VLV_SPAREG2H);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	s->gt_imr		= I915_READ(GTIMR);
+	s->gt_ier		= I915_READ(GTIER);
+	s->pm_imr		= I915_READ(GEN6_PMIMR);
+	s->pm_ier		= I915_READ(GEN6_PMIER);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	s->tilectl		= I915_READ(TILECTL);
+	s->gt_fifoctl		= I915_READ(GTFIFOCTL);
+	s->gtlc_wake_ctrl	= I915_READ(VLV_GTLC_WAKE_CTRL);
+	s->gtlc_survive		= I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	s->pmwgicz		= I915_READ(VLV_PMWGICZ);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	s->gu_ctl0		= I915_READ(VLV_GU_CTL0);
+	s->gu_ctl1		= I915_READ(VLV_GU_CTL1);
+	s->clock_gate_dis2	= I915_READ(VLV_GUNIT_CLOCK_GATE2);
+
+	/*
+	 * Not saving any of:
+	 * DFT,		0x9800-0x9EC0
+	 * SARB,	0xB000-0xB1FC
+	 * GAC,		0x5208-0x524C, 0x14000-0x14C000
+	 * PCI CFG
+	 */
+}
+
+static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+	struct vlv_s0ix_state *s = &dev_priv->vlv_s0ix_state;
+	u32 val;
+	int i;
+
+	/* GAM 0x4000-0x4770 */
+	I915_WRITE(GEN7_WR_WATERMARK,	s->wr_watermark);
+	I915_WRITE(GEN7_GFX_PRIO_CTRL,	s->gfx_prio_ctrl);
+	I915_WRITE(ARB_MODE,		s->arb_mode | (0xffff << 16));
+	I915_WRITE(GEN7_GFX_PEND_TLB0,	s->gfx_pend_tlb0);
+	I915_WRITE(GEN7_GFX_PEND_TLB1,	s->gfx_pend_tlb1);
+
+	for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++)
+		I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
+
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
+	I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
+
+	I915_WRITE(RENDER_HWS_PGA_GEN7,	s->render_hwsp);
+	I915_WRITE(GAM_ECOCHK,		s->ecochk);
+	I915_WRITE(BSD_HWS_PGA_GEN7,	s->bsd_hwsp);
+	I915_WRITE(BLT_HWS_PGA_GEN7,	s->blt_hwsp);
+
+	I915_WRITE(GEN7_TLB_RD_ADDR,	s->tlb_rd_addr);
+
+	/* MBC 0x9024-0x91D0, 0x8500 */
+	I915_WRITE(VLV_G3DCTL,		s->g3dctl);
+	I915_WRITE(VLV_GSCKGCTL,	s->gsckgctl);
+	I915_WRITE(GEN6_MBCTL,		s->mbctl);
+
+	/* GCP 0x9400-0x9424, 0x8100-0x810C */
+	I915_WRITE(GEN6_UCGCTL1,	s->ucgctl1);
+	I915_WRITE(GEN6_UCGCTL3,	s->ucgctl3);
+	I915_WRITE(GEN6_RCGCTL1,	s->rcgctl1);
+	I915_WRITE(GEN6_RCGCTL2,	s->rcgctl2);
+	I915_WRITE(GEN6_RSTCTL,		s->rstctl);
+	I915_WRITE(GEN7_MISCCPCTL,	s->misccpctl);
+
+	/* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+	I915_WRITE(GEN6_GFXPAUSE,	s->gfxpause);
+	I915_WRITE(GEN6_RPDEUHWTC,	s->rpdeuhwtc);
+	I915_WRITE(GEN6_RPDEUC,		s->rpdeuc);
+	I915_WRITE(ECOBUS,		s->ecobus);
+	I915_WRITE(VLV_PWRDWNUPCTL,	s->pwrdwnupctl);
+	I915_WRITE(GEN6_RP_DOWN_TIMEOUT,s->rp_down_timeout);
+	I915_WRITE(GEN6_RPDEUCSW,	s->rp_deucsw);
+	I915_WRITE(GEN6_RCUBMABDTMR,	s->rcubmabdtmr);
+	I915_WRITE(VLV_RCEDATA,		s->rcedata);
+	I915_WRITE(VLV_SPAREG2H,	s->spare2gh);
+
+	/* Display CZ domain, 0x4400C-0x4402C, 0x4F000-0x4F11F */
+	I915_WRITE(GTIMR,		s->gt_imr);
+	I915_WRITE(GTIER,		s->gt_ier);
+	I915_WRITE(GEN6_PMIMR,		s->pm_imr);
+	I915_WRITE(GEN6_PMIER,		s->pm_ier);
+
+	for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++)
+		I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]);
+
+	/* GT SA CZ domain, 0x100000-0x138124 */
+	I915_WRITE(TILECTL,			s->tilectl);
+	I915_WRITE(GTFIFOCTL,			s->gt_fifoctl);
+	/*
+	 * Preserve the GT allow wake and GFX force clock bit, they are not
+	 * be restored, as they are used to control the s0ix suspend/resume
+	 * sequence by the caller.
+	 */
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= VLV_GTLC_ALLOWWAKEREQ;
+	val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+
+	val = I915_READ(VLV_GTLC_SURVIVABILITY_REG);
+	val &= VLV_GFX_CLK_FORCE_ON_BIT;
+	val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
+	I915_WRITE(VLV_GTLC_SURVIVABILITY_REG, val);
+
+	I915_WRITE(VLV_PMWGICZ,			s->pmwgicz);
+
+	/* Gunit-Display CZ domain, 0x182028-0x1821CF */
+	I915_WRITE(VLV_GU_CTL0,			s->gu_ctl0);
+	I915_WRITE(VLV_GU_CTL1,			s->gu_ctl1);
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE2,	s->clock_gate_dis2);
+}
+
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 {
 	u32 val;
@@ -949,6 +1141,137 @@ int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
 #undef COND
 }
 
+static int vlv_allow_gt_wake(struct drm_i915_private *dev_priv, bool allow)
+{
+	u32 val;
+	int err = 0;
+
+	val = I915_READ(VLV_GTLC_WAKE_CTRL);
+	val &= ~VLV_GTLC_ALLOWWAKEREQ;
+	if (allow)
+		val |= VLV_GTLC_ALLOWWAKEREQ;
+	I915_WRITE(VLV_GTLC_WAKE_CTRL, val);
+	POSTING_READ(VLV_GTLC_WAKE_CTRL);
+
+#define COND (!!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEACK) == \
+	      allow)
+	err = wait_for(COND, 1);
+	if (err)
+		DRM_ERROR("timeout disabling GT waking\n");
+	return err;
+#undef COND
+}
+
+static int vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
+				 bool wait_for_on)
+{
+	u32 mask;
+	u32 val;
+	int err;
+
+	mask = VLV_GTLC_PW_MEDIA_STATUS_MASK | VLV_GTLC_PW_RENDER_STATUS_MASK;
+	val = wait_for_on ? mask : 0;
+#define COND ((I915_READ(VLV_GTLC_PW_STATUS) & mask) == val)
+	if (COND)
+		return 0;
+
+	DRM_DEBUG_KMS("waiting for GT wells to go %s (%08x)\n",
+			wait_for_on ? "on" : "off",
+			I915_READ(VLV_GTLC_PW_STATUS));
+
+	/*
+	 * RC6 transitioning can be delayed up to 2 msec (see
+	 * valleyview_enable_rps), use 3 msec for safety.
+	 */
+	err = wait_for(COND, 3);
+	if (err)
+		DRM_ERROR("timeout waiting for GT wells to go %s\n",
+			  wait_for_on ? "on" : "off");
+
+	return err;
+#undef COND
+}
+
+static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
+{
+	if (!(I915_READ(VLV_GTLC_PW_STATUS) & VLV_GTLC_ALLOWWAKEERR))
+		return;
+
+	DRM_ERROR("GT register access while GT waking disabled\n");
+	I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
+}
+
+static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	u32 mask;
+	int err;
+
+	/*
+	 * Bspec defines the following GT well on flags as debug only, so
+	 * don't treat them as hard failures.
+	 */
+	(void)vlv_wait_for_gt_wells(dev_priv, false);
+
+	mask = VLV_GTLC_RENDER_CTX_EXISTS | VLV_GTLC_MEDIA_CTX_EXISTS;
+	WARN_ON((I915_READ(VLV_GTLC_WAKE_CTRL) & mask) != mask);
+
+	vlv_check_no_gt_access(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, true);
+	if (err)
+		goto err1;
+
+	err = vlv_allow_gt_wake(dev_priv, false);
+	if (err)
+		goto err2;
+	vlv_save_gunit_s0ix_state(dev_priv);
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (err)
+		goto err2;
+
+	return 0;
+
+err2:
+	/* For safety always re-enable waking and disable gfx clock forcing */
+	vlv_allow_gt_wake(dev_priv, true);
+err1:
+	vlv_force_gfx_clock(dev_priv, false);
+
+	return err;
+}
+
+static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int err;
+	int ret;
+
+	/*
+	 * If any of the steps fail just try to continue, that's the best we
+	 * can do at this point. Return the first error code (which will also
+	 * leave RPM permanently disabled).
+	 */
+	ret = vlv_force_gfx_clock(dev_priv, true);
+
+	vlv_restore_gunit_s0ix_state(dev_priv);
+
+	err = vlv_allow_gt_wake(dev_priv, true);
+	if (!ret)
+		ret = err;
+
+	err = vlv_force_gfx_clock(dev_priv, false);
+	if (!ret)
+		ret = err;
+
+	vlv_check_no_gt_access(dev_priv);
+
+	intel_init_clock_gating(dev);
+	i915_gem_restore_fences(dev);
+
+	return ret;
+}
+
 static int intel_runtime_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -976,6 +1299,8 @@ static int intel_runtime_suspend(struct device *device)
 		ret = 0;
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_suspend(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_suspend(dev_priv);
 	} else {
 		ret = -ENODEV;
 		WARN_ON(1);
@@ -1024,6 +1349,8 @@ static int intel_runtime_resume(struct device *device)
 		ret = snb_runtime_resume(dev_priv);
 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		ret = hsw_runtime_resume(dev_priv);
+	} else if (IS_VALLEYVIEW(dev)) {
+		ret = vlv_runtime_resume(dev_priv);
 	} else {
 		WARN_ON(1);
 		ret = -ENODEV;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3cac434..77cb7fc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -819,6 +819,67 @@ struct i915_suspend_saved_registers {
 	u32 savePCH_PORT_HOTPLUG;
 };
 
+struct vlv_s0ix_state {
+	/* GAM */
+	u32 wr_watermark;
+	u32 gfx_prio_ctrl;
+	u32 arb_mode;
+	u32 gfx_pend_tlb0;
+	u32 gfx_pend_tlb1;
+	u32 lra_limits[GEN7_LRA_LIMITS_REG_NUM];
+	u32 media_max_req_count;
+	u32 gfx_max_req_count;
+	u32 render_hwsp;
+	u32 ecochk;
+	u32 bsd_hwsp;
+	u32 blt_hwsp;
+	u32 tlb_rd_addr;
+
+	/* MBC */
+	u32 g3dctl;
+	u32 gsckgctl;
+	u32 mbctl;
+
+	/* GCP */
+	u32 ucgctl1;
+	u32 ucgctl3;
+	u32 rcgctl1;
+	u32 rcgctl2;
+	u32 rstctl;
+	u32 misccpctl;
+
+	/* GPM */
+	u32 gfxpause;
+	u32 rpdeuhwtc;
+	u32 rpdeuc;
+	u32 ecobus;
+	u32 pwrdwnupctl;
+	u32 rp_down_timeout;
+	u32 rp_deucsw;
+	u32 rcubmabdtmr;
+	u32 rcedata;
+	u32 spare2gh;
+
+	/* Display 1 CZ domain */
+	u32 gt_imr;
+	u32 gt_ier;
+	u32 pm_imr;
+	u32 pm_ier;
+	u32 gt_scratch[GEN7_GT_SCRATCH_REG_NUM];
+
+	/* GT SA CZ domain */
+	u32 tilectl;
+	u32 gt_fifoctl;
+	u32 gtlc_wake_ctrl;
+	u32 gtlc_survive;
+	u32 pmwgicz;
+
+	/* Display 2 CZ domain */
+	u32 gu_ctl0;
+	u32 gu_ctl1;
+	u32 clock_gate_dis2;
+};
+
 struct intel_gen6_power_mgmt {
 	/* work and pm_iir are protected by dev_priv->irq_lock */
 	struct work_struct work;
@@ -1447,6 +1508,7 @@ struct drm_i915_private {
 
 	u32 suspend_count;
 	struct i915_suspend_saved_registers regfile;
+	struct vlv_s0ix_state vlv_s0ix_state;
 
 	struct {
 		/*
-- 
1.8.4

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

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

* Re: [PATCH v3 23/25] drm/i915: add various missing GTI/Gunit register definitions
  2014-05-05 12:13   ` [PATCH v3 " Imre Deak
@ 2014-05-05 12:21     ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2014-05-05 12:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, May 05, 2014 at 03:13:55PM +0300, Imre Deak wrote:
> Needed by the VLV S0ix context save/restore helpers.
> 
> v2:
> - unchanged
> v3:
> - use proper GEN register prefixes (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h | 41 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f183746..4762391 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -92,6 +92,9 @@
>  #define   GEN6_MBC_SNPCR_LOW	(2<<21)
>  #define   GEN6_MBC_SNPCR_MIN	(3<<21) /* only 1/16th of the cache is shared */
>  
> +#define VLV_G3DCTL		0x9024
> +#define VLV_GSCKGCTL		0x9028
> +
>  #define GEN6_MBCTL		0x0907c
>  #define   GEN6_MBCTL_ENABLE_BOOT_FETCH	(1 << 4)
>  #define   GEN6_MBCTL_CTX_FETCH_NEEDED	(1 << 3)
> @@ -785,9 +788,20 @@ enum punit_power_well {
>  #define RING_MAX_IDLE(base)	((base)+0x54)
>  #define RING_HWS_PGA(base)	((base)+0x80)
>  #define RING_HWS_PGA_GEN6(base)	((base)+0x2080)
> -#define ARB_MODE		0x04030
> +
> +#define GEN7_WR_WATERMARK	0x4028
> +#define GEN7_GFX_PRIO_CTRL	0x402C
> +#define ARB_MODE		0x4030
>  #define   ARB_MODE_SWIZZLE_SNB	(1<<4)
>  #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
> +#define GEN7_GFX_PEND_TLB0	0x4034
> +#define GEN7_GFX_PEND_TLB1	0x4038
> +/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
> +#define GEN7_LRA_LIMITS_BASE	0x403C
> +#define GEN7_LRA_LIMITS_REG_NUM	13
> +#define GEN7_MEDIA_MAX_REQ_COUNT	0x4070
> +#define GEN7_GFX_MAX_REQ_COUNT		0x4074
> +
>  #define GAMTARBMODE		0x04a08
>  #define   ARB_MODE_BWGTLB_DISABLE (1<<9)
>  #define   ARB_MODE_SWIZZLE_BDW	(1<<1)
> @@ -822,6 +836,9 @@ enum punit_power_well {
>  #define   RING_WAIT_I8XX	(1<<0) /* gen2, PRBx_HEAD */
>  #define   RING_WAIT		(1<<11) /* gen3+, PRBx_CTL */
>  #define   RING_WAIT_SEMAPHORE	(1<<10) /* gen6+ */
> +
> +#define GEN7_TLB_RD_ADDR	0x4700
> +
>  #if 0
>  #define PRB0_TAIL	0x02030
>  #define PRB0_HEAD	0x02034
> @@ -948,6 +965,8 @@ enum punit_power_well {
>  
>  #define VLV_DISPLAY_BASE 0x180000
>  
> +#define VLV_GU_CTL0	(VLV_DISPLAY_BASE + 0x2030)
> +#define VLV_GU_CTL1	(VLV_DISPLAY_BASE + 0x2034)
>  #define SCPD0		0x0209c /* 915+ only */
>  #define IER		0x020a0
>  #define IIR		0x020a4
> @@ -955,6 +974,7 @@ enum punit_power_well {
>  #define ISR		0x020ac
>  #define VLV_GUNIT_CLOCK_GATE	(VLV_DISPLAY_BASE + 0x2060)
>  #define   GCFG_DIS		(1<<8)
> +#define VLV_GUNIT_CLOCK_GATE2	(VLV_DISPLAY_BASE + 0x2064)
>  #define VLV_IIR_RW	(VLV_DISPLAY_BASE + 0x2084)
>  #define VLV_IER		(VLV_DISPLAY_BASE + 0x20a0)
>  #define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
> @@ -4988,6 +5008,8 @@ enum punit_power_well {
>  
>  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)
>  
> +#define  VLV_PMWGICZ				0x1300a4
> +
>  #define  FORCEWAKE				0xA18C
>  #define  FORCEWAKE_VLV				0x1300b0
>  #define  FORCEWAKE_ACK_VLV			0x1300b4
> @@ -5011,6 +5033,7 @@ enum punit_power_well {
>  #define  FORCEWAKE_MT_ACK			0x130040
>  #define  ECOBUS					0xa180
>  #define    FORCEWAKE_MT_ENABLE			(1<<5)
> +#define  VLV_SPAREG2H				0xA194
>  
>  #define  GTFIFODBG				0x120000
>  #define    GT_FIFO_SBDROPERR			(1<<6)
> @@ -5040,12 +5063,19 @@ enum punit_power_well {
>  # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12)
>  # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11)
>  
> +#define GEN6_UCGCTL3				0x9408
> +
>  #define GEN7_UCGCTL4				0x940c
>  #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)
>  
> +#define GEN6_RCGCTL1				0x9410
> +#define GEN6_RCGCTL2				0x9414
> +#define GEN6_RSTCTL				0x9420
> +
>  #define GEN8_UCGCTL6				0x9430
>  #define   GEN8_SDEUNIT_CLOCK_GATE_DISABLE	(1<<14)
>  
> +#define GEN6_GFXPAUSE				0xA000
>  #define GEN6_RPNSWREQ				0xA008
>  #define   GEN6_TURBO_DISABLE			(1<<31)
>  #define   GEN6_FREQUENCY(x)			((x)<<25)
> @@ -5098,6 +5128,9 @@ enum punit_power_well {
>  #define GEN6_RP_UP_EI				0xA068
>  #define GEN6_RP_DOWN_EI				0xA06C
>  #define GEN6_RP_IDLE_HYSTERSIS			0xA070
> +#define GEN6_RPDEUHWTC				0xA080
> +#define GEN6_RPDEUC				0xA084
> +#define GEN6_RPDEUCSW				0xA088
>  #define GEN6_RC_STATE				0xA094
>  #define GEN6_RC1_WAKE_RATE_LIMIT		0xA098
>  #define GEN6_RC6_WAKE_RATE_LIMIT		0xA09C
> @@ -5105,11 +5138,14 @@ enum punit_power_well {
>  #define GEN6_RC_EVALUATION_INTERVAL		0xA0A8
>  #define GEN6_RC_IDLE_HYSTERSIS			0xA0AC
>  #define GEN6_RC_SLEEP				0xA0B0
> +#define GEN6_RCUBMABDTMR			0xA0B0
>  #define GEN6_RC1e_THRESHOLD			0xA0B4
>  #define GEN6_RC6_THRESHOLD			0xA0B8
>  #define GEN6_RC6p_THRESHOLD			0xA0BC
> +#define VLV_RCEDATA				0xA0BC
>  #define GEN6_RC6pp_THRESHOLD			0xA0C0
>  #define GEN6_PMINTRMSK				0xA168
> +#define VLV_PWRDWNUPCTL				0xA294
>  
>  #define GEN6_PMISR				0x44020
>  #define GEN6_PMIMR				0x44024 /* rps_lock */
> @@ -5126,6 +5162,9 @@ enum punit_power_well {
>  						 GEN6_PM_RP_DOWN_THRESHOLD | \
>  						 GEN6_PM_RP_DOWN_TIMEOUT)
>  
> +#define GEN7_GT_SCRATCH_BASE			0x4F100
> +#define GEN7_GT_SCRATCH_REG_NUM			8
> +
>  #define VLV_GTLC_SURVIVABILITY_REG              0x130098
>  #define VLV_GFX_CLK_STATUS_BIT			(1<<3)
>  #define VLV_GFX_CLK_FORCE_ON_BIT		(1<<2)
> -- 
> 1.8.4

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-04-30 18:53       ` Imre Deak
@ 2014-05-05 12:44         ` Ville Syrjälä
  2014-05-05 13:18           ` Imre Deak
  0 siblings, 1 reply; 85+ messages in thread
From: Ville Syrjälä @ 2014-05-05 12:44 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Wed, Apr 30, 2014 at 09:53:08PM +0300, Imre Deak wrote:
> On Wed, 2014-04-30 at 21:05 +0300, Ville Syrjälä wrote:
> > On Tue, Apr 15, 2014 at 04:39:45PM +0300, Imre Deak wrote:
> > > Atm, none of the RPM callbacks can fail, but the next patch adding
> > > RPM support for VLV changes this, so prepare for it.
> > > 
> > > In case one of these callbacks return error RPM will get permanently
> > > disabled until the error is explicitly cleared. In the future we could
> > > add support for re-enabling it, for example after resetting the HW, but
> > > for now - hopefully - we can live with the simpler solution.
> > > 
> > > v2:
> > > - propagate the error from the resume callbacks too (Paulo)
> > > v3:
> > > - fix rebase fail typo around IS_GEN6() check in intel_runtime_suspend()
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
> > >  1 file changed, 42 insertions(+), 15 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > > index 845e1e1..aeb7dec 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.c
> > > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > > @@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
> > >  	return i915_drm_freeze(drm_dev);
> > >  }
> > >  
> > > -static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> > > +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> > >  {
> > >  	hsw_enable_pc8(dev_priv);
> > > +
> > > +	return 0;
> > >  }
> > >  
> > > -static void snb_runtime_resume(struct drm_i915_private *dev_priv)
> > > +static int snb_runtime_resume(struct drm_i915_private *dev_priv)
> > >  {
> > >  	struct drm_device *dev = dev_priv->dev;
> > >  
> > >  	intel_init_pch_refclk(dev);
> > > +
> > > +	return 0;
> > >  }
> > >  
> > > -static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> > > +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
> > >  {
> > >  	hsw_disable_pc8(dev_priv);
> > > +
> > > +	return 0;
> > >  }
> > >  
> > >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> > > @@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
> > >  	struct pci_dev *pdev = to_pci_dev(device);
> > >  	struct drm_device *dev = pci_get_drvdata(pdev);
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > +	int ret;
> > >  
> > >  	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
> > >  		return -ENODEV;
> > > @@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
> > >  	intel_runtime_pm_disable_interrupts(dev);
> > >  	cancel_work_sync(&dev_priv->rps.work);
> > >  
> > > -	if (IS_GEN6(dev))
> > > -		;
> > > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > > -		hsw_runtime_suspend(dev_priv);
> > > -	else
> > > +	if (IS_GEN6(dev)) {
> > > +		ret = 0;
> > > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > > +		ret = hsw_runtime_suspend(dev_priv);
> > > +	} else {
> > > +		ret = -ENODEV;
> > >  		WARN_ON(1);
> > > +	}
> > > +
> > > +	if (ret) {
> > > +		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
> > > +		intel_runtime_pm_restore_interrupts(dev);
> > > +
> > > +		return ret;
> > > +	}
> > >  
> > >  	i915_gem_release_all_mmaps(dev_priv);
> > 
> > Not strictly related to this patch, but shouldn't we nuke the mmaps before
> > calling the platform specific runtime suspend function?
> 
> We take an RPM ref on the fault path, so at least this couldn't race
> with user space either way. But if you meant that the platform hooks
> could save/restore some stale state because of this ordering, then I
> agree it'd be safer to move it before calling the platform hook. But I
> don't see what this state would be.

My main worry is that something may get turned off in the platform
specific code which is required by the hardware to service GTT
accesses. A concurrect GTT access may then happen after the platform
spefic code has turned off the hardware but before the mmaps have been
released and hence there's no fault when the access happens.

> 
> --Imre
> 
> > This patch itself looks ok to me:
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > >  
> > > @@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
> > >  	struct pci_dev *pdev = to_pci_dev(device);
> > >  	struct drm_device *dev = pci_get_drvdata(pdev);
> > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > +	int ret;
> > >  
> > >  	WARN_ON(!HAS_RUNTIME_PM(dev));
> > >  
> > > @@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
> > >  	intel_opregion_notify_adapter(dev, PCI_D0);
> > >  	dev_priv->pm.suspended = false;
> > >  
> > > -	if (IS_GEN6(dev))
> > > -		snb_runtime_resume(dev_priv);
> > > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > > -		hsw_runtime_resume(dev_priv);
> > > -	else
> > > +	if (IS_GEN6(dev)) {
> > > +		ret = snb_runtime_resume(dev_priv);
> > > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > > +		ret = hsw_runtime_resume(dev_priv);
> > > +	} else {
> > >  		WARN_ON(1);
> > > +		ret = -ENODEV;
> > > +	}
> > >  
> > > +	/*
> > > +	 * No point of rolling back things in case of an error, as the best
> > > +	 * we can do is to hope that things will still work (and disable RPM).
> > > +	 */
> > >  	i915_gem_init_swizzling(dev);
> > >  	gen6_update_ring_freq(dev);
> > >  	intel_reset_gt_powersave(dev);
> > >  
> > >  	intel_runtime_pm_restore_interrupts(dev);
> > >  
> > > -	DRM_DEBUG_KMS("Device resumed\n");
> > > -	return 0;
> > > +	if (ret)
> > > +		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
> > > +	else
> > > +		DRM_DEBUG_KMS("Device resumed\n");
> > > +
> > > +	return ret;
> > >  }
> > >  
> > >  static const struct dev_pm_ops i915_pm_ops = {
> > > -- 
> > > 1.8.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> 

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH v3 24/25] drm/i915: propagate the error code from runtime PM callbacks
  2014-05-05 12:44         ` Ville Syrjälä
@ 2014-05-05 13:18           ` Imre Deak
  0 siblings, 0 replies; 85+ messages in thread
From: Imre Deak @ 2014-05-05 13:18 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Mon, 2014-05-05 at 15:44 +0300, Ville Syrjälä wrote:
> On Wed, Apr 30, 2014 at 09:53:08PM +0300, Imre Deak wrote:
> > On Wed, 2014-04-30 at 21:05 +0300, Ville Syrjälä wrote:
> > > On Tue, Apr 15, 2014 at 04:39:45PM +0300, Imre Deak wrote:
> > > > Atm, none of the RPM callbacks can fail, but the next patch adding
> > > > RPM support for VLV changes this, so prepare for it.
> > > > 
> > > > In case one of these callbacks return error RPM will get permanently
> > > > disabled until the error is explicitly cleared. In the future we could
> > > > add support for re-enabling it, for example after resetting the HW, but
> > > > for now - hopefully - we can live with the simpler solution.
> > > > 
> > > > v2:
> > > > - propagate the error from the resume callbacks too (Paulo)
> > > > v3:
> > > > - fix rebase fail typo around IS_GEN6() check in intel_runtime_suspend()
> > > > 
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/i915_drv.c | 57 ++++++++++++++++++++++++++++++-----------
> > > >  1 file changed, 42 insertions(+), 15 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > > > index 845e1e1..aeb7dec 100644
> > > > --- a/drivers/gpu/drm/i915/i915_drv.c
> > > > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > > > @@ -888,21 +888,27 @@ static int i915_pm_poweroff(struct device *dev)
> > > >  	return i915_drm_freeze(drm_dev);
> > > >  }
> > > >  
> > > > -static void hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> > > > +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> > > >  {
> > > >  	hsw_enable_pc8(dev_priv);
> > > > +
> > > > +	return 0;
> > > >  }
> > > >  
> > > > -static void snb_runtime_resume(struct drm_i915_private *dev_priv)
> > > > +static int snb_runtime_resume(struct drm_i915_private *dev_priv)
> > > >  {
> > > >  	struct drm_device *dev = dev_priv->dev;
> > > >  
> > > >  	intel_init_pch_refclk(dev);
> > > > +
> > > > +	return 0;
> > > >  }
> > > >  
> > > > -static void hsw_runtime_resume(struct drm_i915_private *dev_priv)
> > > > +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
> > > >  {
> > > >  	hsw_disable_pc8(dev_priv);
> > > > +
> > > > +	return 0;
> > > >  }
> > > >  
> > > >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool force_on)
> > > > @@ -947,6 +953,7 @@ static int intel_runtime_suspend(struct device *device)
> > > >  	struct pci_dev *pdev = to_pci_dev(device);
> > > >  	struct drm_device *dev = pci_get_drvdata(pdev);
> > > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > > +	int ret;
> > > >  
> > > >  	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
> > > >  		return -ENODEV;
> > > > @@ -959,12 +966,21 @@ static int intel_runtime_suspend(struct device *device)
> > > >  	intel_runtime_pm_disable_interrupts(dev);
> > > >  	cancel_work_sync(&dev_priv->rps.work);
> > > >  
> > > > -	if (IS_GEN6(dev))
> > > > -		;
> > > > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > > > -		hsw_runtime_suspend(dev_priv);
> > > > -	else
> > > > +	if (IS_GEN6(dev)) {
> > > > +		ret = 0;
> > > > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > > > +		ret = hsw_runtime_suspend(dev_priv);
> > > > +	} else {
> > > > +		ret = -ENODEV;
> > > >  		WARN_ON(1);
> > > > +	}
> > > > +
> > > > +	if (ret) {
> > > > +		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
> > > > +		intel_runtime_pm_restore_interrupts(dev);
> > > > +
> > > > +		return ret;
> > > > +	}
> > > >  
> > > >  	i915_gem_release_all_mmaps(dev_priv);
> > > 
> > > Not strictly related to this patch, but shouldn't we nuke the mmaps before
> > > calling the platform specific runtime suspend function?
> > 
> > We take an RPM ref on the fault path, so at least this couldn't race
> > with user space either way. But if you meant that the platform hooks
> > could save/restore some stale state because of this ordering, then I
> > agree it'd be safer to move it before calling the platform hook. But I
> > don't see what this state would be.
> 
> My main worry is that something may get turned off in the platform
> specific code which is required by the hardware to service GTT
> accesses. A concurrect GTT access may then happen after the platform
> spefic code has turned off the hardware but before the mmaps have been
> released and hence there's no fault when the access happens.

Right, for existing maps this may be a problem. I'll follow-up with a
patch moving i915_gem_release_all_mmaps() earlier.
 
> > --Imre
> > 
> > > This patch itself looks ok to me:
> > > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > >  
> > > > @@ -989,6 +1005,7 @@ static int intel_runtime_resume(struct device *device)
> > > >  	struct pci_dev *pdev = to_pci_dev(device);
> > > >  	struct drm_device *dev = pci_get_drvdata(pdev);
> > > >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > > > +	int ret;
> > > >  
> > > >  	WARN_ON(!HAS_RUNTIME_PM(dev));
> > > >  
> > > > @@ -997,21 +1014,31 @@ static int intel_runtime_resume(struct device *device)
> > > >  	intel_opregion_notify_adapter(dev, PCI_D0);
> > > >  	dev_priv->pm.suspended = false;
> > > >  
> > > > -	if (IS_GEN6(dev))
> > > > -		snb_runtime_resume(dev_priv);
> > > > -	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> > > > -		hsw_runtime_resume(dev_priv);
> > > > -	else
> > > > +	if (IS_GEN6(dev)) {
> > > > +		ret = snb_runtime_resume(dev_priv);
> > > > +	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > > > +		ret = hsw_runtime_resume(dev_priv);
> > > > +	} else {
> > > >  		WARN_ON(1);
> > > > +		ret = -ENODEV;
> > > > +	}
> > > >  
> > > > +	/*
> > > > +	 * No point of rolling back things in case of an error, as the best
> > > > +	 * we can do is to hope that things will still work (and disable RPM).
> > > > +	 */
> > > >  	i915_gem_init_swizzling(dev);
> > > >  	gen6_update_ring_freq(dev);
> > > >  	intel_reset_gt_powersave(dev);
> > > >  
> > > >  	intel_runtime_pm_restore_interrupts(dev);
> > > >  
> > > > -	DRM_DEBUG_KMS("Device resumed\n");
> > > > -	return 0;
> > > > +	if (ret)
> > > > +		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
> > > > +	else
> > > > +		DRM_DEBUG_KMS("Device resumed\n");
> > > > +
> > > > +	return ret;
> > > >  }
> > > >  
> > > >  static const struct dev_pm_ops i915_pm_ops = {
> > > > -- 
> > > > 1.8.4
> > > > 
> > > > _______________________________________________
> > > > Intel-gfx mailing list
> > > > Intel-gfx@lists.freedesktop.org
> > > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > 
> > 
> 


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

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

* Re: [PATCH v2 26/25] drm/i915: vlv: enable runtime PM
  2014-04-14 17:41 ` [PATCH v2 26/25] drm/i915: vlv: enable runtime PM Imre Deak
@ 2014-05-06 19:39   ` Daniel Vetter
  0 siblings, 0 replies; 85+ messages in thread
From: Daniel Vetter @ 2014-05-06 19:39 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 14, 2014 at 08:41:30PM +0300, Imre Deak wrote:
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Ok, pulled it all in. Thanks for patches&review.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> [ I managed to leave out this last one, so sending it now on top of the
>   rest. ]
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 77cb7fc..3a98119 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1944,7 +1944,7 @@ struct drm_i915_cmd_table {
>  #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
>  #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
>  #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
> -				 IS_BROADWELL(dev))
> +				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev))
>  
>  #define INTEL_PCH_DEVICE_ID_MASK		0xff00
>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

end of thread, other threads:[~2014-05-06 19:39 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-14 17:24 [PATCH v2 00/25] vlv: add support for RPM Imre Deak
2014-04-14 17:24 ` [PATCH v2 01/25] drm/i915: vlv: clean up GTLC wake control/status register macros Imre Deak
2014-04-24 21:04   ` Rodrigo Vivi
2014-04-14 17:24 ` [PATCH v2 02/25] drm/i915: vlv: clear master interrupt flag when disabling interrupts Imre Deak
2014-04-14 17:24 ` [PATCH v2 03/25] drm/i915: vlv: add RC6 residency counters Imre Deak
2014-04-14 17:24 ` [PATCH v2 04/25] drm/i915: fix the RC6 status debug print Imre Deak
2014-04-14 17:24 ` [PATCH v2 05/25] drm/i915: remove the i915_dpio debugfs entry Imre Deak
2014-04-14 17:24 ` [PATCH v2 06/25] drm/i915: get a runtime PM ref for debugfs entries where needed Imre Deak
2014-04-14 17:24 ` [PATCH v2 07/25] drm/i915: move getting struct_mutex lower in the callstack during GPU reset Imre Deak
2014-04-14 17:24 ` [PATCH v2 08/25] drm/i915: get a runtime PM ref for the deferred GT powersave enabling Imre Deak
2014-04-25  7:59   ` Daniel Vetter
2014-04-25  8:14     ` Imre Deak
2014-04-25  9:09       ` Daniel Vetter
2014-04-25  8:01   ` Daniel Vetter
2014-04-14 17:24 ` [PATCH v2 09/25] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
2014-04-16 12:11   ` Ville Syrjälä
2014-04-18 12:47   ` [PATCH v3] " Imre Deak
2014-04-22 19:38     ` Daniel Vetter
2014-04-22 20:34       ` Imre Deak
2014-04-22 21:05         ` Daniel Vetter
2014-04-22 22:13     ` [PATCH v4] " Imre Deak
2014-04-23  7:07       ` Daniel Vetter
2014-04-23  7:52         ` Imre Deak
2014-04-25  8:00           ` Daniel Vetter
2014-04-14 17:24 ` [PATCH v2 10/25] drm/i915: gen2: move error capture of IER to its correct place Imre Deak
2014-04-16 12:22   ` Ville Syrjälä
2014-04-16 12:57     ` Imre Deak
2014-04-24 21:06       ` Rodrigo Vivi
2014-04-14 17:24 ` [PATCH v2 11/25] drm/i915: add missing error capturing of the PIPESTAT reg Imre Deak
2014-04-16 12:17   ` Ville Syrjälä
2014-04-18 11:44     ` Imre Deak
2014-04-18 12:55   ` [PATCH v3 " Imre Deak
2014-04-23  7:53     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 12/25] drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on Imre Deak
2014-04-14 17:24 ` [PATCH v2 13/25] drm/i915: fix unbalanced GT powersave enable / disable calls Imre Deak
2014-04-14 17:24 ` [PATCH v2 14/25] drm/i915: sanitize enable_rc6 option Imre Deak
2014-04-16 12:28   ` Ville Syrjälä
2014-04-16 12:37     ` Imre Deak
2014-04-18 13:01   ` [PATCH v3 " Imre Deak
2014-04-23  7:58     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 15/25] drm/i915: disable runtime PM if RC6 is disabled Imre Deak
2014-04-14 17:24 ` [PATCH v2 16/25] drm/i915: make runtime PM interrupt enable/disable platform independent Imre Deak
2014-04-14 17:24 ` [PATCH v2 17/25] drm/i915: factor out gen6_update_ring_freq Imre Deak
2014-04-16 17:31   ` Ville Syrjälä
2014-04-18 13:16   ` [PATCH v3 " Imre Deak
2014-04-23  7:59     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 18/25] drm/i915: make runtime PM swizzling/ring_freq init platform independent Imre Deak
2014-04-14 17:24 ` [PATCH v2 19/25] drm/i915: reinit GT power save during resume Imre Deak
2014-04-16 17:46   ` Ville Syrjälä
2014-04-18 10:51     ` Imre Deak
2014-04-22 17:21   ` [PATCH v3 " Imre Deak
2014-04-23  8:06     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 20/25] drm/i915: vlv: setup RPS min/max frequencies once during init time Imre Deak
2014-04-14 17:24 ` [PATCH v2 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock Imre Deak
2014-04-16 17:49   ` Ville Syrjälä
2014-04-18 13:35   ` [PATCH v3 21/25] drm/i915: vlv: factor out vlv_force_gfx_clock and check for pending force-off Imre Deak
2014-04-23  8:11     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 22/25] drm/i915: vlv: increase timeout when forcing on the GFX clock Imre Deak
2014-04-25 14:04   ` Daniel Vetter
2014-04-14 17:24 ` [PATCH v2 23/25] drm/i915: add various missing GTI/Gunit register definitions Imre Deak
2014-04-24 21:17   ` Rodrigo Vivi
2014-04-24 21:49     ` Imre Deak
2014-04-30 14:32   ` Ville Syrjälä
2014-05-05 11:43     ` Imre Deak
2014-05-05 12:13   ` [PATCH v3 " Imre Deak
2014-05-05 12:21     ` Ville Syrjälä
2014-04-14 17:24 ` [PATCH v2 24/25] drm/i915: propagate the error code from runtime PM callbacks Imre Deak
2014-04-15 13:39   ` [PATCH v3 " Imre Deak
2014-04-30 18:05     ` Ville Syrjälä
2014-04-30 18:53       ` Imre Deak
2014-05-05 12:44         ` Ville Syrjälä
2014-05-05 13:18           ` Imre Deak
2014-04-14 17:24 ` [PATCH v2 25/25] drm/i915: vlv: add runtime PM support Imre Deak
2014-04-16 12:39   ` Ville Syrjälä
2014-04-16 14:53   ` Daniel Vetter
2014-04-16 16:01     ` Imre Deak
2014-04-22 17:28   ` [PATCH v3 " Imre Deak
2014-04-22 22:09     ` [PATCH v4] drm/i915: get a runtime PM ref for the deferred GPU reset work Imre Deak
2014-04-24 21:02       ` Rodrigo Vivi
2014-04-30 17:35     ` [PATCH v3 25/25] drm/i915: vlv: add runtime PM support Ville Syrjälä
2014-05-05  9:33       ` Daniel Vetter
2014-05-05 12:19     ` [PATCH v4 " Imre Deak
2014-04-14 17:41 ` [PATCH v2 26/25] drm/i915: vlv: enable runtime PM Imre Deak
2014-05-06 19:39   ` Daniel Vetter
2014-04-17 11:00 ` [PATCH v2 00/25] vlv: add support for RPM 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.